Symfony2 компоненты перевода

Если вы когда-либо работали над созданием сайта, который должен быть доступен на нескольких языках, то вы знаете, как трудно это сделать. С помощью компонентов перевода Symfony2 можно легко сделать сайт на разных сайтах. В статье показано, некоторые примеры кода и некоторые обсуждения его API.

Базовый пример Symfony2

Давайте начнем с создания файла translation.php с содержанием ниже.



<?php
require 'vendor/autoload.php';
use Symfony\Component\Translation\Translator,
   Symfony\Component\Translation\Loader\ArrayLoader;

$translator = new Translator('fr_FR');
$translator->addLoader('array', new ArrayLoader());
$translator->addResource('array', array(
   'Hello World!' => 'Bonjour tout le monde!',
   ),
   'fr_FR'
);

echo $translator->trans('Hello World!') . "\n";
echo $translator->trans('How are you?') . "\n"; ?>


Объект Translator в данном примере французский/Франция и, опционально, экземпляр объекта MessageSelector в качестве второго аргумента. MessageSelector используется для pluralization . Если вы не одного не создали, Переводчик конструктор создает свои собственные.

После устанавливается загрузчик, который используется для загрузки строк языка. Метод AddLoader() использует имя (вы можете назвать по разному) и объекты типа LoaderInterface. В этом данном случае используется ArrayLoader который реализует интерфейс.

Метод AddResource() добавляет перевод сообщений. Первым аргументом является имя загрузчика addLoader() , а второй аргумент представляет собой массив (так как мы используем ArrayLoader ). В зависимости от загрузчика, второй аргумент может измениться. Третий аргумент является строки языка.

Поиск перевода, производится через метод trans() . Если соответствующий перевод найден, будет возвращена исходная строка.

Перевод обычно не делается программистами. Вместо этого они пользуются профессиональными переводчиками. Переводчики могут не иметь знаний в области программирования, и нам не нужно давать им код. К счастью, Symfony2 может использовать различные загрузчики, из которых списки переводов будут загружены. Полный список поддерживаемых загрузчиков ArrayLoader , CsvFileLoader , MoFileLoader , XliffFileLoader , IcuDatFileLoader , PhpFileLoader , YamlFileLoader , IcuResFileLoader , PoFileLoader , IniFileLoader , и QtTranslationsLoader .

Давайте посмотрим, как загрузить строки перевода, используя PoFileLoader вместо массива что бы было проще понять людям, которые переводят.

Изменение второго аргумента addLoader() к экземпляру объекта PoFileLoader . Кроме того, в методе AddResource() , указать путь, где находится файл po .



<?php
require 'vendor/autoload.php';
use Symfony\Component\Translation\Translator,
   Symfony\Component\Translation\Loader\PoFileLoader;

$translator = new Translator('fr_FR');
$translator->addLoader('pofile', new PoFileLoader());
$translator->addResource('pofile', 'languages/po/fr_FR.po', 'fr_FR');
?>


Обработка резервного Языка

Вы можете использовать класс PHP-Locale для получения требуемой локализации из строки заголовка Accept-Language, или использовать компонент Symfony Locale (который расширяет класс PHP с некоторой дополнительной функциональностью), установить локализацию динамично.



<?php
$locale = Locale::acceptFromHttp($_SERVER['HTTP_ACCEPT_LANGUAGE']);
$translator = new Translator($locale); ?>



Но что, если язык недоступен? Вы можете установить резервную локализацию с помощью метода setFallbackLocale() . Если язык не найден, или язык существует, но отсутствует перевод, то переводчик будет смотреть на запасной вариант.



<?php
$translator->setFallbackLocale('fr'); ?>


Тот же самый язык может отличаться между странами; рассмотрим английский, например, и вы заметите, en_GB для британского_английского, en_US для английского_американского, и т.д. Каждый язык может иметь различия в зависимости от региона.

В случае запрашиваемого региона язык fr_CA , а вы не имеете перевода fr_CA . В качестве запасного варианта, вы могли бы попытаться получить переводы из fr_FR , и если нет, то от en_US , и тогда общий английский..



<?php
$translator->setFallbackLocale(array('fr_FR', 'en_US', 'en')); ?>


Могут быть случаи, когда вы хотите разделить сообщения одного региона на множество мелких частей. По умолчанию, все строки будут добавлены и пересмотрены в сообщениях области (именно поэтому мы не должны передать домен в trans() ).

Названия для файлов с переводом: domain . localeformat , например messages.fr.po, navigation.fr.po, и т.д. Если вы хотите получить переводы из определенного домена, то вы должны указать домен в качестве третьего аргумента в trans() . Откаты происходят в пределах одного домена, а не к другим регионом.

Все вместе это выглядит следующим образом:



<?php
require 'vendor/autoload.php';
use Symfony\Component\Translation\Translator,
   Symfony\Component\Translation\Loader\PoFileLoader;

$locale = Locale::acceptFromHttp($_SERVER['HTTP_ACCEPT_LANGUAGE']);
$translator = new Translator($locale);
$translator->setFallbackLocale(array('fr_FR', 'en_US', 'en'));

$translator->addLoader('pofile', new PoFileLoader());
$iterator = new FilesystemIterator("languages/po");
$filter = new RegexIterator($iterator, '/\.(po)$/');
foreach($filter as $entry) {
    $name = $entry->getBasename('.po');
    list($domain, $locale) = explode('.', $name);
    $translator->addResource('pofile',
        $entry->getPathname(), $locale, $domain
    );
}

echo $translator->trans('Hello World!') . "\n";
echo $translator->trans('How are you?') . "\n";
echo $translator->trans('How are you?', array(), 'navigation') . "\n"; ?>


Если вы назвали файлы перевода с регионами, например fr_FR.po , fr_CA.po и т.д., то это может быть хорошей идеей, чтобы назвать некоторые из ваших откатов исключительно языком (fr.po). Рассмотрим пример, если кто-то из Бельгии, который находится с визитом на вашем сайте и заголовок Accept-Language запросит fr_BE . У вас нет fr_BE , и fr_FR не будет соответствовать. Это возврат к fr.po , чем переход на другой язык полностью, допустим английский язык.

Язык только с именем резерва могут быть извлечены из языка и поставлен во главе массива следующим образом:



<?php
$fallbacks = array('fr_FR', 'en_US', 'en');
$locale = Locale::acceptFromHttp($_SERVER['HTTP_ACCEPT_LANGUAGE']);
array_unshift($fallbacks, substr($locale, 0, 2));
$translator->setFallbackLocale($fallbacks); ?>


Pluralization

Обработка формы множественного числа, является одной из сложнейших частей Интернационализации. Для выбора разных переводов, основанных по номеру, вы используете метод transChoice() . Вот пример, чтобы продемонстрировать его использования:



<?php
$value = 1;
echo $translator->transChoice(
   '[-Inf, 0]There is nothing to delete|{1}Are you sure you want to delete this file|]1,10[ %count% files will be deleted|[10,Inf] Are you sure you want to delete all files',
  $value,
  array('%count%' => $value)
) . "\n"; ?>


Альтернативные строки, разделенные вертикальной чертой. Нужно изменить значение $value и посмотреть, как переводчик изменяет выход. Сначала вы должны получить сообщение “Are you sure you want to delete this file” (Вы уверены, что хотите удалить этот файл). Если вы измените значение $value 2 до 9 вы получите сообщение “$value files will be deleted” (файлы $value будут удалены). Если вы используете 10 или больше вы получите сообщение «Are you sure you want to delete all files» (Вы уверены, что хотите удалить все файлы). Если значение $value , чем 1 вы получите “There is nothing to delete” (Нет ничего, для удаления).

Symfony перевода использует обозначение ISO 31-11 так выше использует интервал классов, чтобы выбрать правильный направление. Мы можем написать диапазоны вроде этого:



[a, b] means a <= x <= b
[a, b[ means a <= x < b
]a, b] means  a < x <= b
]a, b[ means a < x < b


Полезный мнемонический прием, чтобы легче понять диапазон, чтобы посмотреть, в каком направлении квадратная скобка открывается с какой стороны. Если квадратная скобка открывается на номер, то это включительно.



[3 means value is <= 3 (inclusive)
]3 means value is < 3 (exclusive)


Вы также можете определить набор конкретных значений в фигурные скобки, например {1,2,3}, чтобы соответствовать только значению 1, 2 и 3.

Преобразование между форматами перевода

В начале статьи, используется ArrayLoader , потому что, вероятно, для начала это самый простой способ из большинства разработок. Но потом продолжили с PoFileLoader, потому что po файлы проще для переводчиков. Что делать, если у вас есть набор переводов как массивы, или даже другой формат, такой как YAML, и вы хотите, преобразовать их? Вы можете конвертировать один формат, а другой для любого из загрузчиков Symfony с помощью dumpers (самовыгружаемых).



<?php
require 'vendor/autoload.php';
   Symfony\Component\Translation\Loader\YamlFileLoader,
   Symfony\Component\Translation\MessageCatalogue,
   Symfony\Component\Translation\Dumper\PoFileDumper;

$loader = new YamlFileLoader();
$iterator = new FilesystemIterator("languages/yaml");
$filter = new RegexIterator($iterator, '/\.(yml)$/');
foreach($filter as $file) {
    $name = $file->getBasename('.yml');
    list($domain, $locale) = explode('.', $name);
    $array = $loader->load($file->getPathname(), $locale, $domain);
    $catalogue = new MessageCatalogue($locale);
    $catalogue->addCatalogue($array);

    $dumper = new PoFileDumper();
    $dumper->dump($catalogue, array('path'=> __DIR__ . '/languages/pofile'));
} ?>


Просто замените загрузчик с соответствующем томом, который вы используете для входа и dumpers все выходные которые вам нужны.

В заключение

В статье было рассмотрено, как подключать строки с переводом, как работать с запасной локализацией, как выполняется pluralization , и, как использовать dumper. Я надеюсь, это руководство поможет вам начать работу с интернационализацией, которая выполняется легко с помощью Symfony компонентом перевода.

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Можно использовать следующие HTML -теги и атрибуты: <a href= http://pixelcom.crimea.ua/"" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>