Мультиязычные сайты
Как создать сайт на нескольких языках: настройки, URL-префиксы, _t объект, класс Core\I18n.
Мультиязычные сайты
apidcms поддерживает создание сайтов на нескольких языках через систему URL-префиксов, кук и объект перевода _t.
Как включить
В админке перейдите в Настройки (/admin/settings). Найдите две опции:
| Настройка | Описание | Пример |
|---|---|---|
site_language |
Базовый язык сайта | ru |
site_languages |
Дополнительные языки (JSON-массив) | ["en", "de"] |
После сохранения на фронтенде появится переключатель языков, а все страницы будут доступны с языковым префиксом в URL.
Важно: система opt-in — пока site_languages не заполнен, мультиязычность не активна.
Как это работает
URL-префиксы
Каждый дополнительный язык получает префикс в URL:
| Базовый язык (ru) | Английский (en) |
|---|---|
/changelog |
/en/changelog |
/docs/install |
/en/docs/install |
/plugins |
/en/plugins |
Базовый язык (site_language) не получает префикс — его URL остаются «голыми». Это позволяет сохранить обратную совместимость со старыми ссылками.
Кука site_lang
При посещении страницы с языковым префиксом система устанавливает куку site_lang на 1 год. Если пользователь переходит по ссылке без префикса, система проверяет куку и показывает сохранённый язык.
Переключение на базовый язык происходит через query-параметр ?lang=ru — он сбрасывает куку и возвращает базовую локаль.
Объект _t в шаблонах
Все переводы хранятся прямо в шаблоне base.html.twig в виде объекта _t:
{% set _t = {
ru: {
home: "Главная",
docs: "Документация",
changelog: "CHANGELOG"
},
en: {
home: "Home",
docs: "Documentation",
changelog: "Changelog"
}
} %}
Использование в любом шаблоне:
<h1>{{ _t[site_lang].changelog_heading }}</h1>
<a href="{{ url('/docs') }}">{{ _t[site_lang].docs }}</a>
Переменная site_lang автоматически передаётся во все шаблоны — она содержит текущий язык (ru или en).
Функция url()
Все внутренние ссылки должны использовать url(), а не жёсткие пути:
{# Правильно — префикс добавится автоматически #}
<a href="{{ url('/changelog') }}">Чейнджлог</a>
{# Неправильно — ссылка всегда ведёт на базовый язык #}
<a href="/changelog">Чейнджлог</a>
url() проверяет текущую локаль и, если она отличается от базовой, добавляет префикс:
- При
site_lang = en:url('/changelog')→/en/changelog - При
site_lang = ru:url('/changelog')→/changelog
Служебные пути (/admin, /storage, /static) не получают префикс.
Переключатель языков
Минимальный переключатель в base.html.twig:
{% if get_setting('site_languages')|default('') is not empty %}
<div class="lang-switch">
<a href="/{{ current_path }}?lang=ru"
class="{% if site_lang == 'ru' %}active{% endif %}">RU</a>
<a href="/en/{{ current_path }}"
class="{% if site_lang == 'en' %}active{% endif %}">EN</a>
</div>
{% endif %}
- Базовый язык (RU):
/{current_path}?lang=ru— query-параметр сигнализирует о явном переключении - Дополнительный язык (EN):
/en/{current_path}— URL-префикс
Переменная current_path содержит текущий путь без языкового префикса.
current_path
Переменная current_path автоматически очищается от префикса локали:
| URL страницы | site_lang |
current_path |
|---|---|---|
/changelog |
ru |
changelog |
/en/changelog |
en |
changelog |
/en/changelog/v2-1-1 |
en |
changelog/v2-1-1 |
Это позволяет переключателю языков всегда формировать правильные ссылки.
Класс Core\I18n
Для продвинутой работы с переводами в PHP-коде используется класс Core\I18n.
resolve()
Извлекает значение для текущей локали из i18n-объекта:
use Core\I18n;
$title = I18n::resolve($item['title'], 'ru'); // {"ru":"Привет","en":"Hello"} → "Привет"
$title = I18n::resolve($item['title'], 'en'); // → "Hello"
resolveArray()
Рекурсивно обходит массив и разрешает все i18n-поля:
$items = I18n::resolveArray($items, 'en');
// Все поля вида {"ru":"...","en":"..."} будут заменены на англ. значение
Используется в FrontController::resolveI18nData() для автоматического перевода данных перед рендером.
searchExpr()
Экранирует поисковый запрос для разных локалей:
$expr = I18n::searchExpr($query, 'ru');
Полезно при реализации поиска на мультиязычных сайтах.
encode()
Кодирует значение с учётом локали:
$encoded = I18n::encode($value, 'ru');
Внешние страницы и contenturl{locale}
Для внешних страниц (changelog, плагины) можно указать разные URL контента для разных языков.
Вместо одного поля content_url используйте:
| Поле | Назначение |
|---|---|
content_url |
URL по умолчанию (базовый язык) |
content_url_ru |
URL для русской версии |
content_url_en |
URL для английской версии |
Если поле content_url_{locale} не задано, используется content_url.
Настройка <html lang>
Шаблон base.html.twig должен использовать site_lang для атрибута lang:
<html lang="{{ site_lang }}">
Это важно для SEO и доступности (screen readers).
Известные ограничения
- Нет авто-редиректа. Система не перенаправляет с голого URL на префиксный. Если у пользователя установлена кука
site_lang=en, а он заходит на/changelog, страница отобразится на английском, но URL останется без префикса. - Только префиксный метод. Нет поддержки поддоменов (
en.example.com) или параметров (?lang=enдля постоянного использования). - Переводы в шаблонах. Все строки
_tхранятся вbase.html.twig. Для больших проектов это может стать громоздким — рассмотрите вынос в отдельный Twig-файл черезinclude. - Нет перевода контента. Система переводит только интерфейс (навигацию, кнопки, заголовки). Контент страниц (тексты, статьи) требует ручного дублирования для каждой локали.