SLOT-H: Принцип локализации



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




1. Текст в коде



Тексты, которые жёстко зашиты в PHP-файлах, передаются через статический метод `\Config\CC::locale(&

039;....')`.



Пример:

php
echo CC::locale('Добро пожаловать');

Для таких текстов существует сборщик, который сканирует код, находит все вызовы CC::locale() и актуализирует список строк для перевода. Эти строки сохраняются в таблицу tkeys.

В полной версии предусмотрен механизм автоматического перевода через API внешних сервисов. Он формирует первичный пул переводов в таблице tvalues. Первичный - потому что машинный перевод требует ручной корректировки, так как качество автоматического перевода недостаточно для production-использования.

Переводы выполняются на все языки, включённые в проекте (таблица project_languages).

Если перевод отсутствует, система возвращает исходный текст, переданный как аргумент в CC::locale().

2. Полноценные тексты


Это тексты, которые хранятся в таблице texts и управляются через административный интерфейс. Для них используется связанная таблица переводов t_texts.

Для таких текстов автоматизированный перевод не применяется. Большие объёмы текста при машинном переводе дают результат, неприемлемый с точки зрения носителей языка. Переводы выполняются вручную через интерфейс администратора.

Структура:

texts - основная таблица с исходными текстами

t_texts - таблица переводов, связанная с texts через поле parent

3. Переводные тексты в хранилище данных


Для таблиц, которые должны поддерживать переводы, в классе DbTable устанавливается свойство:

php
public static $_translate = true;

Для работы с переводами необходимо:

Создать таблицу переводов с именем t_<имя основной таблицы>

В этой таблице обязательно должны быть поля:

language_id - идентификатор языка

parent - идентификатор записи из основной таблицы

Добавить поля, соответствующие переводимым полям основной таблицы (1:1 по именам и типам)

Программисту не нужно думать о JOIN-ах и данных. Его задача - работать с исходной моделью, без использования модели с префиксом t_. ORM автоматически формирует один запрос, получающий исходные данные таблицы и JSON, содержащий полный набор переводов.

Пример для демонстрации принципа:

В административной части вызывается:

php
$links = \Modules\Base\Models\DbTables\Alias::getAll();

ORM генерирует следующий SQL-запрос:

sql
SELECT 
  aliases.*,
  CONCAT(
    "{",
    GROUP_CONCAT(
      CONCAT(
        '"',
        dev.t_aliases.language_id,
        '":{"alias_name":"',
        REPLACE(
          REPLACE(
            REPLACE(
              IFNULL(dev.t_aliases.alias_name,''),
              '"',
              '\\"'
            ),
            '\n',
            '<br>'
          ),
          '\r',
          ''
        ),
        '"}'
      )
    ),
    "}"
  ) AS tblock
FROM 
  `dev`.`aliases` AS aliases
LEFT JOIN dev.t_aliases ON dev.t_aliases.parent = dev.aliases.alias_id
WHERE dev.aliases.alias_id IS NOT NULL
AND aliases.project_id = "1"
GROUP BY dev.aliases.alias_id

Все переводы собираются в JSON-поле tblock, которое затем парсится моделью. При вызове геттера модель проверяет наличие перевода на текущий язык и возвращает его, если он доступен.

Единый принцип


Во всех трёх случаях действует одно правило:

Если перевод на текущий язык пользователя существует - показывается он. Если нет - показывается исходный текст.

Исходный текст для кода - это аргумент метода CC::locale(). Для данных - это значение в исходной таблице.

Программист работает только с исходными сущностями. Один раз создав таблицу с префиксом t_ и переопределив в классе признак переводной сущности, программист может забыть про переводы. Всё, что связано с JOIN-ами, группировкой и подстановкой переводов, берёт на себя ORM. Это делает систему устойчивой к отсутствию переводов: пользователь всегда видит текст, пусть и не на своём языке.




Что дальше?



- ➡️ Раздел 27. Запуск сервера очередей
- ➡️ Раздел 28. Задачи сервера очередей
- ➡️ Раздел 29. Хелперы