Ошибка i18n: контроллер и шаблоны используют разные неявные языки - PullRequest
9 голосов
/ 16 марта 2012

Контроллер:

def test = Action { implicit request =>
    import play.api.i18n._
    val msg = Messages("error.invalid")
    implicit val langInController = lang(request)
    Ok(views.html.test(langInController, msg))
}

Просмотр:

@(langInController: play.api.i18n.Lang, msg:String)(implicit request: Request[_])
<div>Lang from controller: @langInController, Message: @msg</div>
<div>Message from view: @play.api.i18n.Messages("error.required")</div>

Ресурс сообщений, conf/messages.zh-CN:

error.required=该字段必填

Попытка

  1. Использует английский Firefox, который отправляет заголовок запроса Accept-Language:en-us,en;q=0.5 для посещения действия test.Результат:

    Language from controller: Lang(en,), Message: This field is required
    Message in view: 该字段必填
    
  2. Использует китайский Google Chrome, который отправляет заголовок запроса Accept-Language:zh-CN,zh;q=0.8 для его посещения.Результат:

    Language: Lang(zh,CN), Message: 该字段必填
    Message in view: 该字段必填
    

Из тестов мы знаем, что:

  1. Неявный язык в контроллере взят из заголовка запроса Accept-Language
  2. Неявный язык, используемый в шаблоне, определяется ОС

Среда:

  1. Play 2 - последняя версия play2.1-SNAPSHOT от GitHub (2012-03-16)
  2. Моя ОС - Windows 7 x64 Китайская версия

Я думаю, Play 2 должен использовать один и тот же неявный язык для контроллеров и представлений.Я могу это исправить, добавив что-то в Build.sbt:

val main = PlayProject(...) (
    templatesImport ++= Seq("utilis.TemplateMixin._")
)

Где TemplateMixin просто:

object TemplateMixin extends play.api.mvc.Controller

(Это расширяет контроллер и просто повторяет некоторые методы,как implicit def lang(request).)

Но я думаю, что это должно быть сделано с помощью платформы Play.

1 Ответ

17 голосов
/ 16 марта 2012

Функция play.api.i18n.Messages(key) принимает дополнительный неявный параметр типа Lang.Поэтому, когда вы пишете Messages("foo"), оно расширяется до Messages("foo")(l), где l - это значение типа Lang, взятое из текущей неявной области.

Всегда есть доступный неявный lang по умолчанию (который имеет низкий приоритет ), используя ваш языковой стандарт по умолчанию jvm.

Но когда вы находитесь внутри Controller , неявное значение с более высоким приоритетомможно найти, если есть неявный запрос.Это значение выглядит в заголовке Accept-Language запроса.

Когда вы находитесь внутри шаблона, будет использоваться неявный lang по умолчанию, если ваш шаблон не импортирует другой неявный lang.

Вот почему,в вашем примере сообщения, вычисленные из контроллера, используют заголовок запроса Accept-Language, а сообщения, вычисленные из представления, используют ваш языковой стандарт по умолчанию jvm.

Если вы добавите в шаблон неявный параметр типа Lang, этоПараметр будет иметь более высокий приоритет, чем lang по умолчанию, и будет использоваться для вычисления сообщений:

@(langInController: Lang, msg:String)(implicit request: RequestHeader, lang: Lang)

<div>Lang from controller: @langInController, Message: @msg</div>
<div>Message from view: @Messages("error.required")</div>

Когда вы вызовете шаблон из действия Controller, его неявный lang будет передан, поэтому тот же langбудет использоваться как вашими представлениями, так и вашими контроллерами.

...