Настройка мультиязычности на основе Babel

Дорогие друзья! Сегодня мы с вами будем настраивать мультиязычность с помощью компонента Babel на примере одного из наших проектов. Забегая вперед скажу, что данный способ подходит и для организации мультисайтовости в MODx Revo.

Для начала устанавливаем компонент Babel из официального репозитория. При установке он у нас спросит про некоторые параметры, мы оставляем все по умолчанию и устанавливаем.

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

Реализовывать мультиязычность мы с вами будем на примере украинского языка. И для начала создадим контекст с ключом UA, а имя ему дадим “Украинский”. Так как контекст WEB у нас с вами будет по умолчанию русским, его тоже можно отредактировать, дав ему имя – “Русский”.

MODX Revo - настройка мультиязычности

Теперь нам с вами необходимо настроить наши контексты. Для этого кликаем по контексту в дереве ресурсов правой кнопкой мыши и нажимаем “редактировать”. На вкладке “Настройки контекста” нам с вами необходимо переопределить некоторые глобальные настройки системы.

MODX Revo - настройка мультиязычности

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

Настройка

web

ua

base_url

/

/ua/

cultureKey

ru

ua

site_start

1

205

site_url

test4.dart.agency/

test4.dart.agency/ua/

Теперь предлагаю разобраться с параметрами:

  • base_url – базовый URL сайта относительно корня
  • cultureKey – ключ языка
  • site_start – идентификатор главной страницы сайта
  • site_url – URL сайта (если вы используете домены или поддомены, то вместо моих значений у вас должны стоять разные домены, поддомены)

Не забывайте нажать кнопку “сохранить” после выставления всех настроек.

Настройка htaccess.

После того, как мы внесем все параметры в наши контексты нам необходимо настроить так называемы роутинг для инициализации наших контекстов. И первый файл, который мы с вами поправим – это .htaccess. В нем нам необходимо закомментировать стандартный роутинг MODX и сделать такую конфигурацию:

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

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

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

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

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

Обратите внимание, что я оставил закоменченный роутинг MODX, для того, чтобы вам было удобнее ориентироваться.

Если же вы используете домены или поддомены, то вам не нужно использовать настройку .htaccess. Можете сразу переходить к написанию плагина.

Смысл здесь довольно простой: сначала мы настраиваем редиректы с /ua/favicon.ico, /ua/assets/, /ua/images/ на аналогичные папки без виртуального префикса /ua/. Следующий шаг, нам необходимо отследить, какой из контекстов мы будем грузить. Также делаем это на основе виртуального префикса /ua/, передав его в MODX как GET-параметр cultureKey.

Пишем плагин-обработчик

MODX у нас не знает, что появился новый параметр. Поэтому нам необходимо написать плагин gateway на событие onHandleRequest:

<?php
if ($modx->context->key == 'mgr' || !$modx->getOption('friendly_urls') || $modx->event->name != 'OnHandleRequest') {
    return;
}
switch($_REQUEST["cultureKey"]){
    // Украинский
    case 'ua':
        $modx->switchContext('ua');
        break;
        
    // Русский
    default: 
        $modx->switchContext('web');
        break;
}
unset($_GET["cultureKey"]);

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

<?php
/* don't execute if in the Manager */
if ($modx->context->key == 'mgr' || !$modx->getOption('friendly_urls') || $modx->event->name != 'OnHandleRequest') {
    return;
}
 
switch ($_SERVER['HTTP_HOST']) {
   // проверка домена 1
    case 'mastercentr.tmweb.ru':
        // if the http_host is of a specific domain, switch the context
        $modx->switchContext('web');
        break;
   // проверка домена 2
    case 'mso.mastercentr.tmweb.ru':
        // if the http_host is of a specific domain, switch the context
        $modx->switchContext('moika');
        break;
    default:
        // by default, don't do anything
        $modx->switchContext('web');
        break;
}

Отлично! Теперь мы настроили с вами основную часть нашей задачи. Теперь осталось дело за малым – перевести все тексты. Для статичных элементов в нашей верстке нам необходимо создать файлы лексикона MODX.

Переводы в файлах лексиконов.

Надеюсь, вы уже заметили, что у каждого компонента в папке /core/components/ есть папка /lexicon/, в которой хранятся файлы лексиконов. Мы с вами будем работать в папке компонента babel. Так как у нас там не будет находится папки /ua/ ее необходимо будет создать. Также советую туда продублировать файл default.inc.php из папки /ru/.

Для переводов непосредственно на сайте я создаю в обоих папках файл translate.inc.php, где переведем фразу “Заказать звонок” и наименования наших языков. Файл translate.inc.php из папки “ru”:

<?php
$_lang["ledsystems.buttons.callback"] = "Заказать звонок";
/* ----------- Языки -------------- */
$_lang["ledsystems.lang.ru"] = "RU";
$_lang["ledsystems.lang.ua"] = "UA";

Файл translate.inc.php из папки “ua”:

<?php
$_lang["ledsystems.buttons.callback"] = "(укр.) Заказать звонок";
/* ----------- Языки -------------- */
$_lang["ledsystems.lang.ru"] = "(укр.) RU";
$_lang["ledsystems.lang.ua"] = "(укр.) UA";

На языках лучше создавать ключи, у которых значение задано с префиксом, в моем случае “(укр.)”. После полного заполнения файла он передается заказчику, и он уже все переведет с учетом контекста изложения.

Использование лексиконов.

Далее мы можем использовать наши лексиконы в шаблонах, чанках и сниппетах. В шаблонах и чанках мы будем использовать их следующим образом в синтаксисе fenom:

{$_modx->lexicon("ledsystems.buttons.callback")} 
{"ledsystems.buttons.callback" | lexicon}

Единственное, нужно заранее загрузить файлы лексикона выше строкой (обычно я это делаю в самом верху шаблона):

{$_modx->lexicon->load('babel:translate')}

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

[[%ledsystems.buttons.callback? &namespace=`babel` &topic=`translate`]]

В сниппете же вызов будет такой:

<?php
// подгрузка лексиконов
$modx->lexicon->load('babel:translate');
// использование
$data = $modx->lexicon(‘ledsystems.buttons.callback’);

Настройка идентификаторов контейнеров, ресурсов.

Для того, чтобы передавать корректные значения parents и аналогичные, я советую использовать их через настройки контекста. Таким образом, мы сделаем работу с контекстами гибкой и удобной. Использовать настройки контекста мы сможем также, как и настройки системы. В синтаксисе fenom:

{$_modx->runSnippet("pdoMenu",[
	"parents" => $_modx->config.ledsystems_base_catalog,
	"level" => 1
])}

Стандартный синтаксис:

[[pdoMenu?
&parents=`[[++ ledsystems_base_catalog]]`
&level=`1`
]]

Вывод ссылок на языковые версии.

Вывести ссылки на языки мы можем с помощью сниппета babelLinks, таким образом:

{$_modx->runSnippet("!babelLinks", [
	"showCurrent" => 1,
	"includeUnlinked" => 1,
	"tpl" => "babelLinksTpl"
])}

Параметры showCurrent (показывать ссылку на текущую языковую версию) и includeUnlinked (показывать ссылки на не прикрепленные ресурсы) можете использовать по желанию.

Таким вот образом можно настраивать мультисайтовость и мультиязычность с помощью компонента babel. При настройке мультисайтовости, использование babel не обязательно.

Настройка мультиязычности на основе Babel

0 Число голосов: 7
5
5
1
7

Комментарии ()

  1. Андрей 08 августа 2019, 06:37 # 0
    Добрый день Артём. У меня ранее была проблема такого рода — не подтягиваются в переведенный ресурс изображения товаров из минишопа2, и при переводе любого другого ресурса, последнее изображение в контенте тоже не отображается нормально. Это когда сам пытался настроить мультиязычность компонентом Бабель.Не сталкивались случайно с такой проблемой?
    1. Петропавловский Артем 08 августа 2019, 18:12 # 0
      Зачем вам дубли изображений — они ведь одинаковы в разных контекстах? В подобных случаях я использую примерно такой код:
      [[!*context_key:eq=`web`:then=`
      	[[!msGallery? 
              	&tpl=`tpl.msGallery.custom`
      	]]
      `:else=`
      	[[!msGallery?
              	&tpl=`tpl.msGallery.custom`
              	&product=`[[!BabelTranslation? &contextKey=`web` &resourceId=`[[*id]]`]]`
      	]]
      `]]
      
      В данном куске кода мы берем картинки из галереи товара в контексте WEB.
      1. Андрей 13 августа 2019, 19:33(Комментарий был изменён) # 0
        Попробовал. С этим кодом вообще ложится сайт.У меня теперь изображения из карточки товара, не переносятся в переведенный ресурс, надо добавлять их по новой(. Контент, изображения в контенте переносятся, а из минишопа не хотят. Это у всех так, или есть выход?)
        1. Петропавловский Артем 13 августа 2019, 19:41(Комментарий был изменён) # 0
          Этот код на 100% рабочий, взят с рабочего проекта. Можете попробовать у context_key убрать символ "!". И посмотрите логи, какие ошибки там выдает? Ответ: «у меня из-за этого кода все ложится» — может сказать лишь о том, что вы недостаточно корректно адаптировали его.
          Из miniShop2 галерея не будет переноситься, так как это два совсем разных ресурса. Советую вам разобраться в принципе работы компонентов MODX и их структуре (хотя бы поверхностно) — тогда многие вопросы отпадут сами собой.
          1. Андрей 14 августа 2019, 06:10 # 0
            Сорри, неправильно выразился, не «ложится сайт», а на месте картинки выводится Array ( [files] => и куча текста, логов нет. msGallery вроде выводит картинки, но «не совсем адаптированно», по своему).
            Сам понимаю что не хватает базовых знаний, поэтому буду разбираться далее, меня чем и подкупил МОДекс, так это своей простотой и гибкостью. Надеялся что и здесь можно воспользоваться каким нибудь «хитрым кодом».
            Кстати, не разбираясь ни в html, ни в css, за небольшой промежуток времени, только благодаря вашим урокам удалось реализовать полноценный, работающий интернет-магазин, и теперь уже сделать его мультиязычным. Агонь!
            1. Петропавловский Артем 14 августа 2019, 12:36 # 0
              У вас выводится массив значений, так как нет чанков, указанных в параметре 'tpl'
              1. Андрей 14 августа 2019, 16:56 # 0
                Работает! Ура!
                Поменял названия чанков на свои.
                Спасибо огромнейшее!
    2. Андрей 15 августа 2019, 11:37 # 0
      Наверное это уже наглость с моей стороны, но если не спрошу, то не смогу спокойно спать.)
      Существует ли возможность выводить у переведённого ресурса цепочку отзывов или тикетов, которые принадлежат родительскому ресурсу? Или у каждого ресурса исключительно своя цепочка отзывов и никак это не обойти?
      1. Петропавловский Артем 16 августа 2019, 16:17(Комментарий был изменён) # 0
        Решение будет аналогично тому, которое я выше написал. Например, у комментариев Tickets есть параметр &thread, которому можно передать любое значение и формировать свои цепочки. В нашем случае нам еще поможет сниппет BabelTranslation. Только вопрос: зачем? Мы же делаем мультиязычную версию сайта, а вы хотите все комментарии и отзывы на разных языках смешать.
      2. Игорь 2 часа назад # 0
        День добрый.Где может быть косяк?В самом начале установки бабеля.При переходе на главная/ua/ выдает 404 ошибкуХотя страница есть и id указан в контексте верноДаже из админки если кликать «просмотреть» тоже 404

        Наши клиенты

        Многие компании уже доверяют нам. Будьте в их числе!

        Хотите реализовать проект?

        Контакты

        Напишите нам - мы расскажем вам много интересного!


        Пермь, ул. Крупской 34, офис 510