ZFConf 2010




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

                       Степан Танасийчук
                        ceo@s...
Чем я занимаюсь?

                  Web разработкой занялся в
                   2003 году
                  С Zend Fram...
Содержание доклада

   Простейшее подключение Zend_Translate
   Работа с view хелпером translate
   Plural forms или фо...
Самый простой вариант подключения
Zend_Translate

   Добавляем в application.ini следующие настройки:
    resources.trans...
Создаем файл переводов для русского
языка

   Структура каталога languages:
    ./application/languages/
    `-- ru
     ...
Почему ”Привет”, а не ”Hello”?

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

   Для этого нужно указать язык или локаль в последнем
    аргумен...
Plural forms или формы
множественного числа

   Поддержка plural forms есть в адаптерах:
      Array
        Csv
     ...
Plural Forms (продолжение)

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

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

   Создаем новый каталог Файл→Создать каталог.
   Указываем необходимые настройки:
Работаем с poedit. Настройка каталога
(продолжение)

   Обязательно указывайте формы множественного числа для
    каждого...
Работаем с poedit. Пути

   На вкладке «Пути» указываем путь к каталогу проекта или
    пути к каталогам которые нужно ск...
Работаем poedit. Ключевые слова

   Также добавляем названия функций, строковые аргументы
    которых должны добавлятся в...
Работаем с poedit. Сканировать *.phtml

   Чтобы xgettext парсил *.phtml шаблоны нужно добавить это
    расширение в наст...
Для чего я добавил plural:1,2?

   Я не успел разобраться как заставить парсер xgettext
    доставать строки из такой кон...
Работаем с Poedit. Обновляем каталог
из исходных файлов

   Сохраняем каталог ./application/languages/ru/application.po
...
Работаем с Poedit. Добавляем
переводы и сохраняем каталог

                     Сохраняем результат. В
                  ...
Ньюансы и хаки для работы с gettext

   Лейблы формы нужно оборачивать в _(). Пример:
    $username = $form->createElemen...
Перевод сообщений валидаторов для
адаптеров != array

 Раньше мы делали отдельный файлик, который содержал
 все сообщения ...
Перевод сообщений валидаторов для
адаптера array

   Для array все намного проще. Добавляем в Bootstrap.php
    такой мет...
Варианты передачи языка в URL

   Язык на поддомене:
      en.wikipedia.org
       ru.wikipedia.org
   Язык в поддирек...
Язык на поддомене

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

 preorder.it/ru/ и preorder.it/en/
 +
   Достаточно просто реализовать в ZF.
        Хорошо подход...
Несколько строчек кода, которые
делают приложение быстрее :)

   Если есть возможность что-то закешировать, значит нужно
...
Upcoming SlideShare
Loading in …5
×

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

8,293 views

Published on

  • Понравилось. Полезно. обязательно буду юзать. Спасибо
    ЗЫ на 24м слайде опечака в слове 'географические'
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here

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

  1. 1. ZFConf 2010 Zend Framework и мультиязычность Степан Танасийчук ceo@stfalcon.com
  2. 2. Чем я занимаюсь?  Web разработкой занялся в 2003 году  С Zend Framework начал работать в 2008 году  Руковожу собственной веб- студией с 2009 года  Активный участник сообщества zendframework.ru  Люблю прикольные смайлы :]
  3. 3. Содержание доклада  Простейшее подключение Zend_Translate  Работа с view хелпером translate  Plural forms или формы множественного числа  Почему я отдаю предпочтение gettext?  Работаем с poedit  Хаки для работы с gettext  Перевод сообщений валидаторов  Сравнение различных схем передачи языка в URL  Zend_Translate и кеширование
  4. 4. Самый простой вариант подключения 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'); }
  5. 5. Создаем файл переводов для русского языка  Структура каталога languages: ./application/languages/ `-- ru `-- application.php  Файл переводов: ./application/languages/ru/application.php <?php return array( 'Hello' => 'Привет', );  Результат: Привет
  6. 6. Почему ”Привет”, а не ”Hello”?  Потому что в моих настройках браузера русский язык по приоритету выше английского:
  7. 7. Отдельные можно выводить сообщения на указанном языке  Для этого нужно указать язык или локаль в последнем аргументе vie хелпера translate(): ./application/controllers/IndexController.php public function indexAction() { echo $this->view->translate('Hello', 'en_GB'); // или echo $this->view->translate('Hello', 'en'); }  Результат: Hello Эту возможность удобно использовать при формировании текстов для многоязычной рассылки.
  8. 8. 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'); }
  9. 9. Plural Forms (продолжение)  Обновим файл переводов для русского языка: ./application/languages/ru/application.php <?php return array( 'Hello' => 'Привет', 'left before the conference' => 'осталось до начала конференции', '%s day' => array( '%s день', '%s дня', '%s дней' ) );  Результат: Привет! 5 дней осталось до начала конференции
  10. 10. Почему я отдаю предпочтение gettext?  В коде отображаются оригиналы сообщений. Пример сообщения в view шаблоне: <h2><?php echo $this->translate('Create new brand'); ?>:</h2>  Не нужно искать где и какие строки были добавлены или удалены в исходном коде — gettext сам найдет все изменения.  Есть готовые программы для работы с файлами переводов (особенно актуально для НЕпрограммистов). Достаточно предоставить заказчику или перводчику .po файл и программу для его редактирования (например кроссплатформенная Poedit).
  11. 11. Работаем с poedit. Настройки каталога  Создаем новый каталог Файл→Создать каталог.  Указываем необходимые настройки:
  12. 12. Работаем с 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)
  13. 13. Работаем с poedit. Пути  На вкладке «Пути» указываем путь к каталогу проекта или пути к каталогам которые нужно сканировать:
  14. 14. Работаем poedit. Ключевые слова  Также добавляем названия функций, строковые аргументы которых должны добавлятся в языковый файл (вкладка «Ключевые слова»):
  15. 15. Работаем с poedit. Сканировать *.phtml  Чтобы xgettext парсил *.phtml шаблоны нужно добавить это расширение в настройки анализатора PHP в Правка→Параметры→Анализаторы *.php;*.phtml
  16. 16. Для чего я добавил plural:1,2?  Я не успел разобраться как заставить парсер xgettext доставать строки из такой конструкции: $this->view->translate(array('%s day', '%s days', $count)  Но он успешно достает их из конструкции вида: $this->view->translate()->getTranslator()->plural('%s day', '%s days', $count)
  17. 17. Работаем с Poedit. Обновляем каталог из исходных файлов  Сохраняем каталог ./application/languages/ru/application.po  И обовляем его Каталог→Обновить из исходного кода  Получаем следующую картину:
  18. 18. Работаем с Poedit. Добавляем переводы и сохраняем каталог  Сохраняем результат. В параметрах должна быть отмечена опция ”При сохранении автоматически компилировать файл .mo”.  В application.ini меняем адаптер на: resources.translate.adapter = "gettext"  Запускаем: Привет! 5 дней осталось до начала конференции
  19. 19. Ньюансы и хаки для работы с 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', )
  20. 20. Перевод сообщений валидаторов для адаптеров != array Раньше мы делали отдельный файлик, который содержал все сообщения обернутые в _(): _("A record matching "%value%" was found"); _("Password and confirmed password do not match."); xgettext этот файл парсил, а мы переводили и компилировали .mo файл, который уже подключали ко всем проектам. Теперь в ZF появилась папочка resources, в которой лежат переводы сообщений валидаторов. Но как ихподключить если для основного сайта используется адаптер отличный от array я пока не успел разобраться. Думаю, что вскоре эта проблема будет решена и решение будет опубликовано на сайте или форуме http://zendframework.ru
  21. 21. Перевод сообщений валидаторов для адаптера 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; }
  22. 22. Варианты передачи языка в URL  Язык на поддомене:  en.wikipedia.org  ru.wikipedia.org  Язык в поддиректории:  1й вариант: mota.ru – русский  mota.ru/en/ – английский  2й вариант:  preorder.it – ”auto” или по базе GeoIP  preorder.it/ru/ – русский  preorder.it/en/ – английский
  23. 23. Язык на поддомене +  Ускоренная индексация.  Для доменов первого уровня, которые не имеют георгафической привязки можно настроить разные географические цели для каждой языковой версии сайта (в Google Webmaster Tools).  Вес с основного домена передается на поддомены.  Сайты можно разнести на разные сервера и делать независимые изменения в коде. -  Бюджет на продвижение и эффект от него будет дробиться на все сайты.
  24. 24. Язык в поддиректории preorder.it/ru/ и preorder.it/en/ +  Достаточно просто реализовать в ZF.  Хорошо подходит для сайтов-услуг.  Идет продвижения одного домена, т.е. тот же бюджет что и в первом варианте даст больший эффект. -  Более медленная индексация.  Нельзя сделать разные георгафические цели для разных языковых версий сайта.  С технической стороны будет проблематично разнести разные языковые версии сайта на разные сервера.
  25. 25. Несколько строчек кода, которые делают приложение быстрее :)  Если есть возможность что-то закешировать, значит нужно её использовать: $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);

×