25
Zend Framework и мультиязычность Степан Танасийчук [email protected] 27 марта 2010 г. Санкт- Петербург

ZFConf 2010: Zend Framework and Multilingual

Embed Size (px)

DESCRIPTION

 

Citation preview

Page 1: ZFConf 2010: Zend Framework and Multilingual

Zend Framework и мультиязычность

Степан Танасийчук[email protected]

27 марта 2010 г.

Санкт-Петербург

Page 2: ZFConf 2010: Zend Framework and Multilingual

Чем я занимаюсь?

Web разработкой занялся в 2003 году

С Zend Framework начал работать в 2008 году

Руковожу собственной веб-студией с 2009 года

Активный участник сообщества zendframework.ru

Люблю прикольные смайлы :]

Page 3: ZFConf 2010: Zend Framework and Multilingual

Содержание доклада

Простейшее подключение Zend_Translate Работа с view хелпером translate Plural forms или формы множественного числа Почему я отдаю предпочтение gettext? Работаем с poedit Хаки для работы с gettext Перевод сообщений валидаторов Сравнение различных схем передачи языка в URL Zend_Translate и кеширование

Page 4: ZFConf 2010: Zend Framework and Multilingual

Самый простой вариант подключения Zend_Translate

Добавляем в application.ini следующие настройки:resources.translate.data = APPLICATION_PATH "/languages"

resources.translate.adapter = "array"

resources.translate.locale = "auto"

resources.translate.options.scan = "directory"

resources.translate.options.disableNotices = true

Редактриуем IndexAction() в дефолтном контроллере:./application/controllers/IndexController.php

public function indexAction()

{

echo $this->view->translate('Hello');

}

Page 5: ZFConf 2010: Zend Framework and Multilingual

Создаем файл переводов для русского языка

Структура каталога languages:./application/languages/

`-- ru

`-- application.php

Файл переводов:./application/languages/ru/application.php

<?php

return array(

'Hello' => 'Привет',

);

Результат:Привет

Page 6: ZFConf 2010: Zend Framework and Multilingual

Почему ”Привет”, а не ”Hello”?

Потому что в моих настройках браузера русский язык по приоритету выше английского:

Page 7: ZFConf 2010: Zend Framework and Multilingual

Отдельные можно выводить сообщения на указанном языке

Для этого нужно указать язык или локаль в последнем аргументе view хелпера translate():

./application/controllers/IndexController.php

public function indexAction() {

echo $this->view->translate('Hello', 'en_GB');

// или

echo $this->view->translate('Hello', 'en');

}

Результат:Hello

Эту возможность удобно использовать при формировании текстов для многоязычной рассылки.

Page 8: ZFConf 2010: Zend Framework and Multilingual

Plural forms или формы множественного числа

Поддержка plural forms есть в адаптерах: Array Csv Gettext

Разберем на примере:./application/controllers/IndexController.php

public function indexAction()

{

echo $this->view->translate('Hello') . '! ';

$count = 5;

echo sprintf($this->view->translate(array('%s day', '%s days', $count)), $count) . ' ' . $this->view->translate('left before the conference');

}

Page 9: ZFConf 2010: Zend Framework and Multilingual

Plural Forms (продолжение)

Обновим файл переводов для русского языка:./application/languages/ru/application.php

<?php

return array(

'Hello' => 'Привет',

'left before the conference' => 'осталось до начала конференции',

'%s day' => array(

'%s день',

'%s дня',

'%s дней'

)

);

Результат:Привет! 5 дней осталось до начала конференции

Page 10: ZFConf 2010: Zend Framework and Multilingual

Почему я отдаю предпочтение gettext?

В коде отображаются оригиналы сообщений. Пример сообщения в view шаблоне:

<h2><?php echo $this->translate('Create new brand'); ?>:</h2>

Не нужно искать где и какие строки были добавлены или удалены в исходном коде — gettext сам найдет все изменения.

Есть готовые программы для работы с файлами переводов (особенно актуально для НЕпрограммистов). Достаточно предоставить заказчику или перводчику .po файл и программу для его редактирования (например кроссплатформенная Poedit).

Page 11: ZFConf 2010: Zend Framework and Multilingual

Работаем с poedit. Настройки каталога

Создаем новый каталог Файл→Создать каталог. Указываем необходимые настройки:

Page 12: ZFConf 2010: Zend Framework and Multilingual

Работаем с poedit. Настройка каталога (продолжение)

Обязательно указывайте формы множественного числа для каждого перевода!

Полный список форм можно найти на странице http://translate.sourceforge.net/wiki/l10n/pluralforms

Например для русского:

nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 or n%100>=20) ? 1 : 2)

для немецкого:

nplurals=2; plural=(n != 1)

Page 13: ZFConf 2010: Zend Framework and Multilingual

Работаем с poedit. Пути

На вкладке «Пути» указываем путь к каталогу проекта или пути к каталогам которые нужно сканировать:

Page 14: ZFConf 2010: Zend Framework and Multilingual

Работаем poedit. Ключевые слова

Также добавляем названия функций, строковые аргументы которых должны добавлятся в языковый файл (вкладка «Ключевые слова»):

Page 15: ZFConf 2010: Zend Framework and Multilingual

Для чего я добавил plural:1,2?

Я не знаю как заставить парсер xgettext доставать строки из такой конструкции:

$this->view->translate(array('%s day', '%s days', $count)

Но он успешно достает их из конструкции вида:$this->view->translate()->getTranslator()->plural('%s day', '%s days',

$count)

Page 16: ZFConf 2010: Zend Framework and Multilingual

Работаем с Poedit. Обновляем каталог из исходных файлов

Сохраняем каталог ./application/languages/ru/application.po И обовляем его Каталог→Обновить из исходного кода Получаем следующую картину:

Page 17: ZFConf 2010: Zend Framework and Multilingual

Работаем с Poedit. Добавляем переводы и сохраняем каталог

Сохраняем результат. В параметрах должна быть отмечена опция ”При сохранении автоматически компилировать файл .mo”.

В application.ini меняем адаптер на:

resources.translate.adapter = "gettext"

Запускаем:Привет! 5 дней осталось до начала конференции

Page 18: ZFConf 2010: Zend Framework and Multilingual

Ньюансы и хаки для работы с gettext

Лейблы формы нужно оборачивать в _(). Пример:$username = $form->createElement('text', 'username');

$username->setLabel(_('Имя пользователя'));

Только что подумал о том, что setLabel тоже можно добавить в ключевые слова :).

Та же ситуация с названиями пунктов меню для Zend_Navigation:

array(

'controller' => 'users',

'action' => 'list',

'resource' => 'mvc:users',

'privilege' => 'list',

'label' => _('Users'),

'route' => 'default',

)

Page 19: ZFConf 2010: Zend Framework and Multilingual

Перевод сообщений валидаторов для адаптеров != array

Раньше мы делали отдельный файлик, который содержал все сообщения валидаторов обернутые в _():

_("A record matching \"%value%\" was found");

_("Password and confirmed password do not match.");

xgettext этот файл парсил, а мы переводили и компилировали .mo файл, который уже подключали ко всем проектам.

Теперь в ZF появилась папочка resources, в которой лежат переводы сообщений валидаторов. Но как ихподключить если для основного сайта используется адаптер отличный от array я пока не разобрался. Думаю, что вскоре разберусь и решение будет опубликовано на сайте или форуме http://zendframework.ru

Page 20: ZFConf 2010: Zend Framework and Multilingual

Перевод сообщений валидаторов для адаптера array

Для array все намного проще. Добавляем в Bootstrap.php такой метод:

/**

* Init translator to Zend_Validate

* @return Zend_Translate

*/

public function _initZendValidateTranslator()

{

$this->bootstrap('translate');

$translate = $this->getResource('translate');

$translate->addTranslation(APPLICATION_PATH . '/../resources/languages');

return $translate;

}

Page 21: ZFConf 2010: Zend Framework and Multilingual

Варианты передачи языка в URL

Язык на поддомене (Zend_Controller_Router_Route_Hostname): en.wikipedia.org ru.wikipedia.org

Язык в поддиректории: 1й вариант (CyEngine_Controller_Router_Route_Multilingual):

mota.ru – русский mota.ru/en/ – английский

2й вариант (переопределяем Zend_Controller_Router_Route): preorder.it – ”auto” или по базе GeoIP preorder.it/ru/ – русский preorder.it/en/ – английский

Page 22: ZFConf 2010: Zend Framework and Multilingual

Язык на поддомене +/-

+ Ускоренная индексация. Для доменов первого уровня, которые не имеют

географической привязки можно настроить разные географические цели для каждой языковой версии сайта (в Google Webmaster Tools).

Вес с основного домена передается на поддомены. Сайты можно разнести на разные сервера и делать

независимые изменения в коде.

- Бюджет на продвижение и эффект от него будет

дробиться на все сайты.

Page 23: ZFConf 2010: Zend Framework and Multilingual

Язык в поддиректории +/-

+ Достаточно просто реализовать в ZF. Хорошо подходит для сайтов-услуг. Идет продвижения одного домена, т.е. тот же бюджет

что и в первом варианте даст больший эффект.

- Более медленная индексация. Нельзя сделать разные географические цели для

разных языковых версий сайта. С технической стороны будет проблематично разнести

разные языковые версии сайта на разные сервера.

Page 24: ZFConf 2010: Zend Framework and Multilingual

Несколько строчек кода, которые делают приложение быстрее :)

Если есть возможность что-то закешировать, значит нужно её использовать:

$cache = Zend_Cache::factory(

'Core',

'File',

array(

'caching' => true,

'automatic_serialization' => true,

'lifetime' => 3600,

),

array(

'cache_dir' => realpath(APPLICATION_PATH . '/../tmp'),

)

);

Zend_Translate::setCache($cache);

Page 25: ZFConf 2010: Zend Framework and Multilingual

The end

Благодарю за внимание!Задавайте ваши вопросы ;)

Степан Танасийчук[email protected]