Интернационализация и локализация в PHP (часть 2)

фев 22, 13:53

Итак, в прошлый раз разговор был о Symfony. Сегодня речь пойдет о Akelos. Кто не в курсе Akelos, скажу лишь то, что этот фреймворк является полным клоном RoR с единственным отличием – написан он на PHP. Правда ли это для вопросов интернационализации я не знаю. Но как бы то ни было все равно посмотрим, что Akelos нам приготовил.

Пару слов о документации

Как таковой для Akelos ее нет. Есть пару отписок, небольшой Readme, плюс сгенерированная с помощью phpxref дока и демонстрационный скринкаст. Все. Может быть в этом плане разработчик понадеялся на прошлый опыт с Ruby On Rails. Не знаю, но факт, как говорится, на лицо и с этим следует смириться. В оправдание могу сказать, что фреймворк достаточно само документированный и разобраться как и что происходит не составляет особого труда. Исходники благо открыты для любого применения.

Интернационализация интерфейса, сообщений и тд

Здесь Akelos ничем примечательным от Symfony не отличается. Если помните в Symfony для проблемы поддержки нескольких языков и стран использовался параметр Culture ( язык_СТРАНА в двухбуквенных кодах). Akelos используют более простую модель. В файле config задаются разрешенные локали, которые можно увидеть в банальном HTTP-заголовке «Accept-Language» (например, «ru, en_us»). После того как настроены необходимые языки Akelos будет самостоятельно создавать и следить за словарями для этих языков с помощью специального метода t() или специальных тегов _{} в виде.

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

Для того, чтобы сменить локаль достаточно в URL добавить код языка. Например, вот так будет выглядить классическая строка с доступными языками:


  <div align="right">
    <?php echo $url_helper->link_to($controller->t('en'), array('lang' => 'en')) ?> | 
    <?php echo $url_helper->link_to($controller->t('de'), array('lang' => 'de')) ?> | 
    <?php echo $url_helper->link_to($controller->t('ru'), array('lang' => 'ru')) ?> | 
  </div>

Это все. Akelos по щелчку на ссылку прибавит к URL выбранный язык. И даже более того, во-всех ссылках, созданных с помощью link_to(), отобразится изменения, связанные с выбором языка. Ни о чем разработчику беспокоится не приходится.

Что касается словарей, то никого XML подобия вы не встретите. Обыкновенные ассоциативные массивы:


$dictionary = array();
$dictionary['Pages'] = 'Страницы';
$dictionary['OK'] = 'OK';
$dictionary['Cancel'] = 'Отмена';

Локализация содержимого

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

Для начала следует обьявить что твоя любимая модель имеет многоязыковую структуру и что даже несколько столбцов в соответствующей ей таблицы из базы данных имеет перевод на другие языки мира. Как это делается? А вот так:


    function up_1()
    {
        $this->createTable('pages', "
          id,
          en_title,
          de_title,
          ru_title,
          en_body text,
          de_body text,
          ru_body text
        ");
    }

Все это естественно должно находится в инсталлере приложения. Как видите, в одной таблице мы имеет сразу же и английский, и немецкий, и русский вариант заголовка и текста страницы. Ну что же, разработчики доупрощались настолько, что нарушили святые нормальные формы старика Кодда, так ревностно оберегаемые математиками и профессорам ВУЗов. Мне если честно, такой поворот событий тоже не очень нравится. Не правильно это по единственной простой причине – если не все страницы могут быть переведены на все три языка, то на что будет похожа наша таблица? Пустое пространство – это не есть хорошо и все-таки следует беречь ресурсы данные нам Богом.

Ну оставим и пойдем дальше. Дальше никаких сюрпризов не ожидается. Все те же get- и set-методы автоматом подхватываются фрейморков. И мы просто лениво наслаждаться тем, что мир прекрасен и чуден, и все так хорошо и просто. На всякий случай приведу пример как же это делается:

Контроллер:


$this->Page->setAttribute('title', $this->params['title']);
$this->Page->setAttribute('body', $this->params['body']);
$this->Page->save();

Вид:


<h1>En</h1>
<p> <label for=“page_title”>_{Title}</label><br /> <?php echo $form_helper->text_field(‘title’, ‘en’)?> </p>

<p> <label for=“page_body”>_{Body}</label><br /> <?php echo $form_helper->text_area(‘body’, “en”) ?>
</p>

<h1>Ru</h1>
<p> <label for=“page_title”>_{Title}</label><br /> <?php echo $form_helper->text_field(‘title’, ‘ru’)?>
</p>

<p> <label for=“page_body”>_{Body}</label><br /> <?php echo $form_helper->text_area(‘body’, ‘ru’) ?>
</p>

Модель (инсталлер):


$this->createTable('pages', "
  id,
  en_title,
  ru_title,
  en_body text,
  ru_body text
");

И все. Красота да и только.

Выводы

Akelos прост на уровня интуитивного понимания. Конечно хранение в одной таблицы сразу всех версий контента не очень красиво. Гораздо приятным в этом отношении выглядит Symfony, которые как заядлый отличник старается все время вытянуть на пятерку.

Но и у Symfony есть свои недостатки, которые, как мне кажется, все-таки сглаживаются на больших проектах. Взять хотя бы тот же XML для словарей. Его неудобно писать вручную. Но кто знает, возможно на большом сайте такой необходимости уже и не будет, так как можно будет использовать генерирующие XLIFF программы.

По большому счету, что Akelos, что Symfony — без разницы. Все они используют ту же модель – хеллпер, словарь, ORM, автоматом подхватывающие get- и set-методы.

Надеюсь, что это небольшая обзорная статья в чем-то поможет в реализации многоязычных приложения самостоятельно. Курс и направление движения есть. Существуют ли какие-либо другие варианты? Наверняка существуют. Если мне что-нибудь интересного в этом плане попадется, обязательно напишу.

В следующей статье я планирую немножко развить эту тему и немножко отойти к другой. Меня интересует ORM-фреймворк Doctrine. Что за вкусности там есть, опять же поддержка интернационализации, удобно ли пользоваться, насколько эффективен для применения «один разработчик – небольшой приложение». Словом, не буду загадывать – все равно сами все увидите.

Дмитрий Науменко

,

---

Комментарии

Комментирование этой статьи закрыто

---