pbStudio: Подключаем мультиязычность в PageBlocks
Введение
PageBlocks поддерживает мультиязычность без контекстов. Достаточно указать языки, задать поля для перевода и, при необходимости, подключить автоперевод — остальное сделает PageBlocks.
Навигация по урокам:
- pbStudio: Создаём сайт с PageBlocks – настройка и главная страница
- pbStudio: Меню и страница «О нас»
- pbStudio: Чистый контроллер или FetchIt — два способа обработки форм
- pbStudio: Портфолио, Услуги и Контакты
- pbStudio: Подключаем мультиязычность в PageBlocks
Шаг 1. Настройка мультиязычности
Чтобы включить поддержку языков, измените следующие системные настройки:
- pageblocks_context_aware = Да
- pageblocks_contexts = [{«key»:«web»,«value»:«Russian»}, {«key»:«en»,«value»:«English»}]
В MODX 3 доступна удобная таблица редактирования языков.
Также нужно указать, какие поля ресурса нужно переводить:
- pageblocks_translate_resource_fields = pagetitle,longtitle,description,introtext,content,menutitle
Шаг 2. Настройка автоматического перевода (опционально)
Поддерживаются два переводчика:
ChatGPT
- pageblocks_translator = ChatGPT
- pageblocks_chatgpt_apikey = ваш API-ключ
DeepL
- pageblocks_translator = DeepL
- pageblocks_deepl_account = Free или Pro
- pageblocks_deepl_apikey = ваш API-ключ
Шаг 3. Вывод переключателя языков на сайте
Добавьте в header.tpl следующий код:
<ul class="navbar-nav ms-auto d-flex align-items-center list-unstyled mb-0">
{'!pbLang' | snippet: [
'tpl' => '@INLINE <li class="nav-item">
<a class="nav-link {$activeCls}" lang="{$key}" href="{$url}">{$value}</a>
</li>',
'showCurrent' => 1
]}
</ul>
Если у вас не используется маршрутизация, шаги 4 и 5 можно пропустить.
Шаг 4. Настройка маршрутов (опционально)
При переходе на URL вида /en/ без правильного маршрута вы получите ошибку 404. Чтобы это исправить, добавьте маршрут в web.php:
Route::get('/{context}/{alias?}', [ResourceController::class, 'context'])
->where('context', '[a-z]{2}');
->where('context', '[a-z]{2}') — указываем, что контекст должен состоять из двух букв.Важно: разместите этот маршрут до основного, чтобы сначала обрабатывался контекст:
Route::get('/{alias?}', [ResourceController::class, 'index']);
Шаг 5. Контроллер ResourceController (опционально)
Добавим метод context в контроллер и сразу сделаем рефакторинг, чтобы убрать дублирования кода:
class ResourceController extends Controller
{
public $classKey = \modResource::class;
public function index(string $alias = '')
{
$resource = $this->getResource($alias);
$this->modx->resource = updateResource($resource);
$this->modx->config['site_url'] = $this->modx->getOption('site_url');
$this->modx->config['cultureKey'] = $this->modx->getOption('cultureKey');
$this->modx->context->set('key', $this->modx->getOption('default_context'));
return response()->view('templates/base');
}
public function context(string $context, string $alias = '')
{
$resource = $this->getResource($alias);
$this->modx->resource = updateResource($resource, $context);
$this->modx->config['site_url'] = $this->modx->getOption('site_url') . "$context/";
$this->modx->config['cultureKey'] = $context;
$this->modx->context->set('key', $context);
return response()->view('templates/base');
}
private function getResource(string $alias = '')
{
$where = [
'published' => 1,
'deleted' => 0,
];
if (empty($alias)) {
$where['id'] = $this->modx->getOption('site_start', null, 1, true);
} else {
$where['alias'] = $alias;
}
if (!$resource = $this->modx->getObject($this->classKey, $where)) {
abort();
}
return $resource;
}
}
Теперь маршрут /en/ работает и открывает главную страницу, но она пустая — для этого контекста ещё не добавлены блоки. Давайте это исправим.
Шаг 6. Работа с контентом
После включения pageblocks_context_aware, в интерфейсе блоков и таблиц появится выпадающий список контекстов:

Теперь можно:
- Копировать блоки с одного языка на другой
- Переводить их вручную или через ИИ

Шаг 7. Перевод ресурса
Переходим во вкладку «Переводы», добавляем нужные языки и, при необходимости, активируем автоперевод полей:

Заключение
Готово! PageBlocks берёт на себя всю сложную работу по мультиязычности:
- Учитывает текущий язык во всех сниппетах
- Сниппеты pbMenu и pbResources возвращают переведённые ресурсы
- Вам остаётся лишь настроить языки и перевести контент
Поблагодарить автора
Отправить деньги
Комментарии: 12
Доброй ночи! Не нашел в документации снипета sitemap, есть какие-то особенности при мультиязычности?
- redirect — если мы переходим на страницу без перевода, то срабатывает редирект на главную, и такие страницы исключаются из всех сниппетов.
- 404 — то же самое, что и redirect, но показываем 404 страницу вместо главной
- default — страницы без перевода учитываются в сниппетах, (pbLang, pbMenu), но не в pbSitemap. При переходе на такую страницу показываем страницу без перевода.
Привет.
Сниппет для sitemap будет добавлен на этой неделе.
Сниппет для sitemap будет добавлен на этой неделе.
есть какие-то особенности при мультиязычности?Например? Там все очень просто, но если возникнут сложности — я помогу.
Важно решить как управлять страницами при мультиязычности:
— если нет перевода, то не отображать страницу
- если нет перевода, то показывать 404
- если нет перевода, то показывать «основную» локализацию
Как правило, клиенты просят исключить (не отображать) не переведенные страницы. Эта логика должна учитываться, в том числе и при формировании sitemap.
Также для мультиязычности необходим сниппет Canonical — sitemap, сanonical и переключатель языков (pbLang) базовые снипеты для мультиязычного сайта
Желающие «переехать» на ваш компонент также столкнуться с еще одной проблемой — у многих сайты на субдоменах или того хуже — на разных доменах.
PS Посмотрите в сторону Polylang, отличный компонент, но не поддерживает MODX 3.
— если нет перевода, то не отображать страницу
- если нет перевода, то показывать 404
- если нет перевода, то показывать «основную» локализацию
Как правило, клиенты просят исключить (не отображать) не переведенные страницы. Эта логика должна учитываться, в том числе и при формировании sitemap.
Также для мультиязычности необходим сниппет Canonical — sitemap, сanonical и переключатель языков (pbLang) базовые снипеты для мультиязычного сайта
Желающие «переехать» на ваш компонент также столкнуться с еще одной проблемой — у многих сайты на субдоменах или того хуже — на разных доменах.
PS Посмотрите в сторону Polylang, отличный компонент, но не поддерживает MODX 3.
Важно решить как управлять страницами при мультиязычности:Сейчас, если перевода нет — показывается страница в основной локали.
Остальные варианты пока не реализованы.
pbLang — есть
pbSitemap — есть
pbCanonical — будет
Желающие «переехать» на ваш компонент также столкнуться с еще одной проблемой — у многих сайты на субдоменах или того хуже — на разных доменах.Если используется роутинг — проблем вообще нет. А если по старинки, то да, нужно доработать.
Важно решить как управлять страницами при мультиязычности:А что значит не отображать страницу? Показываем главную?
— если нет перевода, то не отображать страницу
Вся логика в том, что локализованные версии сайта по своей сути отдельные сайты как для поисковых систем, так и для посетителей.
Если страница не переведена, то она должна быть исключена из локализации — для поисковых систем это не релевантная страница в данной локализации, а для посетителя — не user friendly.
В сниппетах Polylang для этого применяется параметр onlyWithLocalization:
Если страница не переведена, то она должна быть исключена из локализации — для поисковых систем это не релевантная страница в данной локализации, а для посетителя — не user friendly.
В сниппетах Polylang для этого применяется параметр onlyWithLocalization:
Исключение из результатов сниппетов ресурсов без локализации
Если необходимо исключить из результатов работы сниппетов ресурсы которые не содержат для текущего языка локализаций, то добавьте в вызов сниппета параметр onlyWithLocalization с значением 1.
Сниппеты исключают страницу, если нет перевода, даже если показываем 404 страницу.
Поэтому у меня работает так:
За это будет отвечать системная настройка pageblocks_context_fallback
Поэтому у меня работает так:
За это будет отвечать системная настройка pageblocks_context_fallback
Так же есть вопрос:
При создании например полей в админ панели,
Например если на сайте два языка, русский и английски, то для русской версии отображался бы «Заголовок» а для англ «Title».
При создании например полей в админ панели,
Field::make('title')->label('Заголовок')
Возможно ли, что бы данный заголовок тоже можно было менять, в зависимости от выбранного языка для перевода? Например если на сайте два языка, русский и английски, то для русской версии отображался бы «Заголовок» а для англ «Title».
Пока невозможно, но я обязательно добавлю это.
Было бы супер.
А у вас есть в планах сделать что-то похожее на «Client Config» page?
Ну то-есть будет какая то страница, где люди смогут создавать глобальные поля, вроде номера телефона или email. Мне кажется это был бы тоже приятное дополнение.
А у вас есть в планах сделать что-то похожее на «Client Config» page?
Ну то-есть будет какая то страница, где люди смогут создавать глобальные поля, вроде номера телефона или email. Мне кажется это был бы тоже приятное дополнение.
А чем Client Config не устраивает?
Все устраивает.
Просто подумал что скачал один модуль, а там уже это тоже есть.
И не надо ставить еще один модуль. ))
Просто подумал что скачал один модуль, а там уже это тоже есть.
И не надо ставить еще один модуль. ))
Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.