Настройка мультиязычности в MODX Revo (Контексты + Babel)

Подключить мультиязычность на MODX Revolution не сложно, но нужен четкий план действий. Для лучшего понимания рассмотрим процедуру подключения на примере.

Допустим мы хотим подключить два дополнительных языка для сайте, то есть мы хотим получить следующий результат:

  • Русская версия сайта - http://site.ru/
  • Английская версия - http://site.ru/en/

Навигация по статье:


Языков можно подключить неограниченно, для примера остановимся на 1-ом дополнительном языке. Также нам нужен удобный интерфейс создания ресурсов в панели с учетом мультиязычности: связка страниц разных языков.

Для реализации данной задачи нам понадобится:

  • MODX Revolution (2.0 и старше), само собой
  • Доступ до .htaccess (или ht.access)
  • Плагин Babel (2.2 и старше)

Настройка .htaccess

В корне сайта должен быть файл .htaccess (иногда файлы скрыты от просмотра, см. в настройках вашего FTP-клиента) или ht.access (его переименовываем в .htaccess).

В файле .htaccess проверяем правильность 'RewriteBase' и включен ли modRewrite ('RewriteEngine On').

ВАЖНО! .htaccess - файл дополнительной конфигурации веб-сервера Apache, если у вас другой сервер и без Apache конфигураций, то директивы в .htaccess у вас работать не будут. Но практически все современные сервера используют связку Apache + NGINX, т. е. работать .htaccess в скорее всего будет. Работает ли modRewrite можно проверить путем добавления обычных редиректов в .htaccess или путем настройки SEF-ссылок (если они работают, то .htaccess активен).

Если сайт установлен в корневой каталог используемого домена, то в .htaccess пишем:

RewriteEngine On
RewriteBase /

Если сайт установлен не в корневой каталог, то пишем:

RewriteEngine On
RewriteBase /каталог/

Далее добавляем в наш .htaccess после наших редиректов, в самом конце, следующее (см. изображение ниже):

RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(ru|en)/favicon.ico$ favicon.ico [L,QSA]

RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(ru|en)/assets(.*)$ assets$2 [L,QSA]

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(ru|en)?/?(.*)$ index.php?cultureKey=$1&q=$2 [L,QSA]

Где (ru|en) должны совпадать с: ru для корневой директории http://site.ru/ , а en - с http://site.ru/en/ (прописываются в настройках контекста ниже).

ВАЖНО! Директивы '# The Friendly URLs part' УДАЛЯЕМ или комментируем через # (по умолчанию включены), получится так (см. изображение ниже):

# The Friendly URLs part
# RewriteCond %{REQUEST_FILENAME} !-f
# RewriteCond %{REQUEST_FILENAME} !-d
# RewriteRule ^(.*)$ index.php?q=$1 [L,QSA]

Настройка контекстов

В админке MODX нам нужно создать контекст для нового языка. Для этого перейдите по: "Система" -> "Контексты" и нажимаем "Создать новый".

Далее в качестве "Ключа контекста" вводим, например, для английского - "eng".

ВАЖНО! Эти ключи в дальнейшем будут использованные в плагине переключения контекстов.

Далее правый клик мыши по новому контексту и выбираем "Редактировать". Переходим по табу "Настройки контекста" и нажимаем "Создать новый".

Для каждого языка нам нужно добавить следующие настройки.

Существующий контекст (ключ "web"): Новый контекст (ключ "eng"):

Base URL

  • Ключ: base_url (!именно base_url, MODX предлагает не тот ключ)
  • Имя: Base URL
  • Запись словаря для раздела: language
  • Значение: /

Base URL

  • Ключ: base_url
  • Имя: Base URL
  • Запись словаря для раздела: language
  • Значение: /en/

Culture key ([[++cultureKey]]).
Не путать с "Ключом контекста" ([[*context_key]])

  • Ключ: cultureKey
  • Имя: Culture key
  • Запись словаря для раздела: language
  • Значение: ru

Culture key

  • Ключ: cultureKey
  • Имя: Culture key
  • Запись словаря для раздела: language
  • Значение: en

Site start

  • Ключ: site_start
  • Имя: Site start
  • Запись словаря для раздела: language
  • Значение: 1

Site start

  • Ключ: site_start
  • Имя: Site start
  • Запись словаря для раздела: language
  • Значение: id страницы для Главной в английской версии.
    Все id создаем через Babel, об этом ниже.

Site name

  • Ключ: site_name
  • Имя: Site name
  • Запись словаря для раздела: language
  • Значение: Название сайта

Site name

  • Ключ: site_name
  • Имя: Site name
  • Запись словаря для раздела: language
  • Значение: Название сайта на английском языке

Site URL

  • Ключ: site_url
  • Имя: Site URL
  • Запись словаря для раздела: language
  • Значение: / (или http://site.ru/)

Site URL

  • Ключ: site_url
  • Имя: Site URL
  • Запись словаря для раздела: language
  • Значение: /en/ (или http://site.ru/en/)

Error page

  • Ключ: error_page
  • Имя: 404 page
  • Запись словаря для раздела: language
  • Значение: id страницы для 404 ошибки

Error page

  • Ключ: error_page
  • Имя: 404 page
  • Запись словаря для раздела: language
  • Значение: id страницы для 404 ошибки в английской версии.
    Все id создаем через Babel, об этом ниже.

Locale, используется для форматирования даты в текстовом виде

  • Ключ: locale
  • Имя: Setting locale
  • Запись словаря для раздела: language
  • Значение: ru_RU.UTF8

Locale

  • Ключ: locale
  • Имя: Setting locale
  • Запись словаря для раздела: language
  • Значение: en_US.UTF8

Для контекста "web" все настройки уже есть в "Системных настройках", но при этом для каждого контекста их можно переопределить.

Создание плагина "switchContext"

Для того чтобы наша мультиязычность работала нам нужен плагин для связки языка с контекстом.

В панели управления переходим по табу "Элементы" и нажимаем на иконку "Новый плагин".

В поле имя пишем switchContext и помещаем следующий код:

<?php
/* Запускаем плагин только на фронтенде и с включенными sef-url */
if ($modx->context->key == 'mgr' || !$modx->getOption('friendly_urls') || $modx->event->name != 'OnHandleRequest') {return;}

/* Определяем текущий язык в cultureKey */
switch ($_REQUEST['cultureKey']) {
    /* Переключаем контекст */
    case 'en':
    $modx->switchContext('eng');
    break;

    /* Добавляем дополнительные языки в плагин, если нужно
    case 'de':
    $modx->switchContext('dtsch');
    break;
    */

    /* Устанавливаем контекст по умолчанию */
    default:
    $modx->switchContext('web');
    break;
}

/* Очищаем GET-параметр чтобы не допустить появлении ссылки вида cultureKey=xy при генерации URL других компонентов */
unset($_GET['cultureKey']);
}
?>

Далее переходим по вкладке "Системные события", включаем OnHandleRequest и сохраняем.

Установка Babel

Устанавливаем пакет Babel, в панели управления переходим по "Система" -> "Управление пакетами" и нажимаем "Загрузить дополнения" и находим там Babel, загружаем и устанавливаем пакет.

Проходим все необходимые условия установки пока не увидите "Настройки установки". Здесь уже должны быть контексты которые мы создали (по примеру это: web, eng; если поле пустое, то можно вписать ключи контекстов руками), другие настройки оставляем без изменений.

Создание мультиязычного контента

Как добавлять страницы сайта на других языках?

В панели управления сайта, во вкладке "Ресурсы", мы видим наши контексты (выводятся имена контекстов, которые вы заполнили при создании/редактировании контекста). Ресурсы каждого из контекстов отвечают за ресурсы языковых версий сайта.

Но как нам знать какой ресурс за какую страницу отвечает, т.е. как же связать страницы разных языков между собой?

Здесь нам и поможет Babel. При создании или редактировании ресурса в правом верхнем углу появятся кнопки, отвечающие за языковые версии ("Создать перевод", "Связать перевод"). Через эти кнопки создаются и связываются ресурсы в другом контексте (языковой версии).

Полученные id ресурсов и используем в настройках контекстов для страниц Главная и 404 (см. таблицу с настройками выше).

Переключатель языков на сайте.

Наконец нам нужны кнопки (ссылки) переключения языковых версий на сайте (не забудьте опубликовать нужные ресурсы). Для этого в любом месте где нужно вывести переключатель (шаблон, чанк) пишем следующее:

<ul>
[[BabelLinks?
&showCurrent=`1`
]]
</ul>

Все параметры BabelLinks можно посмотреть тут - https://docs.modx.com/extras/revo/babel/babel.babellinks.

Очень редко бывает, что BabelLinks не выводит связанные страницы, хотя все верно настроено и опубликовано. Для этого проверьте создан ли TV связи ссылок - babelLanguageLinks, если TV нет, то создайте его с именем babelLanguageLinks (и названием Babel Translation Links) и укажите имя TV для Babel в "Системных настройках", а так же проверьте указаны ли ключи контекстов в тех же настройках. Или попробуйте переустановить Babel.

Вывод статического содержимого в зависимости от языка

Существует несколько методов вывода разного статического содержания (заголовки, адреса и копирайт в футере, кнопки и пр.) в зависимости от языка:

1. Создать для каждого чанка копии с нужным языком, например, [[$footer_ru]], [[$footer_en]], а в шаблонах вызывать в виде [[$footer_[[++cultureKey]]]] (при генерации страницы MODX подставит нужное значение [[++cultureKey]] и выведет содержание чанка для активного языка).

2. Можно проверять контекст и выводить нужное содержимое через фильтры ввода-вывода.

Условие вывода лучше прописывать именно через [[*context_key]], а, к примеру, не через [[++cultureKey]] т. к. Ключ контекста заполняется один раз и изменить его нельзя, а настройки же контекста можно менять. Например, условие будет таким:

[[*context_key:is=`web`:then=`г. Москва, ул. Льва Толстого, д. 1`:else=`Moscow, Leo Tolstoy st. 1`]]

С другой стороны, с использованием [[++cultureKey]], условие будет грамотнее читаться:

[[++cultureKey:is=`ru`:then=`г. Москва, ул. Льва Толстого, д. 1`:else=`Moscow, Leo Tolstoy st. 1`]]

В общем, выбор, как всегда, за вами :)

Автоматически определяем id переведенных страниц

Часто в статических элементах сайта прописаны ссылки на ресурсы обычной версии, и, соответственно, нужно прописать и id другой языковой версии сайта, но как их узнать, не выискивая перевода каждой страницы сайта (а если каталог огромный, то можно засеть на долгое время)?

В этом нам поможет сниппет BabelTranslation. Подробнее можно посмотреть тут - BabelTranslation. BabelTranslation выводит связанный id переведенной страницы нужного контекста:

[[BabelTranslation? &resourceId=`6` &contextKey=`eng`]]

Выведет в шаблоне связанный id в контексте eng для страницы с id=6 активного контекста (в нашем случае web).

В совокупности с условиями ввода-вывода, конструкцию можно сделать грамотнее:

[[*context_key:is=`web`:then=`6`:else=`[[BabelTranslation:default=`6`? &resourceId=`6` &contextKey=`eng`]]`]]

Тут мы выводим id=6, если контекст web и выводим связанный id для контекста eng через BabelTranslation, если же связанного id нет, то выведет id=6 (исходя из :default).

Конструкцию можно сделать еще грамотнее и проще, для этого всю конструкцию сохраняем в чанк [[$eng_id]] и задаем параметр [[+ru_id]] в чанке (чанк и параметр можно назвать как угодно). Код чанка:

[[*context_key:is=`web`:then=`[[+ru_id]]`:else=`[[BabelTranslation:default=`[[+ru_id]]`? &resourceId=`[[+ru_id]]` &contextKey=`eng`]]`]]

А так, например, выводим id для ссылки через наш чанк с параметром (если не найдет переведенную страницу, откроется исходная страница):

<a href="[[~[[$eng_id?ru_id=`6`]]]]">Ссылка на страницу</a>

Источники файлов в TV для нескольких контекстов

Если у вас для каких-либо TV настроены источники файлов, то после создания нового контекста нужно будет добавить источники файлов в настройках этих TV к новым контекстам.

Символические ссылки для контекстов

Бывает так, что нужно сделать не разные языковые версии сайта, а разные сайты для городов, однако у таких сайтов много будет дублирующих страниц (например, страница Контактов), чтобы этого не возникало, можно пользоваться "символическими ссылками", они позволяют использовать контент указанной страницы, но при этом можно задать свои заголовки, шаблон, url и поля, т.е. править текст можно будет в одном месте.

По умолчанию между контекстами нельзя ставить символические ссылки, чтобы это включить - переходим в админке сайта "Системные настройки" выбираем в фильтре "Система и сервер" и ставим у "Разрешить перенаправление через контексты" - "Да"

Вот, собственно, и все, да здравствует мультиязычность в MODX Revolution :)


На поддержку блога

Комментарии к посту (10)