На днях совершил над собой титаническое усилие и добавил-таки своему Netspark.ru английскую версию. Учитывая, что это по сути одностраничник (ну, плюс 404 и «Сайт на обслуживании») — можно было бы тупо скопировать и поменять текстики на английские. Тем более английскую версию поставил на другой домен. Но все же чтобы фронт-энд был одинаковый в обеих версиях — мало ли там, добавить чего, поменять — решил использовать возможности локализации. О чем и расскажу немного.
Локализация в OctoberCMS — примерно такая же, как в Laravel. Есть файлы с локализацией, например lang.php
, из них возвращаются массивы, примерно так:
return [
'messages' => [
'my_message' => 'Hello world',
],
];
После чего используется фильтр trans
в твиге, где обращение к строке происходит как author.pluginname::lang.messages.mymessage
. Author и pluginname — это имя автора и плагина, чтобы было ясно, откуда брать строки. Соответственно, файлы локализации должны жить в плагинах.
Это нормально, если проект не совсем примитивный и в нём есть кастомный плагин для всяких там дополнений и расширений. Но в рассматриваемом случае проект совсем примитивный и кастомных плагинов в нём нет, соответственно, хранить переводные строки негде. В таком случае нужно использовать плагин Translate. Если он установлен, хранить переводы можно прямо в theme.yaml
используемой фронт-энд-темы. Заинклудить отдельный ямл с переводами тоже можно, да.
В файле строки будут храниться вот так:
translate:
en:
nav.portfolio: 'Our works'
nav.services: 'Services'
ru:
nav.portfolio: 'Наши работы'
nav.services: 'Услуги'
А обращаться к строчкам во фронт-энде можно с помощью фильтра твига _
, вот так:
{{ 'nav.portfolio'|_ }}
То есть даже неймспейс никакой соблюдать не надо.
В фильтр перевода можно передавать параметры для подстановки:
{{ 'There are :works works in portfolio'|_({works: 1000}) }}
Естественно, строчку There are :works works in portfolio
тоже можно положить в ямл и заменить дескриптором.
Помимо фильтра перевода _
, есть и фильтр __
, вызывающий transchoice()
и помогающий в правильном склонении множественных чисел.
Чтобы строки из yaml-файла попали в систему, нужно их сначала обнаружить плагином Translate. Для этого со страницы переводов нужно запустить сканирование сообщений и затем почистить кэш.
К слову, если пользоваться плагином Translate, хранить строки в yaml-файле вообще необязательно. Если подать любую строку во фронт-энде на фильтр перевода, она может быть отсканирована и переведена через админку плагина. Примерно как функция t()
в Друпале — засунул в неё что-нибудь, и это что-нибудь стало можно перевести. Но что еще интересно, в отличие от Друпала, где системный язык всегда английский и мы переводим с него, в OctoberCMS с плагином Translate дефолтный язык — действительно дефолтный. То есть мы можем сделать сайт на русском, сделать русский дефолтным, и переводить строки с русского на французский, или китайский, вообще без какого-либо упоминания английского.
Что еще можно сказать. Как видно из скриншота выше, плагин позволяет экспортировать переводы в и импортировать из csv-файлов (аналогично импорту-экспорту моделей).
Напоследок приведу пример определения текущей локали в системе. Я просто добавил обработчик onStart()
в лейаут, и страницам, использующим этот лейаут, стали доступны переменные switchLocaleName, switchLocaleFlag и switchLocaleLink.
use RainLab\Translate\Classes\Translator;
protected $translator;
function onStart() {
$this->translator = Translator::instance();
$switchLocale = ($this->translator->getLocale() == 'ru') ? 'en' : 'ru';
$this['switchLocaleName'] = ($switchLocale == 'ru') ? 'Русская версия' : 'English version';
$this['switchLocaleFlag'] = 'assets/img/flags/' . $switchLocale . '.svg';
$this['switchLocaleLink'] = ($switchLocale == 'ru') ? 'https://netspark.ru' : 'https://netspark.pro';
}
Лично мне это пригодилось, чтобы построить свой переключатель языков, который направляет на другой домен, вместо изменения языка в URL.