43Интернационализация
language и sourceLanguage, Yii::t() с параметрами, множественным числом, select, number и date (ICU MessageFormat), источники переводов PhpMessageSource/DbMessageSource/GettextMessageSource, извлечение сообщений командой message, переводы представлений и модулей, локаль форматтера.
I18n в Yii — это три вещи: язык приложения (Yii::$app->language), перевод сообщений через Yii::t() с форматированием ICU и локализация вывода дат/чисел через formatter. Строки пишутся на исходном языке (обычно английском), переводы хранятся в файлах или БД по категориям.
Языки#
'sourceLanguage' => 'en-US', // на каком языке написаны строки в коде (по умолчанию en-US)
'language' => 'ru-RU', // язык вывода; можно менять во время выполнения// например, по настройке пользователя или заголовку Accept-Language
Yii::$app->language = 'ru-RU';
Yii::$app->language = Yii::$app->request->getPreferredLanguage(['en-US', 'ru-RU', 'de']);Код языка — IETF: en, en-US, ru-RU, zh-Hans-CN. Если для ru-RU перевода нет, будет искаться ru.
Yii::t()#
echo Yii::t('app', 'This is a string to translate!');
echo Yii::t('app', 'Hello, {username}!', ['username' => $username]);
echo Yii::t('app', 'Price: {0}', [$price]); // позиционные — {0}, {1}
echo Yii::t('app', 'Balance: {0, number, currency}', [$amount]); // формат числа через ICU
echo Yii::t('app', 'Today is {0, date, short}', [time()]);
echo Yii::t('app', 'Hello', [], 'de'); // явный языкКатегория (app) — группа сообщений; yii зарезервирована для фреймворка, расширения используют свои (yii/bootstrap...). Если строка не переведена, вернётся исходная (и сработает событие missingTranslation).
Множественное число#
echo Yii::t('app', 'There {n, plural, =0{are no cats} =1{is one cat} other{are # cats}}!', ['n' => $n]);Формы для русского перевода — one, few, many, other (правила CLDR):
'There {n, plural, =0{are no cats} =1{is one cat} other{are # cats}}!' =>
'На диване {n, plural, =0{нет кошек} one{# кошка} few{# кошки} many{# кошек} other{# кошки}}!',# — число, =0 — точное значение. Также {n, plural, offset:1 …} и {n, selectordinal, one{#st} two{#nd} few{#rd} other{#th}}.
Выбор по значению#
echo Yii::t('app', '{name} is {gender, select, female{she} male{he} other{it}} and loves Yii!', [
'name' => 'Alexander',
'gender' => 'male',
]);Числа, даты, порядковые#
Yii::t('app', '{n, number}', ['n' => 1234.5]); // 1 234,5 (ru)
Yii::t('app', '{n, number, percent}', ['n' => 0.42]);
Yii::t('app', '{n, number, #,##0.00}', ['n' => 1234.5]); // свой паттерн
Yii::t('app', '{d, date, long}', ['d' => time()]); // short | medium | long | full | паттерн
Yii::t('app', '{t, time, short}', ['t' => time()]);
Yii::t('app', '{n, spellout}', ['n' => 42]); // forty-two
Yii::t('app', '{n, ordinal}', ['n' => 42]); // 42ndВсё это MessageFormatter расширения intl; без intl доступны только простые подстановки, plural и select.
Источники переводов#
'components' => [
'i18n' => [
'translations' => [
'app*' => [ // категории app, app/error, app/mail…
'class' => 'yii\i18n\PhpMessageSource',
'basePath' => '@app/messages', // messages/ru-RU/app.php
'sourceLanguage' => 'en-US',
'fileMap' => [
'app' => 'app.php',
'app/error' => 'error.php',
],
// 'forceTranslation' => true, // переводить, даже если language == sourceLanguage
// 'on missingTranslation' => [TranslationEventHandler::class, 'handleMissingTranslation'],
],
'*' => ['class' => 'yii\i18n\PhpMessageSource'], // остальное — по умолчанию @app/messages
],
],
],return [
'This is a string to translate!' => 'Это строка для перевода!',
'Hello, {username}!' => 'Привет, {username}!',
'not translated yet' => '', // пустая — вернётся исходная
];PhpMessageSourcebasePath/<язык>/<категория>.php; самый быстрый и простойDbMessageSourcesource_message и message (миграция @yii/i18n/migrations); переводы редактируются в админкеGettextMessageSource.po/.mo, инструменты переводчиковКлюч app* — маска по префиксу. Переводы фреймворка (yii) уже есть на десятках языков — категорию yii настраивать не нужно.
Извлечение сообщений#
./yii message/config-template @app/messages/config.php # шаблон конфигурации
./yii message/config --languages=ru-RU,de --messagePath=@app/messages @app/messages/config.php
./yii message @app/messages/config.php # просканировать код, обновить файлы переводовКоманда находит все вызовы Yii::t() (и \Yii::t, $this->t в шаблонах — настраивается translator), создаёт файлы для каждого языка, помечает удалённые строки @@…@@, сортирует. Для БД — 'format' => 'db', для gettext — 'po'.
Переводы в разных местах#
// модели: подписи и ошибки
public function attributeLabels() { return ['username' => Yii::t('app', 'Username')]; }
['username', 'required', 'message' => Yii::t('app', '{attribute} is required')],
// представления: целые файлы — views/site/ru-RU/about.php выберется автоматически для language = ru-RU
// (устарело с 2.0.x, лучше Yii::t внутри представлений)
// виджеты и модули — своя категория и регистрация переводов
class Module extends \yii\base\Module
{
public function init()
{
parent::init();
$this->registerTranslations();
}
public function registerTranslations()
{
Yii::$app->i18n->translations['modules/users/*'] = [
'class' => 'yii\i18n\PhpMessageSource',
'sourceLanguage' => 'en-US',
'basePath' => '@app/modules/users/messages',
'fileMap' => ['modules/users/validation' => 'validation.php', 'modules/users/form' => 'form.php'],
];
}
public static function t($category, $message, $params = [], $language = null)
{
return Yii::t('modules/users/' . $category, $message, $params, $language);
}
}
// Module::t('form', 'Save')Локаль форматтера и прочее#
Yii::$app->formatter->localeпо умолчанию =language— даты и числа локализуются автоматически.Yii::$app->languageвлияет наHtml::tag('html', …, ['lang' => …])— задавайтеlangв layout изYii::$app->language.- RTL-языки:
Yii::$app->formatterне решает вёрстку — используйте классdir="rtl"в layout по языку. - URL с языком (
/ru/site/about) — свойUrlManagerили правило с параметром<lang:(ru|en)>и установка языка вbeforeAction/bootstrap; готовые расширения:codemix/yii2-localeurls.
Исходную строку Hello и вызовет событие missingTranslation у источника.
one, few, many (и other); =0/=1 — для точных значений.
@app/messages/ru-RU/app.php.
./yii message/config для конфигурации, затем ./yii message config.php.
Зарегистрировать источник в Yii::$app->i18n->translations под своей категорией (обычно в init() модуля) и использовать эту категорию в Yii::t().