SlideShare a Scribd company logo
1 of 25
Download to read offline
ZFConf 2010




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

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

                  Web разработкой занялся в
                   2003 году
                  С Zend Framework начал
                   работать в 2008 году
                  Руковожу собственной веб-
                   студией с 2009 года
                  Активный участник сообщества
                   zendframework.ru
                  Люблю прикольные смайлы :]
Содержание доклада

   Простейшее подключение Zend_Translate
   Работа с view хелпером translate
   Plural forms или формы множественного числа
   Почему я отдаю предпочтение gettext?
   Работаем с poedit
   Хаки для работы с gettext
   Перевод сообщений валидаторов
   Сравнение различных схем передачи языка в URL
   Zend_Translate и кеширование
Самый простой вариант подключения
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');
    }
Создаем файл переводов для русского
языка

   Структура каталога languages:
    ./application/languages/
    `-- ru
        `-- application.php


   Файл переводов:
    ./application/languages/ru/application.php
    <?php
    return array(
          'Hello' => 'Привет',
    );


   Результат:
    Привет
Почему ”Привет”, а не ”Hello”?

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

   Для этого нужно указать язык или локаль в последнем
    аргументе vie хелпера translate():
    ./application/controllers/IndexController.php
    public function indexAction() {
         echo $this->view->translate('Hello', 'en_GB');
        // или
        echo $this->view->translate('Hello', 'en');
    }


   Результат:
    Hello

    Эту возможность удобно использовать при
    формировании текстов для многоязычной рассылки.
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');
    }
Plural Forms (продолжение)

   Обновим файл переводов для русского языка:
    ./application/languages/ru/application.php
    <?php
    return array(
          'Hello' => 'Привет',
          'left before the conference' => 'осталось до начала конференции',
          '%s day' => array(
                '%s день',
                '%s дня',
                '%s дней'
          )
    );


   Результат:
    Привет! 5 дней осталось до начала конференции
Почему я отдаю предпочтение gettext?

   В коде отображаются оригиналы сообщений. Пример
    сообщения в view шаблоне:
    <h2><?php echo $this->translate('Create new brand'); ?>:</h2>


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

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

   Создаем новый каталог Файл→Создать каталог.
   Указываем необходимые настройки:
Работаем с 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)
Работаем с poedit. Пути

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

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

   Чтобы xgettext парсил *.phtml шаблоны нужно добавить это
    расширение в настройки анализатора PHP в
    Правка→Параметры→Анализаторы
    *.php;*.phtml
Для чего я добавил plural:1,2?

   Я не успел разобраться как заставить парсер xgettext
    доставать строки из такой конструкции:
    $this->view->translate(array('%s day', '%s days', $count)


   Но он успешно достает их из конструкции вида:
    $this->view->translate()->getTranslator()->plural('%s day', '%s days',
    $count)
Работаем с Poedit. Обновляем каталог
из исходных файлов

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

                     Сохраняем результат. В
                      параметрах должна быть
                      отмечена опция ”При
                      сохранении автоматически
                      компилировать файл .mo”.
                     В application.ini меняем
                      адаптер на:
                      resources.translate.adapter =
                      "gettext"
                     Запускаем:
                      Привет! 5 дней
                      осталось до начала
                      конференции
Ньюансы и хаки для работы с 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',
    )
Перевод сообщений валидаторов для
адаптеров != array

 Раньше мы делали отдельный файлик, который содержал
 все сообщения обернутые в _():
 _("A record matching "%value%" was found");
 _("Password and confirmed password do not match.");
 xgettext этот файл парсил, а мы переводили и
 компилировали .mo файл, который уже подключали ко всем
 проектам.

 Теперь в ZF появилась папочка resources, в которой лежат
 переводы сообщений валидаторов. Но как ихподключить
 если для основного сайта используется адаптер отличный
 от array я пока не успел разобраться. Думаю, что вскоре
 эта проблема будет решена и решение будет опубликовано
 на сайте или форуме http://zendframework.ru
Перевод сообщений валидаторов для
адаптера 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;
    }
Варианты передачи языка в URL

   Язык на поддомене:
      en.wikipedia.org
       ru.wikipedia.org
   Язык в поддиректории:
      1й вариант:
                 mota.ru – русский
                 mota.ru/en/ – английский


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

 +
        Ускоренная индексация.
        Для доменов первого уровня, которые не имеют
         георгафической привязки можно настроить разные
         географические цели для каждой языковой версии сайта
         (в Google Webmaster Tools).
        Вес с основного домена передается на поддомены.
        Сайты можно разнести на разные сервера и делать
         независимые изменения в коде.
 -
        Бюджет на продвижение и эффект от него будет
         дробиться на все сайты.
Язык в поддиректории

 preorder.it/ru/ и preorder.it/en/
 +
   Достаточно просто реализовать в ZF.
        Хорошо подходит для сайтов-услуг.
        Идет продвижения одного домена, т.е. тот же бюджет
         что и в первом варианте даст больший эффект.
 -
        Более медленная индексация.
        Нельзя сделать разные георгафические цели для
         разных языковых версий сайта.
        С технической стороны будет проблематично разнести
         разные языковые версии сайта на разные сервера.
Несколько строчек кода, которые
делают приложение быстрее :)

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

    $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);

More Related Content

What's hot

PHP 5.4: Что нового?
PHP 5.4: Что нового?PHP 5.4: Что нового?
PHP 5.4: Что нового?phpdevby
 
Лекция #6. Введение в Django web-framework
Лекция #6. Введение в Django web-frameworkЛекция #6. Введение в Django web-framework
Лекция #6. Введение в Django web-frameworkЯковенко Кирилл
 
Хранение, обработка и отдача статики с использованием \Zend\File. Опыт социал...
Хранение, обработка и отдача статики с использованием \Zend\File. Опыт социал...Хранение, обработка и отдача статики с использованием \Zend\File. Опыт социал...
Хранение, обработка и отдача статики с использованием \Zend\File. Опыт социал...zfconfua
 
Что нового в PHP-5.3
Что нового в PHP-5.3 Что нового в PHP-5.3
Что нового в PHP-5.3 phpclub
 
Perl6pod devconf
Perl6pod devconfPerl6pod devconf
Perl6pod devconfzagru
 
Презентация «Bundle Transformer – инструмент для клиентской оптимизации в сре...
Презентация «Bundle Transformer – инструмент для клиентской оптимизации в сре...Презентация «Bundle Transformer – инструмент для клиентской оптимизации в сре...
Презентация «Bundle Transformer – инструмент для клиентской оптимизации в сре...Andrey Taritsyn
 
Презентация «Drupal и SEO» с московской DrupalConf 2011
Презентация «Drupal и SEO» с московской DrupalConf 2011Презентация «Drupal и SEO» с московской DrupalConf 2011
Презентация «Drupal и SEO» с московской DrupalConf 2011Alexey Kostin
 
XML Native Database на примере SednaXML
XML Native Database на примере SednaXMLXML Native Database на примере SednaXML
XML Native Database на примере SednaXMLSlach
 
Node.JS: возможности для РНР-разработчика
Node.JS: возможности для РНР-разработчикаNode.JS: возможности для РНР-разработчика
Node.JS: возможности для РНР-разработчикаAlexei Smolyanov
 
Артем Розуменко - "Как и зачем разрабатывать собственный фреймворк?"
Артем Розуменко - "Как и зачем разрабатывать собственный фреймворк?"Артем Розуменко - "Как и зачем разрабатывать собственный фреймворк?"
Артем Розуменко - "Как и зачем разрабатывать собственный фреймворк?"QA Dnepropetrovsk Community (Ukraine)
 
"Великолепный API без Rest", Констатин Якушев (Badoo)
 "Великолепный API без Rest", Констатин Якушев (Badoo) "Великолепный API без Rest", Констатин Якушев (Badoo)
"Великолепный API без Rest", Констатин Якушев (Badoo)Badoo Development
 
Язык программирования Go для Perl-программистов
Язык программирования Go для Perl-программистовЯзык программирования Go для Perl-программистов
Язык программирования Go для Perl-программистовAndrew Shitov
 
Saint Perl 2009: CGI::Ajax demo
Saint Perl 2009: CGI::Ajax demoSaint Perl 2009: CGI::Ajax demo
Saint Perl 2009: CGI::Ajax demomegakott
 
Документирование исходных текстов (javadoc)
Документирование исходных текстов (javadoc)Документирование исходных текстов (javadoc)
Документирование исходных текстов (javadoc)Fedor Malyshkin
 

What's hot (20)

PHP 5.4: Что нового?
PHP 5.4: Что нового?PHP 5.4: Что нового?
PHP 5.4: Что нового?
 
Лекция #6. Введение в Django web-framework
Лекция #6. Введение в Django web-frameworkЛекция #6. Введение в Django web-framework
Лекция #6. Введение в Django web-framework
 
Хранение, обработка и отдача статики с использованием \Zend\File. Опыт социал...
Хранение, обработка и отдача статики с использованием \Zend\File. Опыт социал...Хранение, обработка и отдача статики с использованием \Zend\File. Опыт социал...
Хранение, обработка и отдача статики с использованием \Zend\File. Опыт социал...
 
file handling in c
file handling in cfile handling in c
file handling in c
 
Что нового в PHP-5.3
Что нового в PHP-5.3 Что нового в PHP-5.3
Что нового в PHP-5.3
 
бегун
бегунбегун
бегун
 
бегун
бегунбегун
бегун
 
Perl6pod devconf
Perl6pod devconfPerl6pod devconf
Perl6pod devconf
 
The Best Portlet
The Best PortletThe Best Portlet
The Best Portlet
 
Презентация «Bundle Transformer – инструмент для клиентской оптимизации в сре...
Презентация «Bundle Transformer – инструмент для клиентской оптимизации в сре...Презентация «Bundle Transformer – инструмент для клиентской оптимизации в сре...
Презентация «Bundle Transformer – инструмент для клиентской оптимизации в сре...
 
Презентация «Drupal и SEO» с московской DrupalConf 2011
Презентация «Drupal и SEO» с московской DrupalConf 2011Презентация «Drupal и SEO» с московской DrupalConf 2011
Презентация «Drupal и SEO» с московской DrupalConf 2011
 
XML Native Database на примере SednaXML
XML Native Database на примере SednaXMLXML Native Database на примере SednaXML
XML Native Database на примере SednaXML
 
Node.JS: возможности для РНР-разработчика
Node.JS: возможности для РНР-разработчикаNode.JS: возможности для РНР-разработчика
Node.JS: возможности для РНР-разработчика
 
Артем Розуменко - "Как и зачем разрабатывать собственный фреймворк?"
Артем Розуменко - "Как и зачем разрабатывать собственный фреймворк?"Артем Розуменко - "Как и зачем разрабатывать собственный фреймворк?"
Артем Розуменко - "Как и зачем разрабатывать собственный фреймворк?"
 
"Великолепный API без Rest", Констатин Якушев (Badoo)
 "Великолепный API без Rest", Констатин Якушев (Badoo) "Великолепный API без Rest", Констатин Якушев (Badoo)
"Великолепный API без Rest", Констатин Якушев (Badoo)
 
Язык программирования Go для Perl-программистов
Язык программирования Go для Perl-программистовЯзык программирования Go для Perl-программистов
Язык программирования Go для Perl-программистов
 
Saint Perl 2009: CGI::Ajax demo
Saint Perl 2009: CGI::Ajax demoSaint Perl 2009: CGI::Ajax demo
Saint Perl 2009: CGI::Ajax demo
 
PHP
PHPPHP
PHP
 
Документирование исходных текстов (javadoc)
Документирование исходных текстов (javadoc)Документирование исходных текстов (javadoc)
Документирование исходных текстов (javadoc)
 
REST
RESTREST
REST
 

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

Trening modul2-webinar11
Trening modul2-webinar11Trening modul2-webinar11
Trening modul2-webinar11olgaoov
 
Console application with ZF 2.0
Console application with ZF 2.0Console application with ZF 2.0
Console application with ZF 2.0Alexey Kachayev
 
Web deployment
Web deploymentWeb deployment
Web deploymentGetDev.NET
 
Воюем за ресурсы (ZFConf2011)
Воюем за ресурсы (ZFConf2011)Воюем за ресурсы (ZFConf2011)
Воюем за ресурсы (ZFConf2011)Alexey Kachayev
 
Взломать сайт на ASP.NET
Взломать сайт на ASP.NETВзломать сайт на ASP.NET
Взломать сайт на ASP.NETPositive Hack Days
 
Что нового в Visual Studio 2010 и .Net 4.0
Что нового в Visual Studio 2010 и .Net 4.0Что нового в Visual Studio 2010 и .Net 4.0
Что нового в Visual Studio 2010 и .Net 4.0akrakovetsky
 
ZFConf 2011: Воюем за ресурсы: Повышение производительности Zend Framework пр...
ZFConf 2011: Воюем за ресурсы: Повышение производительности Zend Framework пр...ZFConf 2011: Воюем за ресурсы: Повышение производительности Zend Framework пр...
ZFConf 2011: Воюем за ресурсы: Повышение производительности Zend Framework пр...ZFConf Conference
 
Компиляция скриптов PHP. Алексей Романенко
Компиляция скриптов PHP. Алексей РоманенкоКомпиляция скриптов PHP. Алексей Романенко
Компиляция скриптов PHP. Алексей РоманенкоFuenteovejuna
 
Компиляция скриптов PHP (Алексей Романенко)
Компиляция скриптов PHP (Алексей Романенко)Компиляция скриптов PHP (Алексей Романенко)
Компиляция скриптов PHP (Алексей Романенко)Ontico
 
Как быть с большими сайтами на Word press
Как быть с большими сайтами  на Word pressКак быть с большими сайтами  на Word press
Как быть с большими сайтами на Word pressvovasik
 
Микрофреймворки PHP
Микрофреймворки PHPМикрофреймворки PHP
Микрофреймворки PHPEkaterina Giganova
 
Drupal организация разработки
Drupal   организация разработкиDrupal   организация разработки
Drupal организация разработкиAnna Fedoruk
 
Drupal -organizaciya_razrabotki
Drupal  -organizaciya_razrabotkiDrupal  -organizaciya_razrabotki
Drupal -organizaciya_razrabotkidrupalconf
 
Solit 2012, Enterprise разработка PHP приложений, Иван Захарченко
Solit 2012, Enterprise разработка PHP приложений, Иван ЗахарченкоSolit 2012, Enterprise разработка PHP приложений, Иван Захарченко
Solit 2012, Enterprise разработка PHP приложений, Иван Захарченкоsolit
 
Internationalization and localization of the python applications with gettext...
Internationalization and localization of the python applications with gettext...Internationalization and localization of the python applications with gettext...
Internationalization and localization of the python applications with gettext...Volodymyr Hotsyk
 
IOP202 DevCon 2012 Apache Lucene in Windows Azure
IOP202 DevCon 2012 Apache Lucene in Windows AzureIOP202 DevCon 2012 Apache Lucene in Windows Azure
IOP202 DevCon 2012 Apache Lucene in Windows AzureVadim Novitskiy
 
Что нового в Visual Studio 2015
Что нового в Visual Studio 2015Что нового в Visual Studio 2015
Что нового в Visual Studio 2015GetDev.NET
 
Hadoop presentation
Hadoop presentationHadoop presentation
Hadoop presentationVlad Orlov
 

Similar to Zend Framework и мультиязычность (20)

Trening modul2-webinar11
Trening modul2-webinar11Trening modul2-webinar11
Trening modul2-webinar11
 
Zend Framework и Doctrine
Zend Framework и DoctrineZend Framework и Doctrine
Zend Framework и Doctrine
 
Console application with ZF 2.0
Console application with ZF 2.0Console application with ZF 2.0
Console application with ZF 2.0
 
Web deployment
Web deploymentWeb deployment
Web deployment
 
Воюем за ресурсы (ZFConf2011)
Воюем за ресурсы (ZFConf2011)Воюем за ресурсы (ZFConf2011)
Воюем за ресурсы (ZFConf2011)
 
Взломать сайт на ASP.NET
Взломать сайт на ASP.NETВзломать сайт на ASP.NET
Взломать сайт на ASP.NET
 
Что нового в Visual Studio 2010 и .Net 4.0
Что нового в Visual Studio 2010 и .Net 4.0Что нового в Visual Studio 2010 и .Net 4.0
Что нового в Visual Studio 2010 и .Net 4.0
 
ZFConf 2011: Воюем за ресурсы: Повышение производительности Zend Framework пр...
ZFConf 2011: Воюем за ресурсы: Повышение производительности Zend Framework пр...ZFConf 2011: Воюем за ресурсы: Повышение производительности Zend Framework пр...
ZFConf 2011: Воюем за ресурсы: Повышение производительности Zend Framework пр...
 
Компиляция скриптов PHP. Алексей Романенко
Компиляция скриптов PHP. Алексей РоманенкоКомпиляция скриптов PHP. Алексей Романенко
Компиляция скриптов PHP. Алексей Романенко
 
Компиляция скриптов PHP (Алексей Романенко)
Компиляция скриптов PHP (Алексей Романенко)Компиляция скриптов PHP (Алексей Романенко)
Компиляция скриптов PHP (Алексей Романенко)
 
Как быть с большими сайтами на Word press
Как быть с большими сайтами  на Word pressКак быть с большими сайтами  на Word press
Как быть с большими сайтами на Word press
 
Микрофреймворки PHP
Микрофреймворки PHPМикрофреймворки PHP
Микрофреймворки PHP
 
Drupal организация разработки
Drupal   организация разработкиDrupal   организация разработки
Drupal организация разработки
 
Drupal -organizaciya_razrabotki
Drupal  -organizaciya_razrabotkiDrupal  -organizaciya_razrabotki
Drupal -organizaciya_razrabotki
 
Solit 2012, Enterprise разработка PHP приложений, Иван Захарченко
Solit 2012, Enterprise разработка PHP приложений, Иван ЗахарченкоSolit 2012, Enterprise разработка PHP приложений, Иван Захарченко
Solit 2012, Enterprise разработка PHP приложений, Иван Захарченко
 
Internationalization and localization of the python applications with gettext...
Internationalization and localization of the python applications with gettext...Internationalization and localization of the python applications with gettext...
Internationalization and localization of the python applications with gettext...
 
Zend framework 2
Zend framework 2Zend framework 2
Zend framework 2
 
IOP202 DevCon 2012 Apache Lucene in Windows Azure
IOP202 DevCon 2012 Apache Lucene in Windows AzureIOP202 DevCon 2012 Apache Lucene in Windows Azure
IOP202 DevCon 2012 Apache Lucene in Windows Azure
 
Что нового в Visual Studio 2015
Что нового в Visual Studio 2015Что нового в Visual Studio 2015
Что нового в Visual Studio 2015
 
Hadoop presentation
Hadoop presentationHadoop presentation
Hadoop presentation
 

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

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