Yesod: и17я
Приветствую!
Сегодня поговорим об интернационализации, одном из важнейших аспектов современных веб-решений. Как вы уже знаете, в корне проекте расположен каталог messages
, содержащий языковые файлы. Далее предполагается, что нас интересуют два языка, английский и русский.
Ключи и переводы
Итак, давайте чуток расширим содержимое файла messages/en.msg
и напишем в нём следующее:
Hello: Hello
Welcome: Welcome to Yesod!
ну и в файл messages/ru.msg
напишем, соответственно, это:
Hello: Привет
Welcome: Добро пожаловать в Yesod!
Теперь у нас есть два i18n-ключа, Hello
и Welcome
, с каждым из которых ассоциировано по два перевода. Это избавляет нас от дубляжа кода в наших виджетах. Не знаю как вы, но я не очень люблю веб-решения, многоязычность которых реализуется дубляжом (и, соответственно, отражается языковой меткой в URL страниц). А ведь это канонический подход многих веб-систем: для каждой страницы создаются N экземпляров, где N соответствует числу языков. И когда я обращаюсь, скажем, к http://site.com/ru/page
, получаю русский вариант страницы page
, а когда вместо ru
пишется en
- тогда английский вариант.
В Yesod всё элегантнее и проще. Никакого дубляжа страниц здесь нет, ведь в коде страниц используются только ключи, а конкретный перевод подставляется на место ключа динамически, в зависимости от текущего языка. Поэтому при переключении языка URL страницы не меняется, а текстовое содержимое просто переписывается. Выглядит изящно.
Использование
Теперь давайте, наконец, поймём, как же использовать ключи в нашем коде. Основное правило: ключ используется с обязательным префиксом Msg
. То есть ключ Hello
будет фигурировать в коде как MsgHello
, а ключ Welcome
- как MsgWelcome
. Запомнить легко: все ключи, заданные в каталоге messages
, предваряются префиксом Msg
.
Теперь к делу.
Заголовки
Откроем файл Handler/Home.hs
и найдём нашу функцию getHomeR
:
getHomeR :: Handler Html
= defaultLayout $ do
getHomeR "Welcome To Yesod!"
setTitle $(widgetFile "homepage")
Уже известная нам функция setTitle
устанавливает заголовок страницы. Но здесь заголовок прописан явно, на английском языке. Давайте же исправим это:
getHomeR :: Handler Html
= defaultLayout $ do
getHomeR MsgWelcome
setTitleI $(widgetFile "homepage")
Предельно просто. Функция setTitleI
- это i18n-аналог функции setTitle
(отсюда и суффикс I
). Мы передаём ей уже не явный текст, а имеющийся ключ. Таким образом, когда текущим языком страницы будет английский, заголовок будет отображён как “Welcome to Yesod!”, а если русский - тогда как “Добро пожаловать в Yesod!”.
Hamlet
Перейдём к HTML-скелету. Откроем файл templates/homepage.hamlet
:
<div .centered>
<h1>Я - единственный виджет этой страницы!
Единственный контент этого виджета задан по-русски, и это опять-таки не то, чего мы хотим. Добавим новый ключ. В файле messages/en.msg
пропишем это:
Hello: Hello
Welcome: Welcome to Yesod!
HomeMainH: I'm a single widget of this page!
а в файле messages/ru.msg
- это:
Hello: Привет
Welcome: Добро пожаловать в Yesod!
HomeMainH: Я - единственный виджет этой страницы!
Теперь возвращаемся к templates/homepage.hamlet
и пишем:
<div .centered>
<h1>_{MsgHomeMainH}
Как видите, тут тоже всё очень просто. Снова наш ключ с префиксом Msg
, только на этот раз он заключён между символами _{
и }
.
Таким образом, учитывая тот факт, что ключу может соответствовать и аббревиатура, и слово, и фраза, и предложение и даже целый текст, мы можем гибко составлять из них корректные переводы для наших страниц (учитывающие падежи, числа и т.п). Вот, собственно, и всё.
Но внимательный читатель обязательно спросит меня: “В заметке несколько раз был упомянут текущий язык страницы. А как же нам установить этот текущий язык?” Прекрасный вопрос, но это мы обсудим в одной из будущих заметок.