Если ваш сайт выходит за пределы одной страны, рано или поздно встанет вопрос: как сделать его удобным для пользователей, говорящих на разных языках? Мультиязычность — это не просто перевод текста, а целая система, которая включает маршрутизацию, хранение переводов, работу с URL и многое другое. В этой статье мы разберем, как реализовать мультиязычность в Yii2 — одном из самых популярных PHP-фреймворков. Я покажу, как настроить все с нуля, дам примеры кода и поделюсь лайфхаками, которые сэкономят вам часы работы.

Digital-студия WNDER

С чего начать: базовые понятия

Прежде чем погружаться в код, давайте разберемся, что такое мультиязычность в контексте Yii2. Фреймворк предоставляет встроенные инструменты для интернационализации (i18n) — это набор функций, которые позволяют переводить сообщения, форматировать даты и числа в зависимости от локали. Локаль — это комбинация языка и региона, например, en-US или ru-RU.

Основная идея такова: вы пишете код с использованием специальных меток, а Yii2 подставляет нужный перевод в зависимости от выбранной локали. Это похоже на шаблон, куда подставляются значения. Но чтобы все заработало, нужно правильно настроить приложение.

В Yii2 есть два подхода к хранению переводов: файловый (например, PHP-массивы или JSON) и базовый (хранение в базе данных). Файловый подход проще для небольших проектов, базовый — для больших, где переводы обновляются динамически. Мы рассмотрим оба варианта, но начнем с файлового.

Настройка приложения для работы с языками

Первый шаг — настроить компонент i18n в конфигурационном файле приложения (обычно это config/web.php). Здесь мы указываем, где хранятся переводы и какие языки поддерживаются. Вот базовый пример:


'components' => [
    'i18n' => [
        'translations' => [
            'app*' => [
                'class' => 'yii\i18n\PhpMessageSource',
                'basePath' => '@app/messages',
                'sourceLanguage' => 'ru-RU',
                'fileMap' => [
                    'app' => 'app.php',
                    'app/error' => 'error.php',
                ],
            ],
        ],
    ],
],

Здесь basePath указывает на папку, где лежат файлы переводов, а sourceLanguage — язык, на котором написан исходный код (обычно это язык разработчика). Обратите внимание на паттерн app* — он говорит, что все категории, начинающиеся с 'app', будут использовать этот источник.

Теперь создадим файлы переводов. Для каждого языка создается папка с локалью, например, messages/en-US/app.php. Внутри — массив, где ключи — это исходные строки, а значения — переводы:


// messages/en-US/app.php
return [
    'Привет, мир!' => 'Hello, world!',
    'Добро пожаловать' => 'Welcome',
];

Чтобы использовать переводы в коде, достаточно вызвать метод Yii::t():


// В контроллере или представлении
echo Yii::t('app', 'Привет, мир!');

Если перевода нет, Yii2 просто выведет исходную строку — это удобно для отладки.

Маршрутизация с учетом языка

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

  • Использовать поддомены (en.site.com, ru.site.com).
  • Использовать префикс в URL (site.com/en, site.com/ru).
  • Использовать параметр запроса (site.com?lang=en).

Я рекомендую второй вариант — префикс в URL. Он прост в реализации и понятен пользователям. Для этого нужно настроить URL-правила в компоненте urlManager. Вот как это сделать:


'urlManager' => [
    'enablePrettyUrl' => true,
    'showScriptName' => false,
    'rules' => [
        '<lang:(en|ru)>/<controller>/<action>' => '<controller>/<action>',
    ],
],

Теперь нам нужно определить текущий язык в приложении. Это можно сделать в компоненте beforeAction события приложения или в базовом контроллере. Например, создадим компонент LanguageSelector:


class LanguageSelector extends Component
{
    public function init()
    {
        parent::init();
        // Определяем язык из URL
        $lang = Yii::$app->request->get('lang');
        if ($lang && in_array($lang, ['en', 'ru'])) {
            Yii::$app->language = $lang === 'en' ? 'en-US' : 'ru-RU';
        } else {
            // Если язык не указан, используем язык браузера или по умолчанию
            Yii::$app->language = 'ru-RU';
        }
    }
}

Подключаем этот компонент в конфигурации:


'components' => [
    'languageSelector' => [
        'class' => 'app\components\LanguageSelector',
    ],
],

Теперь при обращении к site.com/en/contact язык будет английский, а при site.com/ru/contact — русский. Осталось только добавить переключатель языка на сайте — это может быть ссылка или выпадающий список.

Перевод динамического контента из базы данных

Статические строки мы перевели, но что делать с контентом, который хранится в базе данных? Например, у нас есть таблица posts, и мы хотим, чтобы заголовок и текст были на разных языках. Самый простой способ — создать дополнительные поля для каждого языка, например, title_ru, title_en. Но это не очень гибко.

Лучше использовать отдельные таблицы для переводов. Например, у нас есть таблица post с полями id, created_at, и таблица post_lang с полями post_id, lang, title, content. Тогда мы можем легко получать нужный перевод в зависимости от текущего языка.

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


class Post extends \yii\db\ActiveRecord
{
    public function getTranslations()
    {
        return $this->hasMany(PostLang::className(), ['post_id' => 'id']);
    }

    public function getTranslation($lang = null)
    {
        $lang = $lang ?: Yii::$app->language;
        return $this->getTranslations()->where(['lang' => $lang])->one();
    }
}

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


$translation = $post->getTranslation();
echo $translation->title;

Этот подход легко масштабируется: если добавится новый язык, просто добавим записи в таблицу переводов, не меняя структуру основной таблицы.

Практические советы и лайфхаки

Вот несколько советов, которые помогут вам избежать типичных ошибок и упростить жизнь:

  • Всегда указывайте sourceLanguage в конфигурации i18n — это поможет избежать путаницы.
  • Используйте категории для переводов: например, app, app/error, app/form. Это упростит поиск нужных строк.
  • Для дат и чисел используйте встроенные форматтеры Yii2 — они автоматически адаптируются под локаль.
  • Не забывайте про кэширование переводов: в production-режиме включите кэш, чтобы не читать файлы каждый раз.
Лайфхак: чтобы быстро проверить, какие строки не переведены, включите режим отладки и посмотрите на исходные строки в выводе. Yii2 подсветит их, если перевода нет.

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

Сравнение подходов к хранению переводов

Подход Плюсы Минусы
Файловые переводы Простота, быстрота, удобно для статики Не подходит для динамического контента
Переводы в БД Гибкость, возможность редактирования через админку Требует дополнительных запросов, сложнее в настройке

Выбор подхода зависит от вашего проекта. Если сайт простой — хватит файлов. Если контент постоянно обновляется — лучше использовать БД.

Итог: что мы получили

Мы рассмотрели основные шаги для реализации мультиязычности в Yii2: настройку компонента i18n, маршрутизацию с префиксом языка, перевод статических строк и динамического контента. Теперь вы можете сделать свой сайт доступным для пользователей из разных стран.

Помните, что мультиязычность — это не только перевод текста, но и адаптация форматов дат, чисел, валют. Yii2 предоставляет все необходимые инструменты, так что не бойтесь экспериментировать.

Если у вас остались вопросы — загляните в официальную документацию Yii2 или обратитесь к сообществу. Удачи в разработке!

Студия WNDER