Интернационализация (i18n) в PHP: от основ до современных решений
Интернационализация (i18n) — это процесс проектирования программного обеспечения таким образом, чтобы его можно было легко адаптировать под различные языки и регионы без изменения кода. В PHP существует несколько подходов к реализации i18n, от встроенных функций до мощных библиотек. В этой статье мы рассмотрим основные инструменты и лучшие практики.
Зачем нужна интернационализация?
Основная цель i18n — отделить текст интерфейса от кода. Это позволяет:
- Добавлять новые языки без изменения логики приложения
- Поддерживать множественные локали (форматы дат, чисел, валют)
- Упростить процесс перевода для переводчиков
- Соблюдать региональные стандарты (например, формат номера телефона)
Встроенная поддержка: gettext
PHP предлагает мощный механизм gettext для работы с переводами. Это классический подход, используемый в большинстве Linux-систем.
Установка и настройка
Убедитесь, что расширение gettext установлено. В большинстве дистрибутивов Linux оно доступно по умолчанию. Для Windows может потребоваться включить php_gettext.dll в php.ini.
Создание файлов перевода
Сначала создайте каталог для локалей. Типичная структура:
locale/
ru_RU/
LC_MESSAGES/
messages.po
messages.mo
en_US/
LC_MESSAGES/
messages.po
messages.mo
Файлы .po (Portable Object) — это текстовые файлы с переводами. Пример содержимого messages.po для русского языка:
msgid "Welcome"
msgstr "Добро пожаловать"
msgid "Hello, %s!"
msgstr "Здравствуйте, %s!"
Скомпилируйте .po в двоичный .mo с помощью утилиты msgfmt:
msgfmt locale/ru_RU/LC_MESSAGES/messages.po -o locale/ru_RU/LC_MESSAGES/messages.mo
Использование в коде
Пример PHP-скрипта с gettext:
<?php
// Устанавливаем локаль и домен
$locale = 'ru_RU';
putenv("LANG=$locale");
setlocale(LC_ALL, $locale);
bindtextdomain('messages', __DIR__ . '/locale');
textdomain('messages');
// Перевод строк
echo gettext('Welcome'); // Выведет "Добро пожаловать"
echo _('Hello, %s!', 'Иван'); // Выведет "Здравствуйте, Иван!"
?>
Функция _() — это сокращение для gettext(). Для перевода с плейсхолдерами используйте sprintf():
echo sprintf(_('Hello, %s!'), $username);
Современный подход: symfony/translation
Для крупных проектов удобнее использовать библиотеку symfony/translation. Она предлагает более гибкий интерфейс, поддержку разных форматов (YAML, XLIFF, JSON) и легко интегрируется с фреймворками.
Установка через Composer
composer require symfony/translation
Пример использования
<?php
require_once __DIR__ . '/vendor/autoload.php';
use Symfony\Component\Translation\Translator;
use Symfony\Component\Translation\Loader\ArrayLoader;
$translator = new Translator('ru_RU');
$translator->addLoader('array', new ArrayLoader());
// Добавляем переводы напрямую (для демонстрации)
$translator->addResource('array', [
'Welcome' => 'Добро пожаловать',
'Hello %name%' => 'Здравствуйте, %name%',
], 'ru_RU');
// Переключение на английский
$translator->setLocale('en_US');
$translator->addResource('array', [
'Welcome' => 'Welcome',
'Hello %name%' => 'Hello, %name%',
], 'en_US');
// Использование
echo $translator->trans('Welcome'); // "Welcome"
echo $translator->trans('Hello %name%', ['%name%' => 'John']); // "Hello, John"
?>
Работа с YAML-файлами
Создайте файл messages.ru.yaml:
Welcome: Добро пожаловать
'Hello %name%': 'Здравствуйте, %name%'
Загрузите его в код:
use Symfony\Component\Translation\Loader\YamlFileLoader;
$translator->addLoader