Yii Framework — поддержка нескольких языков в URL

Одной из причин, по которой для реализации программного комплекса я выбрал полноценный веб-фреймворк, стала необходимость поддержки трех языков: русского, украинского и английского. В системах управления содержимым (content management system), таких как Joomla, WordPress или Drupal, для поддержки нескольких языков необходимы сторонние дополнения. В то же время, в современных веб-фреймворках, использующих архитектуру Model — View — Controller, модуль поддержки языков встроен в систему и доступен без каких-либо манипуляций со стороны разработчика.

Поддержка нескольких языков интерфейса присутствует и в выбранном для разработки программного комплекса Yii Framework. С переводом представлений проблем нет; в Yii существуют для него два базовых механизма:

  • при помощи сообщений;
  • путем создания специфичных для языка файлов представлений.

Определенные трудности возникают при настройке преобразования URL. В отличие от некоторых других веб-фреймворков (например, Django), Yii «из коробки» не поддерживает работу с URL на сайтах с несколькими языками. Для того, чтобы устранить этот недостаток, надо рассмотреть, как происходит обработка URL в Yii.

В процессе обработки запроса из URL извлекается информация о:

  • контроллере;
  • действии (action) контроллера;
  • параметрах действия.

Например, гипотетическому URL вида /book/5 (вместо 5 может быть другое целое число — идентификатор книги) может соответствовать контроллер BookController (идентификатор book), его метод viewAction (идентификатор view) и параметр действия $id = 5 .

Обратное преобразование используется, например, в отображениях. По идентификаторам действия и контроллера и параметрам действия создается соответствующий URL (например, с помощью метода CController::createUrl).

Соответствие между URL и действиями осуществляет модуль Yii urlManager. Информация о преобразованиях URL хранится в главном файле конфигурации Yii (config/main.php) виде набора правил, каждое из которых состоит из двух частей:

  • Шаблон — выражение для URL, определяющий область применения правила. По своему синтаксису шаблоны напоминают регулярные выражения с именованными группами.
  • Действие, соответствующее URL. Действие состоит из двух частей: идентификаторов контроллера и действия в этом контроллере, разделенных косой чертой /.

Например, приведенное выше правило для URL вида /book/5 в файле конфигурации записывается как

Наиболее очевидный способ добавления поддержки нескольких языков — усложнение используемых правил:

Однако этот способ не очень продуктивен:

  • Во все действия приходится добавлять новый параметр $lang и вызов метода setupLanguage.
  • Параметр lang нужно добавлять и во все методы создания URL.

Значительно более эффективный способ поддержки нескольких языков — использование специального класса правил. Модуль urlManager позволяет заменить класс для всех правил работы с URL с используемого по умолчанию CUrlRule на произвольный другой класс с двумя методами:

  • parseUrl — преобразование из URL в идентификатор действия и параметры;
  • createUrl — обратное преобразование.

При преобразовании URL в действие и обратно модуль Yii urlManager пытается применить соответствующую функцию каждого из правил, объявленных в файле конфигурации. Для того чтобы показать, что правило не применимо для заданного набора аргументов, указанные выше функции должны возвращать значение false. Для того, чтобы заменить класс всех правил, достаточно указать в файле конфигурации значение для поля urlRuleClass в модуле urlManager.

При этом класс правил (в примере выше — CustomUrlRule) должен находиться в известном для Yii месте; имеет смысл поместить его в директорию components/.

Как и обычные правила CUrlRule, правила с новым классом инициализируются с использованием двух переменных: шаблона и идентификатора действия. Дополнительные параметры для создания правил можно передавать, если заменить идентификатор действия на массив:

В случае использования правил для поддержки нескольких языков класс правил (LangUrlRule) должен содержать три фрагмента.

Разбор URL

Метод parseUrl нового класса должен извлекать из предоставленного адреса информацию и устанавливать язык для отображения данных (переменную Yii::app()->language ). Для сайта программного комплекса язык определяется по первому фрагменту URL (en — для английского языка, ru — для русского, uk — для украинского). Если сведения о языке отсутствуют в URL, запрос должен перенаправляться на адрес с явно заданным языком. Например, если запрашивается адрес /book/1, после перенаправления URL станет равным /ru/book/1.

В приведенном коде при отсутствии языка в URL выбирается фиксированный язык (русский); более продвинутый способ — использование предпочитаемых языков, передаваемых браузером (Yii хранит его в переменной Yii::app()->request->preferredLanguages), однако может оказаться, что эти языки не поддерживаются.

Создание URL

Метод createUrl должен добавлять к началу адреса информацию о языке.

Обратная совместимость

Должны поддерживаться нейтральные запросы, не зависящие от языка. Например, если на сайте используется капча, не имеет никакого смысла изменять ее URL в зависимости от языка отображения данных (более того, встроенный в Yii модуль капчи от этого перестает адекватно работать). Таким образом, должна быть возможность объявить правило вроде

Полный код правила.

Итак, с помощью простых приемов можно научить Yii Framework работать с URL для сайтов с поддержкой нескольких языков. Насколько я понимаю, с минимальными изменениями тот же прием можно подходит и для Yii 2.x.

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

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