Сайт на двух языках — это не роскошь, а необходимость. Но когда дело доходит до реализации в Yii2, многие разработчики начинают нервно листать документацию. Знакомая ситуация? Давайте разберёмся, как сделать мультиязычность правильно и без боли.

Digital-студия WNDER

Зачем вообще нужна мультиязычность и с чем её едят

Мультиязычность — это не просто перевод кнопок. Это целая система, которая включает:

  • Перевод статического текста (заголовки, кнопки, сообщения)
  • Перевод контента из базы данных (статьи, товары, описания)
  • Локализацию URL (site.com/ru/about и site.com/en/about)
  • Форматирование дат, чисел и валют

Если вы думаете, что достаточно захардкодить массив с переводами, вы сильно ошибаетесь. Yii2 предлагает мощный инструментарий, который многие просто не замечают.

Настройка базовых компонентов: язык, URL и сессии

Первое, что нужно сделать — настроить компонент i18n и urlManager. Это фундамент, без которого всё остальное развалится.

Откройте файл конфигурации config/web.php и добавьте следующие настройки:

'components' => [
    'language' => 'ru', // язык по умолчанию
    'sourceLanguage' => 'en', // язык исходного кода
    'i18n' => [
        'translations' => [
            'app*' => [
                'class' => 'yii\i18n\PhpMessageSource',
                'basePath' => '@app/messages',
                'sourceLanguage' => 'en',
                'fileMap' => [
                    'app' => 'app.php',
                    'app/error' => 'error.php',
                ],
            ],
        ],
    ],
    'urlManager' => [
        'enablePrettyUrl' => true,
        'showScriptName' => false,
        'rules' => [
            '//' => '/',
            '' => 'site/index',
        ],
    ],
],

Теперь создайте папку messages в корне проекта и внутри неё — подпапки ru и en. В каждой будет файл app.php с переводами:

// messages/ru/app.php
return [
    'Hello' => 'Привет',
    'Welcome to our site' => 'Добро пожаловать на наш сайт',
    'Read more' => 'Читать далее',
];

Теперь в представлениях можно использовать:

Правило: Всегда указывайте категорию перевода (например, 'app'). Это поможет структурировать файлы и не превратить один огромный массив в кашу.

Переключение языка: компонент LanguageSelector

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

namespace app\components;

use Yii;
use yii\base\Component;

class LanguageSelector extends Component
{
    public function init()
    {
        parent::init();
        $this->setLanguage();
    }

    private function setLanguage()
    {
        $session = Yii::$app->session;
        $request = Yii::$app->request;

        if ($request->get('lang')) {
            $lang = $request->get('lang');
            if (in_array($lang, ['ru', 'en'])) {
                $session->set('language', $lang);
            }
        }

        $language = $session->get('language', 'ru');
        Yii::$app->language = $language;
    }
}

Подключите его в конфигурации как компонент languageSelector и добавьте в bootstrap. Теперь при переходе по ссылке ?lang=en язык переключится и запомнится в сессии.

В представлении можно сделать простые ссылки:

Русский
English

Мультиязычные модели: перевод контента из базы

Самый сложный момент — перевод данных из БД. Есть два подхода:

Подход Плюсы Минусы
Отдельные таблицы для каждого языка Простота запросов, гибкость Дублирование структуры, сложность миграций
Одна таблица с полями title_ru, title_en Простота миграций Раздувание таблицы, сложность при добавлении языков
Отдельная таблица переводов (EAV) Гибкость, легко добавлять языки Сложные запросы, нужен доп. код

Я рекомендую третий вариант с использованием поведения TranslateBehavior из пакета creocoder/yii2-translateable или собственной реализации. Вот пример собственного поведения:

namespace app\behaviors;

use yii\base\Behavior;
use yii\db\ActiveRecord;
use app\models\ArticleTranslation;

class TranslateBehavior extends Behavior
{
    public $translationModel = ArticleTranslation::class;
    public $translationAttributes = ['title', 'content'];

    public function getTranslation($language = null)
    {
        $language = $language ?: Yii::$app->language;
        return $this->translationModel::findOne([
            'article_id' => $this->owner->id,
            'language' => $language,
        ]);
    }

    public function __get($name)
    {
        if (in_array($name, $this->translationAttributes)) {
            $translation = $this->getTranslation();
            return $translation ? $translation->$name : $this->owner->$name;
        }
        return parent::__get($name);
    }
}

Теперь в модели Article достаточно подключить это поведение, и обращение к $article->title автоматически вернёт перевод для текущего языка.

Локализация дат и чисел: не забываем про мелочи

Даты и числа в разных странах форматируются по-разному. В Yii2 за это отвечает компонент formatter. Настройте его в конфиге:

'formatter' => [
    'dateFormat' => 'dd.MM.yyyy',
    'decimalSeparator' => ',',
    'thousandSeparator' => ' ',
    'currencyCode' => 'RUB',
],

Для английского языка можно переопределить настройки динамически:

if (Yii::$app->language === 'en') {
    Yii::$app->formatter->dateFormat = 'MM/dd/yyyy';
    Yii::$app->formatter->decimalSeparator = '.';
    Yii::$app->formatter->thousandSeparator = ',';
    Yii::$app->formatter->currencyCode = 'USD';
}
Лайфхак: Создайте отдельный компонент LocaleHelper, который будет автоматически применять настройки форматтера в зависимости от языка. Это избавит от дублирования кода.

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

Чтобы не искать вручную все строки для перевода, Yii2 предоставляет команду message/extract. Запустите её из консоли:

./yii message/extract @app/config/i18n.php

Создайте файл i18n.php с настройками:

return [
    'sourcePath' => __DIR__ . '/../',
    'messagePath' => __DIR__ . '/../messages',
    'languages' => ['ru', 'en'],
    'translator' => 'Yii::t',
    'sort' => false,
    'overwrite' => true,
    'removeUnused' => false,
    'markUnused' => true,
    'except' => [
        '.svn',
        '.git',
        '.gitignore',
        '.gitkeep',
        '.hgignore',
        '.hgkeep',
        '/messages',
        '/vendor',
    ],
    'format' => 'php',
];

После выполнения команды в папках messages/ru и messages/en появятся файлы со всеми найденными строками. Останется только перевести значения.

Что в итоге: чек-лист мультиязычного сайта на Yii2

Подведём итоги. Чтобы ваш сайт заговорил на нескольких языках, нужно:

  • Настроить компоненты i18n, urlManager и formatter
  • Создать систему переключения языка через сессии
  • Организовать хранение переводов контента в базе данных
  • Использовать консольные команды для извлечения строк
  • Не забывать про локализацию дат, чисел и валют

Мультиязычность — это не страшно, если подойти к ней системно. Yii2 даёт все инструменты, а ваша задача — правильно их приготовить. Главное — не хардкодить переводы и следить за чистотой кода.

Теперь вы знаете, как сделать сайт на Yii2 мультиязычным. Осталось только применить знания на практике. Удачи в разработке!

Студия WNDER