Symfony Component Translation: Подробный разбор
Компонент Translation
в Symfony предоставляет мощный и гибкий механизм для интернационализации и локализации вашего приложения. Он позволяет переводить текстовые строки, сообщения об ошибках, метки форм и другие элементы интерфейса на разные языки.
Ключевые концепции:
- Перевод (Translation): Процесс преобразования текста с одного языка (исходного) на другой (целевой).
- Локаль (Locale): Идентификатор языка и региональных настроек. Он состоит из кода языка (например,
en
для английского,ru
для русского,fr
для французского) и, опционально, кода страны (например,en_US
для американского английского,en_GB
для британского английского,fr_CA
для канадского французского).ru_RU
,de_DE
и т. д. - Домен перевода (Translation Domain): Логическая группа сообщений для перевода. По умолчанию используется домен
messages
, но можно создавать собственные домены (например,admin
,validators
,forms
) для лучшей организации. Это помогает разделить переводы, относящиеся к разным частям приложения. - Каталог сообщений (Message Catalogue): Хранилище переводов для конкретной локали и домена. Обычно представлен файлом в формате YAML, XLIFF, PHP или Gettext. Каталог содержит пары «ключ-перевод».
- Загрузчик (Loader): Компонент, отвечающий за загрузку каталогов сообщений из различных форматов (YAML, XLIFF, PHP, Gettext).
- Транслятор (Translator): Основной класс компонента, который предоставляет API для перевода сообщений. Он использует загрузчики для поиска и загрузки каталогов, а затем выбирает подходящий перевод на основе ключа, локали и домена.
- Плюрализация (Pluralization): Механизм для обработки множественного числа в переводах. Например, правила для форм слова «файл» будут разными для «1 файл», «2 файла», «5 файлов».
- Заполнители (Placeholders): Специальные маркеры в строках перевода, которые заменяются динамическими значениями во время выполнения (например, имя пользователя, количество элементов).
Структура проекта (типичная):
translations/
messages.en.yaml # Английский перевод для домена 'messages'
messages.ru.yaml # Русский перевод для домена 'messages'
validators.en.yaml # Английский перевод для домена 'validators'
validators.ru.yaml # Русский перевод для домена 'validators'
admin.en.yaml # Английский перевод для домена 'admin'
admin.ru.yaml # Русский перевод для домена 'admin'
# ... другие файлы переводов
Примеры:
1. Простой перевод:
# translations/messages.en.yaml
welcome: 'Welcome!'
# translations/messages.ru.yaml
welcome: 'Добро пожаловать!'
use Symfony\Component\Translation\Translator;
use Symfony\Component\Translation\Loader\YamlFileLoader;
// Создаем транслятор
$translator = new Translator('en'); // 'en' - локаль по умолчанию
// Добавляем загрузчик для YAML файлов
$translator->addLoader('yaml', new YamlFileLoader());
// Добавляем ресурсы (файлы переводов)
$translator->addResource('yaml', __DIR__.'/translations/messages.en.yaml', 'en');
$translator->addResource('yaml', __DIR__.'/translations/messages.ru.yaml', 'ru');
// Переводим сообщение
echo $translator->trans('welcome'); // Выведет: Welcome!
// Меняем локаль
$translator->setLocale('ru');
echo $translator->trans('welcome'); // Выведет: Добро пожаловать!
2. Перевод с заполнителями:
# translations/messages.en.yaml
welcome_user: 'Welcome, %name%!'
# translations/messages.ru.yaml
welcome_user: 'Добро пожаловать, %name%!'
// ... (предыдущий код)
echo $translator->trans('welcome_user', ['%name%' => 'John']); // Выведет: Welcome, John!
$translator->setLocale('ru');
echo $translator->trans('welcome_user', ['%name%' => 'Иван']); // Выведет: Добро пожаловать, Иван!
3. Плюрализация (множественное число):
# translations/messages.en.yaml
apples: '{0} There are no apples|{1} There is one apple|]1,Inf[ There are %count% apples'
# translations/messages.ru.yaml
apples: '{0} Яблок нет|{1} Есть одно яблоко|{2,3,4} Есть %count% яблока|[5,Inf[ Есть %count% яблок'
{0}
— еслиcount == 0
{1}
— еслиcount == 1
[5,Inf[
полуинтервал, большие либо равное 5]1,Inf[
интервал, строго больше 1{2,3,4}
— еслиcount == 2 || count == 3 || count == 4
// ... (предыдущий код)
echo $translator->trans('apples', ['%count%' => 0]); // Выведет: There are no apples
echo $translator->trans('apples', ['%count%' => 1]); // Выведет: There is one apple
echo $translator->trans('apples', ['%count%' => 5]); // Выведет: There are 5 apples
$translator->setLocale('ru');
echo $translator->trans('apples', ['%count%' => 0]); // Выведет: Яблок нет
echo $translator->trans('apples', ['%count%' => 1]); // Выведет: Есть одно яблоко
echo $translator->trans('apples', ['%count%' => 2]); // Выведет: Есть 2 яблока
echo $translator->trans('apples', ['%count%' => 5]); // Выведет: Есть 5 яблок
echo $translator->trans('apples', ['%count%' => 21]); // Выведет: Есть 21 яблоко (потому что 21 % 10 = 1)
4. Использование разных доменов:
# translations/messages.en.yaml
welcome: 'Welcome!'
# translations/validators.en.yaml
invalid_email: 'Invalid email address.'
// ... (предыдущий код, но добавляем ресурс для validators)
$translator->addResource('yaml', __DIR__.'/translations/validators.en.yaml', 'en', 'validators');
// Перевод из домена 'messages'
echo $translator->trans('welcome'); // Выведет: Welcome!
// Перевод из домена 'validators'
echo $translator->trans('invalid_email', [], 'validators'); // Выведет: Invalid email address.
5. Использование XLIFF:
XLIFF (XML Localization Interchange File Format) — это стандартный XML-формат для обмена данными локализации. Он более сложен, чем YAML, но обеспечивает лучшую поддержку инструментов перевода и управления переводами.
<!-- translations/messages.en.xlf -->
<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
<file source-language="en" target-language="en" datatype="plaintext" original="file.ext">
<body>
<trans-unit id="welcome">
<source>Welcome!</source>
<target>Welcome!</target>
</trans-unit>
<trans-unit id="welcome_user">
<source>Welcome, %name%!</source>
<target>Welcome, %name%!</target>
</trans-unit>
</body>
</file>
</xliff>
use Symfony\Component\Translation\Loader\XliffFileLoader;
// ...
$translator->addLoader('xlf', new XliffFileLoader());
$translator->addResource('xlf', __DIR__.'/translations/messages.en.xlf', 'en');
// ...
6. Fallback (Резервные локали):
Можно указать резервные локали. Если перевод для запрошенной локали не найден, транслятор попытается найти перевод в резервных локалях.
$translator = new Translator('fr_FR'); // Локаль по умолчанию
$translator->setFallbackLocales(['fr', 'en']); // Резервные локали
// Если translations/messages.fr_FR.yaml не содержит 'welcome',
// транслятор проверит translations/messages.fr.yaml,
// а затем translations/messages.en.yaml.
7. Кеширование:
Для повышения производительности в production-среде рекомендуется использовать кеширование каталогов сообщений. Symfony предоставляет различные адаптеры кеша (например, ArrayAdapter
, FilesystemAdapter
, PdoAdapter
).
use Symfony\Component\Cache\Adapter\ArrayAdapter; // Пример адаптера кеша
use Symfony\Component\Translation\Translator;
use Symfony\Component\Translation\Loader\YamlFileLoader;
use Symfony\Component\Translation\MessageCatalogue;
$cache = new ArrayAdapter();
// При первом запуске каталог будет создан
$translator = new Translator('en', null, $cache);
$translator->addLoader('yaml', new YamlFileLoader());
$translator->addResource('yaml', __DIR__.'/translations/messages.en.yaml', 'en');
$translator->trans('welcome');
// При последующих запусках каталог будет загружен из кеша,
// что значительно ускорит процесс.
// Очистка кеша (если нужно перестроить каталог):
$cache->clear();
Интеграция с Symfony Framework:
В полноценном Symfony приложении компонент Translation
интегрирован через сервис translator
. Вам не нужно создавать экземпляр Translator
вручную. Вы можете получить доступ к нему через внедрение зависимостей (Dependency Injection):
// В контроллере
use Symfony\Contracts\Translation\TranslatorInterface;
class MyController
{
public function index(TranslatorInterface $translator)
{
$translatedMessage = $translator->trans('my.message.key');
// ...
}
}
Конфигурация перевода в Symfony Framework обычно находится в файле config/packages/translation.yaml
:
# config/packages/translation.yaml
framework:
default_locale: en # Локаль по умолчанию
translator:
default_path: '%kernel.project_dir%/translations' # Путь к каталогам переводов
fallbacks:
- en # Резервные локали
providers: # Если using translation providers, like Lokalise, Crowdin, Loco
# ... configuration for providers
Преимущества использования компонента Translation:
- Централизованное управление переводами: Все переводы находятся в одном месте, что упрощает их поддержку и обновление.
- Поддержка различных форматов: YAML, XLIFF, PHP, Gettext.
- Плюрализация: Корректная обработка множественного числа.
- Заполнители: Динамическая подстановка значений в переводы.
- Резервные локали: Обеспечение перевода, даже если нет перевода для конкретной локали.
- Кеширование: Повышение производительности.
- Интеграция с Symfony Framework: Простое использование в Symfony-приложениях.
- Расширяемость: Возможность создания собственных загрузчиков и других компонентов.
- Поддержка Translation Providers: Легкая интеграция с такими сервисами, как Lokalise, Crowdin, Loco
- Логирование отсутствующих переводов Можно настроить логгер, который будет записывать info об отсутствующих переводах
Компонент Symfony Translation — это мощный инструмент, который значительно упрощает процесс локализации вашего приложения. Он предоставляет все необходимые функции для создания многоязычного интерфейса, а его гибкость и расширяемость позволяют адаптировать его к любым требованиям.