Компонент интернационализации работает на основе symfony/translation с некоторыми расширениями и загрузкой словарей из модулей
Словарь - это папка, имя которой является именем словаря (домена в нотации symfony/translation), которая содержит набор файлов по локалям, где имя файла - это наименование локали, а содержимое - правила перевода данного словаря для данной локали.
Пример:
- Test
- messages
- main
- ru.php
- en.php
- custom
- ru.php
- en.php
По-умолчанию доступна работа с файлами с расширениями: php, json, po, mo
Словари располагаются в модулях и в приложении. Словари в приложении имеют высокий приоритет, словари в модулях - низкий.
Словари в модулях расположены в папке messages от корня модуля. Например, словари модуля Test должны располагаться в папке app/Modules/Test/messages.
К имени словарей в модулях автоматически добавляется префикс в виде имени модуля.
Пример расположения словаря main в модуле Test:
- Test
- messages
- main
- ru.php
- en.php
Полное имя словаря будет таким: Test.main, соответственно, вызвать перевод с из данного словаря можно следующим образом
Phact::app()->translate->t("Test.main", "Some key")
Файлы правил перевода по локалям могут быть расположены непосредственно в папке messages:
- Test
- messages
- ru.php
- en.php
В этом случае полное имя словаря будет таким: Test.messages и вызвать перевод можно будет как с указанием имени словаря:
Phact::app()->translate->t("Test.messages", "Some key")
так и с указанием только имени модуля:
Phact::app()->translate->t("Test", "Some key")
Словари в приложении организованы таким же образом как и в модулях, за исключением того, что к их имени не добавляются никакие префиксы.
Словари приложения расположены в папке app/messages
Пример расположения словаря main в приложении:
- app
- messages
- main
- ru.php
- en.php
Полное имя словаря будет таким: main, соответственно, вызвать перевод с из данного словаря можно следующим образом
Phact::app()->translate->t("main", "Some key")
Словари в приложении так же позволяют перекрыть стандартные словари (*Phact.**) и словари модулей. Для примера перекроем словарь модуля Test: Test.messages
- app
- messages
- Test.messages
- ru.php
- en.php
Таким образом можно производить замены необходимых значений перевода в словарях модулей и стандартных словарях.
Компонент расположен по адресу Phact::app()->translate
Пример конфигурации:
...
'translate' => [
'class' => \Phact\Translate\Translate::class,
'default' => 'ru',
'locales' => [
'ru' => 'Русский',
'en' => 'English'
],
'localeDetector' => function () {
...
}
],
...
localeDetector - детектор локали. Указывается либо тип callable, либо класс объекта
с имплементированным интерфейсом \Phact\Translate\LocaleDetector
.
Идентифицирует локаль и возвращает ее наименование в строковом формате.
default - локаль по-умолчанию. Применяется при отсутствии localeDetector или при возвращении им пустого значения
locales - список локалей. Внутри компонента не используется, оставлено для удобства разработчика.
setLocale($localeName) - устанавливает текущую локаль
getLocale() - получает текущую локаль
getTranslator() - получает объект \Symfony\Component\Translation\Translator
t - метод для получения перевода
Метод для получения перевода может использоваться в двух сценариях:
- Для обычного перевода строки
- Для перевода с плюрализацией
Для обоих сценариев первые два параметра остаются одинаковыми - это имя словаря и ключ в словаре перевода. Причем, если передать только один параметр - то он будет считатся ключом, а домен будет выбираться по-умолчанию.
А теперь рассмотрим применение подробнее.
И сразу с примеров. Получение значения по ключу Some key из словаря Test.main.
Phact::app()->translate->t('Test.main', 'Some key')
Тут всё просто.
Получение плюрализированного значения по ключу element|elements из словаря Test.main со значением 2.
Phact::app()->translate->t('Test.main', 'element|elements', 2)
В данном случае компонент перевода не просто сделает перевод строки, но и по правилу определения плюрализации для нашей локали выберет из значения, разделенного символом "|" нужный сегмент.
Например, для английского языка он выдаст значение "elements".
А если указать соответствующее значение в словаре для русского языка
[
...
'elements|elements' => 'элемент|элемента|элементов'
...
]
то значением будет "элемента"
Дополнительно оба сценария могут принимать:
- Списки замен
- Имя локали
Иногда бывает достаточно удобно (и даже правильно) вводить динамические параметры в наши строки с переводом. Например вместо следующей конструкции:
Phact::app()->translate->t("Test.main", "Hello, ") . $username . Phact::app()->translate->t("Test.main", ", have a nice day!");
Можно применять следующую:
Phact::app()->translate->t("Test.main", "Hello, %username%, have a nice day!", ['%username%' => $username]);
Для строк с плюрализацией один элемент в списке замен всегда присутствует - это %count%, который содержит значение, которое вы передали для плюрализации.
Пример:
Phact::app()->translate->t('Test.main', '%count% element|%count% elements', 2)
Но и для перевода с плюрализацией доступны обычные замены.
Последним параметром в обоих сценариях можно передать локаль форсированно, тогда перевод будет осуществлен не с учетом локали установленной в компоненте, а с учетом переданной локали в параметре.
Для удобства применения перевода в коде существует trait \Phact\Translate\Translator
,
который добавляет к вашему классу метод ::t
, который является чуть улучшенным алиасом метода Phact::app()->translate->t
.
Улучшение заключется в том, что если метод применяется к классу модуля у которого применен
trait \Phact\Helpers\ClassNames
или существует метод ::getModuleName
(например у всех моделей в модуле),
то для них будет установлен словарь по-умолчанию: "{$moduleName}".
Пример:
<?php
namespace Modules\Test\Models;
use Phact\Orm\Fields\CharField;
use Phact\Orm\Model;
use Phact\Translate\Translator;
class Blogger extends Model
{
use Translator;
public static function getFields()
{
return [
'name' => [
'class' => CharField::class,
'label' => self::t("Blogger name")
]
];
}
}
В данном примере обращение self::t("Blogger name")
будет равно обращению self::t("Test", "Blogger name")
,
так как имя модуля в качестве словаря подставится автоматически.
К тому же использование trait \Phact\Translate\Translator
чуть более безопасно,
так как содержит проверку на присутствие компонента translate в приложении.
Для удобства перевода в шаблонизаторе добавлены функция (для непосредственного вывода данных) и accessor-функция (для получения результата перевода в переменную).
Примеры:
{t "Test" "Module test"}
{t "Test.main" "test"}
{t "Test" "%count% item|%count% items" 2}
{$.t("Test.main", "test")}
{set $translated = $.t("Test" "%count% item|%count% items", 1)}