Начинаю цикл статей по организации мультиязычности в Symfony. Мультиязычность достигается с помощью интернационализации и локализации.
Часть 1.1: интернационализация (I18n) — введение
Немного теории (источник Википедия).
Интернационализа́ция (англ. internationalization) — процесс адаптации продукта, такого как программное или аппаратное обеспечение, к языковым и культурным особенностям региона (регионов), отличного от того, в котором разрабатывался продукт. В английском языке для слова «internationalization» принято сокращение «i18n». При этом число 18 означает количество пропущенных между «i» и «n» букв.
Локализа́ция (англ. localization) — перевод и адаптация элементов интерфейса, вспомогательных файлов и документации. В английском языке для слова «localization» иногда применяется сокращение «l10n». При этом число 10 означает количество пропущенных между «l» и «n» букв.
Собственно хорошая поддержка интернационализации в Symfony на фоне других систем, а также многие другие возможности помогли мне остановиться на этом замечательном фреймворке :).
Хочу поделиться моим небольшим опытом и достигнутыми результатами упрощения организации работы с I18n в Symfony. Весь материал разбил на несколько частей.
Использовалась Symfony 1.1 и Propel 1.3.
Мои требования к интернационализации (I18n) для фреймворка:
1) Локализация интерфейса сайта
2) Интернационализации данных (новости, статьи, продукция,…)
3) Административная панель: редактирование локализации интерфейса
4) Административная панель: редактирование данных с учетом интернационализации
5) Простота использования, гибкость (возможность легко добавить новый язык), производительность
6) Работать с локализацией через БД (MySQL), в частности через PDO (Propel 1.3), используя открытый коннект к БД
Symfony практически «справляется» со всеми требованиями. Но для некоторых процессов пришлось кое-что изменить, доработать. Добился ли я выполнения поставленных задач? ДА!!!!!
По умолчанию доступен один язык, и его можно активировать через настройки: frontend/config/settings.yml
Листинг 1.1: настройка «культуры» по умолчанию
all: .settings: default_culture: ru_RU # или uk_UA
Не забудьте сбросить кеш.
Формат записи (локали): uk_UA — язык и код страны.
Таким образом, мы говорим, какой профиль использовать для интернационализации.
Список всех профилей можно найти в ядре Symfony: /symfony-1.1/lib/i18n/data/
Теперь если использовать Helpers, которые работают с I18n (календарь, список стран, дата…) мы на выходе получим тексты не в английском языке по умолчанию, а в украинском.
Листинг 1.2: получение текущей «культуры»
$culture = $this->getUser()->getCulture();
Часть 1.2: организация итернационализации (I18n) контента в Symfony
Сначала расскажу, как организована интернационализация данных, а после вернемся к локализации интерфейса в других частях.
Вначале наши данные без поддержки I18n имеют следующий вид.
Листинг 1.3: схема таблицы «Статьи» (schema.yml)
propel: _attributes: { package: lib.model.article } article: id: ~ slug: { type: varchar, size: 255, required: true } image_url: { type: varchar, size: 255, required: true } title: { type: varchar, size: 255, required: true } announce: { type: text, required: true } full_text: { type: text, required: true } created_at: ~
Листинг 1.4: Маршрутизация (routing.yml):
article: url: /articles/:year/:month/:day/:slug param: { module: article, action: index }
Ссылка на статью имела бы следующий вид: http://tigor.com.ua/articles/2008/10/28/i18n_hello_world
Добавляем интернационализацию.
Листинг 1.4: Маршрутизация с поддержкой I18n (routing.yml)
article: url: /:sf_culture/articles/:year/:month/:day/:slug param: { module: article, action: index } requirements: { sf_culture: (?:ru|uk|en) }
Указываем к примеру 3-и языка: русский, украинский, английский. Если ввести что-то другое вместо языка, то страница будет не найдена, и получим код ошибки 404.
Теперь ссылка будет вот такая:
• http://tigor.com.ua/en/articles/2008/10/28/i18n_hello_world
• http://tigor.com.ua/ru/articles/2008/10/28/i18n_hello_world
• http://tigor.com.ua/uk/articles/2008/10/28/i18n_hello_world
Но контент все еще на одном языке. Делаем правки схемы.
Листинг 1.5: схема с поддержкой I18n (schema.yml)
propel: _attributes: { package: lib.model.article } article: _attributes: { phpName: Product, isI18N: true, i18nTable: article _i18n } id: ~ slug: { type: varchar, size: 255, required: true } image_url: { type: varchar, size: 255, required: true } created_at: ~ article _i18n: id: { type: integer, required: true, primaryKey: true, foreignTable: article, foreignReference: id, onDelete: cascade, onUpdate: cascade } culture: { isCulture: true, type: varchar, size: 7, required: true, primaryKey: true } title: { type: varchar, size: 255, required: true } announce: { type: text, required: true } full_text: { type: text, required: true }
В Листинге 1.5 для таблицы article _i18n сознательно указаны id и culture, чтобы отобразить, что же Symfony вставляет при указании опции isI18N. Эти поля указывать не стоит, дабы не совершать ошибки. Но в исключительных это может понадобиться.
Листинг 1.6: Небольшие примеры работы с объектом Article
// Чтение данных $article = ProductPeer::retrieveByPk(1); $title = $article ->getTitle(); // По умолчанию испольщуется текущая культура, или переопределенная через машрутизацию $title = $article ->getTitle(‘en’); // Явно указываем язык // Изменение данных $article = ProductPeer::retrieveByPk(1); $article->setTitle(‘Мир во всем мире!’, ‘ru’); $article->save();
Ссылки по теме:
• Symfony: интернационализация (I18n) / часть 2 – редактирование данных в административной панели
• Википедия: Интернационализация
• Википедия: Локализация
• Wikipedia: Internationalization_and_localization
• The Definitive Guide to symfony: Chapter 13 — I18n And L10n
Ноябрь 6th, 2008 at 06:14
Большое спасибо за статью!
Игорь, скажите — у Вас был опыт локализации интерфейса, генерируемого «Admin Generator», который поставляется с Symfony?
То есть кнопки вида «Edit», «Delete», «Create», надписи об успешном добавлении/изменении и т.п.
Дело в том, что мне не удалось, даже при указанной «культуре» в настройках, локализовать его.
Ноябрь 6th, 2008 at 13:08
Мне тоже очень нравится подход, который используется в Symfony для поддержки мультиязычности. Все просто и удобно.
Ноябрь 7th, 2008 at 00:34
Re: Дармен Аманбаев
Да это можно сделать. Все тексты в админке выводяться через функцию локализации __($name). В этом случае надо локализировать админку как и сам сайт. Некоторые тексты можно задать через файлы generator.yml, остальное только через локализацию (i18n).
Ноябрь 11th, 2008 at 00:33
[…] темы мультиязычности в Symfony: первой части, где рассказывались основы работы с […]
Ноябрь 15th, 2008 at 15:12
у меня стоит сандбокс 1.1 я создал схему по этому примеру прописал настройки все как по примеру только заменил их на ru. но по какой-то причине в админке язык на русский не переводится при экшене лист. вопрос как сделать админку всю на русском. и как сделать переключение между языками в админке
Ноябрь 17th, 2008 at 09:31
2Igor: Чтобы админку перевести на русский язык, надо:
1) Сделать локализацию для неё
2) Использовать русские фразы в generator.yml
Переключение можно сделать так, к примеру через параметр /admin/?lang=ru -а в контролере менять культуру, или так /admin/ru/
Декабрь 1st, 2008 at 15:12
В документации написанно что словари (в случае использования XLIFF) могут находиться в директориях модулей.
http://www.symfony-project.org/book/1_1/13-I18n-and-L10n
Another way to organize translation dictionaries is to split them by module. Instead of writing a single messages.XX.xml file for the whole application, you can write one in each modules/[module_name]/i18n/ directory. It makes modules more independent from the application, which is necessary if you want to reuse them, such as in plug-ins (see Chapter 17).
У меня не получаеться заставить его работать таким образом. Я что-то упустил?
Декабрь 1st, 2008 at 16:34
У меня тоже не получилось этого сделать. Папка i18n находиться в самом apps. Как вариант можно создавать отдельный файлы для модулей и вызывать < ?php echo __('Welcome to our website', null, 'navigation') ?>: navigation — этот самый файл.
Декабрь 1st, 2008 at 17:13
Понятно. Я так и сделал уже… Потом поробую разобраться, может получиться все-таки в папку с модулем закинуть словарь