Как настроить Babel, чтобы не было мучительно больно

Один день проведённый на modx.pro показал, что у людей очень много проблем с дополнением Babel. Люди боятся его за сложность настройки. На самом деле всё не так страшно. Эта статья, надеюсь, поможет при создании мультиязычных сайтов. Целью этой статьи не является разбор, чем одно дополнение лучше другого, это именно инструкция: как сделать.
Итак, у вас есть или разрабатывается сайт, который должен стать мультиязычным. С чего начать? Самый важный момент – проверить, что у вас в системных настройках в разделе «Дружественные URL» включены «friendly_urls» (Использовать дружественные URL). Затем создаем дополнительные контексты (то же меню раздел «Контексты»). Например, были у нас web и mgr (да, менеджер тоже находится в отдельном контексте), в дополнение к нему создаём контексты с ключами en и de. Ключи после создания (обычным способом) поменять нельзя, поэтому вызывайте всех святых, чтобы не ошибиться. Во время создания контекстам лучше сразу дать красивые имена, например, English и German (имя можно исправить позже). Контекст web также лучше переименовать для удобства.

Теперь можно скачивать дополнение Babel, как обычно, меню «Приложения» — «Установщик» При установке он сразу подхватит ваши текущие контексты, при желании их можно подправить (Context Keys). Если по какой-то причине позже появится дополнительный контекст, не беда, в «Системным настройках», в разделе Babel можно внести изменения. Иногда случается, что после правок системных настроек Вавилон не отображает значок перевода на фронтенде, хотя у вас связка ресурсов есть. Это из-за сессии. Поэтому после изменения настроек принудительно завершаем все сеансы.
Теперь переходим к редактированию контекстов. Правой кнопкой мыши жмём над нужным нам контекстом, например, Russian, выбираем «Редактировать контекст» и создаём следующие параметры (порядок не важен):
  • Ключ: «base_url», значение: "/ru/".
  • Ключ: «cultureKey», значение: «ru»
  • Ключ: «site_start», значение: «1» (ID номер первой страницы контекста)
  • Ключ: «site_url», значение: «example.ru/ru/» (меняем на свой домен, если надо, указываем протокол https).

Там же переключаемся на «Права доступа» и проверяем есть ли для группы anonymous политика доступа «Load Only» с рангом 9999. Если нет, то создаем.
Далее, все остальные контексты редактируем по такому же принципу.
Следующий шаг – создание плагина, который будет отвечать за переключение контекстов. Идём в «Элементы» и создаём новый плагин, для удобства обзовём его «OnHandleRequest» и включаем для него в разделе «Системные события» OnHandleRequest. Код плагина:
<?php
if($modx->context->get('key') != "mgr"){
    /* grab the current langauge from the cultureKey request var */
    switch ($_REQUEST['cultureKey']) {
        case 'de': 
            $modx->switchContext('de'); 
            setlocale(LC_ALL, 'de_DE.UTF8');
            break;
        case 'en': 
            $modx->switchContext('en'); 
	setlocale(LC_ALL, 'en_US.UTF8');
            break;
        default:
            // Set the default language/context here
            $modx->switchContext('web');
            setlocale(LC_ALL, 'ru_RU.UTF8');
             break;
    }
	unset($_GET['cultureKey']);
}
Кроме переключения на нужный контекст мы также меняем локаль для системы. Теперь PHP скрипты будут разговаривать на правильном языке для каждого контекста. Очень удобно.
Осталось совсем чуть-чуть, поправить .htaccess и в путь. Это при условии, что у вас стоит Апач. Если нет, то переделываете правила под свою систему. Начальный htaccess есть в инсталляции MODX’a, я объясню, что надо поменять. Итак, старый кусок кода:
# The Friendly URLs part
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?q=$1 [L,QSA]
Меняем на это:
# Force language when requesting the root (/) . Смена языка при запросе корня сайта
RewriteCond %{HTTP:Accept-Language} ^ru [NC]
RewriteRule ^$ /ru/ [R=301,L]

RewriteCond %{HTTP:Accept-Language} !^ru [NC]
RewriteRule ^$ /ru/ [R=301,L]

# Языки поменяли, теперь сменим виртуальные пути на реальные
 
# redirect all requests to /en/favicon.ico  to /favicon.ico
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(en|ru|de)/favicon.ico$ favicon.ico [L,QSA]
 
# redirect all requests to /en/assets* to /assets*
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(en|ru|de)/assets(.*)$ assets$2 [L,QSA]
 
# redirect all other requests to /en/* 
# to index.php and set the cultureKey parameter
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(en|ru|de)?/?(.*)$ index.php?cultureKey=$1&q=$2 [L,QSA]
Да, не забываем, что в темплейтах всех ваших страниц должен быть указан :
<head>
    ...
    <base href="[[++site_url]]" />
    ...
</head>
Сайт уже должен работать и адресная строка, при запросе корня сайта (example.ru) должна поменяться на example.ru/ru/. Осталось настроить меню языков. Самый простой вариант, чтобы работало и понятно было:
<ul>
  [[BabelLinks? &tpl=` BabelLinksTpl`]]
</ul>
BabelLinksTpl:
<li><a href="[[+url]]" class="[[+cultureKey]][[+active:notempty=` [[+active]]`]]">[[+cultureKey]]</a></li>
Теперь на главной странице будет так:
<ul>
<li><a href="http://example.ru/en/" class="en">en</a></li>
<li><a href="http://example.ru/de/" class="de">de</a></li>
</ul>
Чтобы было видно текущий язык, надо вызов оформить так:
[[BabelLinks? &tpl=` BabelLinksTpl` &showCurrent=`1`]]
Теперь можно переводить материалы.

На фронтенде, на странице у которой есть перевод появится меню выбора языка. Причем вести ссылка будет на конкретный документ, что связан с оригиналом.
Какие проблемы могут возникнуть во время использования? Поскольку у нас URL стал виртуальным, то могут возникнуть проблемы со ссылками, которые генерятся другими дополнениями. Например, Gallery или AjaxForm. В первом случае нам надо изменить настройки «Источников файлов» (меню «Медиа»). Заходим, как обычно жмём праву кнопку над источником «Filesystem» и выбираем «Редактировать». Меняем два параметра:
  • baseUrl изменить на «/»;
  • baseUrlRelative изменить на «Нет»;

А в случае с AjaxForm в «Системных настройках», раздел «Сессии и куки», параметр «session_cookie_path» поменять на «/».

Что еще почитать? Обязательно официальную документацию на английском, надеюсь теперь она вам будет понятна:
MODX docs – Babel
а это дамашняя страница Babel'a, отсюда я черпал вдохновение:
SEO Friendly Multilingual Websites with MODx and Babel
Ну и конечно же, при создании статьи не обошлось без «Stack Overflow»
Янис
12 сентября 2018, 10:03
18
453
+12

Комментарии: 10

SEQUEL.ONE
12 сентября 2018, 11:58
+1
Спасибо за труд. Для новичков самое то. Не хватает только примеров как в шаблонах например переводить pagetitle и другие плейсхолдеры, там же можно в том числе через модификаторы. Вот на Fenom бы примеры написать, было бы супер.
    Янис
    12 сентября 2018, 12:15
    +1
    Принцип работы с Вавилоном в том и заключается, что вы получаете новый документ в другом контексте и все поля можно заполнять на другом языке. Если поля были чем-то заполнены до перевода, то данные автоматом сохранятся в новом документе. Нет нужды что-то править в темплейте. Там вообще голого текста быть не должно, т.е. темпплейт может выглядеть как-то так:
    ...
    <main>
    <h1>[[*pagetitle]]</h1>
    <p>[[*longtitle]]</p>
    [[*content]]
    <a href="[[~[[*link_url]]]]">[[*link_text]]</a> <!-- кастомные ТВшки -->
    </main>
    ...
      SEQUEL.ONE
      12 сентября 2018, 12:37
      0
      Неудачный коммент, сейчас посмотрел как настроенно у меня. Вот скажем нужно в подвале копирайт перевести на несколько языков статично. Вот так мы будем переводить статично:

      [[++cultureKey:is=`ru`:then=`<p>Все права защищены.</p>`]]
      								    [[++cultureKey:is=`en`:then=`<p>All rights reserved.</p>`]]
      								    [[++cultureKey:is=`de`:then=`
          								    [[pdoMenu?
          								        &parents=`113`
          								        &outerClass=`about`
          								        &firstClass=``
          								    ]]
      								    `]]
      Как мы видим в немецкой версии сайта выводим только ссылки из родителя, т.к. в Германии все сайты должны иметь набор из 3ёх страниц Impressum, AGB и Datenschutzt. А вот ещё пример вывода pdoPage с Babel:

      {'!pdoMenu' | snippet : [
                                          'parents' => '4,85,86', 
                                          'level' => 1,
                                          'displayStart' => 1,
                                          'firstClass' => '',
                                          'tplStart' => '@INLINE <li class="first"><a href="[[+link]]" [[+attributes]]>[[+menutitle]]</a></li>[[+wrapper]]',
                                          'context' => $_modx->context.key
                                      ]}
      В parents указываем родителей желаемых для вывода разделов из разных контекстов.

      P.S. Я вот про такие примеры писал)
        Баха Волков
        12 сентября 2018, 12:54
        0
        … сейчас посмотрел как настроенно у меня. Вот скажем нужно в подвале копирайт перевести на несколько языков статично. Вот так мы будем переводить статично:
        Вот про это я и говорю Янис, тут ведь можно было использовать запись собственного словаря и не проверять все это. Ну в данном случае только проверить если контекст de то вывести меню

        А вот ещё пример вывода pdoPage с Babel:
        Тут тоже согласен (хоть и напрямую к Babel не относиться) но все же. Тут же можно было выйти из ситуации так: создать настройку для контекстов в которой хранились бы нужные id.

        Пример:
        Создать настройку context_menu_id
        Задать его контекстам, web => 4, en => 85, de => 86

        И уже нужно было бы выводить меню так:

        {'!pdoMenu' | snippet : [
            'parents' => $_modx->context.context_menu_id,
            'level' => 1,
             'displayStart' => 1,
            'firstClass' => '',
            'tplStart' => '@INLINE <li class="first"><a href="[[+link]]" [[+attributes]]>[[+menutitle]]</a></li>[[+wrapper]]',
        'context' => $_modx->context.key
        ]}
        Янис
        12 сентября 2018, 12:55
        0
        Всё просто.
        В первом случае, если менеджеру запрещено редактировать эти записи, используем словарь MODX'a:
        <p>[%copy_info]]</p>
        Если разрешено, то на первой странице сайта создаём ТВ'шки со всякой служебной инфой и потом выводим нужные поля, например через fastField:
        <p>[[#[[++site_start]].copy_info]]</p>
        А во втором случае (относится ко всем сниппетам из pdoTools) можно ограничивать выборку по контекстам через опцию &context. Получить текущий контекст через Fenom вообще плёвое дело:
        {$_modx->context.key}
          Янис
          12 сентября 2018, 13:18
          0
          Оу, я невнимательно прочитал вторую часть вашего коммента, у вас там всё уже правильно расписано. Смотрю ещё одной статьёй, не отделаться. На самом деле – это огромный пласт «Как сделать мультиязычный сайт?» Тема для следующей статьи уже есть.
Баха Волков
12 сентября 2018, 12:18
0
Отличная работа. Советую добавить работу с собственным словарем, на странице кроме данных которые вводятся есть еще много чего, что разработчик при разработке обычного (не мультиязычного) сайта прописывает прямо в тело шаблона.

Примеров много:

  • Плейсхолдеры полей ввода
  • Заголовки блоков
  • Тексты кнопок
  • И многое другое
Для таких задач я создаю отдельный словарь, в MODX это удобно. Но вдруг люди/читатели не знают как это делать. Пример из жизни: Попался сайт интернет магазин который я так и не вернул в жизнь, там разработчик в каждом месте где нужно было вывести текст проверял контекст и выводил нужный текст или вообще чанки нагородил под каждый язык.
    Янис
    12 сентября 2018, 12:31
    0
    Это уже отдельная инструкция по работе со словорями :) К работе с Вавилоном она не отностится. Как я уже писал, в темплейте текста быть не должно, также как и в сниппете не должно быть эха. Конечно же, когда я начинал работать на MODX'е, у меня было и то и другое, но с опытом и чтением форумов приходит понятие – как можно сделать красиво и универсально.
      Баха Волков
      12 сентября 2018, 12:36
      0
      Согласен!) Тогда с тебя не только этот урок, а цикл уроков «How сделать multiязычный webсайт» где описать все это дело)
        Янис
        12 сентября 2018, 12:58
        +2
        Да, вполне, но уже на следующей неделе. Деньги зарабатывать тоже надо :)