Локализация

За мультиязычность интерфейса отвечает объект класса /Aleksmir/Core/Lang/Lang . Перевод фраз в шаблоне производится через вспомогательную функцию lang().

Как определяется язык интерфейса

Язык интерфейса определяется по окончанию строки URL. К примеру, если URL выглядит так:

https://core.aleksmir.ru/core/doc/00/en или https://core.aleksmir.ru/en,

то язык интерфейса "Английский", т.к. последний элемент адресной строки - 'en'. Но это будет действовать при условии, что код языка "en" указан в параметре 'core/lang/list'. Например, если в параметре указаны такие языки:

'lang' => [
  'list' => [
    'ru' => 'Russian',
    'en' => 'English'
  ]
],

то допускается использовать окончания в адресной строке 'en'. Причем, язык, указанный первым по списку, считается основным. У основного языка преимущество в том, что приставку в конце адресной строки для него, в этом случае, указывать не нужно. Возможность указывать в адресной строке код основного языка, в данном случае 'ru', заблокирована для того, чтобы одна и та же страница не могла быть доступна с двух разных адресов. Поэтому для основного языка окончание не указываем совсем.

Как работает функция lang()

Вспомогательная функция lang($section, $words) доступна глобально. Применяется в шаблоне и в исходном коде для:

- определения фразы в элементе интерфейса на текущем языке сайта ($section - раздел сайта, $words - код фразы);
- преобразования URL с учётом текущего языка ($section - строка URL до преобразования, $words = '')
- преобразования пути к шаблону (разделитель - точка) с учётом текущего языка ($section - путь к шаблону до преобразования, $words = '')
- преобразования URL адресной строки к другому языку ($section = '', $words - код другого языка);
- получения кода текущего языка ($section = '', $words = '')

Как происходит определение фразы с помощью функции lang()

Функция lang() получает перевод фразы для интерфейса из массива route()->lang->words. Массив route()->lang->words заполняется в момент инициализации объекта 'lang' класса \Aleksmir\Core\Lang\Lang(). Для примера рассмотрим ситуацию, когда 'ru' - основной язык, 'en' - дополнительный. При этом выбранный язык для сайта - английский.

Объект 'lang' читает фразы из файла /view/default/core/lang/en.json и сохраняет их в именованный массив $core->lang->words.

Затем просматривает все папки в каталоге /view/default на предмет наличия других модулей; например, у нас написан свой модуль в папке /view/default/my_module. Тогда дополнительно читаются фразы из файла /view/default/my_module/lang/en.json. Если файл и фразы существуют, то они загружаются в тот же массив core()->lang->words, при этом, фразы с повторяющимися кодами из файла /view/default/core/lang/en.json перезаписываются новыми фразами.

Затем, аналогичным образом просматриваются папки /product и /company. Причем, первой просматривается папка /product, затем папка /company. Если в них встречаются файлы /lang/en.json, то их фразы подгружаются в массив core()->lang->words. Внутри папки /product и /company просматриваются не все, а только те, которые заданы в настройках программ:

core/user/enter_skin - задает код темы оформления; по-умолчанию 'default', в этом случае начало пути принимает вид /view/default
core/user/prod_code - код продукта; по-умолчанию 'my_product', в этом случае начало пути принимает вид /product/my_product;
core/user/prod_code - код предприятия; по-умолчанию 'my_enter', в этом случае начало пути принимает вид /company/my_product.

Применение функции lang() в шаблонах

Рассмотрим пример использования функции lang() в шаблоне /core/main/layout.blade.php:

@section('nav')
  <p>
    {{ lang('main.layout', 'head_title') }} <br />
    {{ lang('main.layout', 'head_motto') }}
  </p>
@endsection

Здесь мы видим код раздела 'main.layout'. Код раздела может быть произвольным, но для лучшей читаемости код раздела будет равен сокращенному названию файла шаблона. Код фразы также произвольный, внутри раздела он должен быть уникальным, но в другом разделе может повторяться.

Теперь рассмотрим содержимое файла ru.json:

{
  "main.layout": {
    "head_title": "Заголовок моего сайта",
    "head_motto": "Слоган для моего сайта"
}

После компиляции шаблона шаблонизатором blade будет сгенерирован код:

<p>
  Заголовок моего сайта<br />
  Слоган моего сайта
</p>

Для англоязычного варианта файл словаря en.json будет выглядеть так:

{
  "main.layout": {
    "title": "My site title",
    "motto": "My site's slogan"
}

Словари можно использовать не только в шаблонах, но и в методах классов. В этом случае код раздела будет представлять из себя полное название пространства имён, например 'aleksmir/core/view':

"aleksmir/core/view": {
  "404": "Страница не найдена!"
}

Реализация мультиязычности содержимого страниц

Если основной язык 'ru', то главная страница на русском языке будет иметь адрес:

https://core.aleksmir.ru,

главная страница на английском языке будет иметь адрес:

https://core.aleksmir.ru/en

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

Код языка также добавлен в основном шаблоне в теге <html>:

<html lang="{{ lang() }}">

Методы объекта класса \Aleksmir\Core\Lang\Lang

Ссылка на объект класса Aleksmir/Core/Lang/Lang в любое время доступна через свойство a()->core->lang. Методы класса Aleksmir/Core/Lang/Lang:

__construct() - конструктор; при инициализации объекта загружает словарь из файлов словаря;
init() - инициализация; при вызове заново загружает словарь из файлов словаря;
translate($section, $words) - возвращает фразу $words из раздела $section;
defineLang() - определяет код языка из адресной строки;
getUrl($lang) - преобразует адресную строку к заданному языку $lang.