9

controlador:i18n error: controlador y plantillas utiliza diferentes lenguajes implícitos

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)) 
} 

Vista:

@(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> 

Mensajes de recursos, conf/messages.zh-CN:

error.required=该字段必填 

Tratando

  1. Utiliza un Firefox inglés que envía el encabezado de solicitud Accept-Language:en-us,en;q=0.5 para visitar la acción test. El resultado es:

    Language from controller: Lang(en,), Message: This field is required 
    Message in view: 该字段必填 
    
  2. Utiliza un chino de Google Chrome que envía el encabezado de la solicitud Accept-Language:zh-CN,zh;q=0.8 a visitarla. El resultado es:

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

De las pruebas, sabemos que:

  1. El lenguaje implícito en el controlador es de Accept-Language
  2. El lenguaje implícito del encabezado de la solicitud utilizada en la plantilla es determinado por el OS

Entorno:

  1. Play 2 es la última play2.1-instantánea en GitHub (2012-03-16)
  2. Mi sistema operativo es Windows 7 x64   versión china

creo Play 2 debe utilizar el mismo implícita lenguaje para controladores y vistas. I puede fijarlo mediante la adición de algo en Build.sbt:

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

Cuando el TemplateMixin es simplemente: (. Se extiende controlador y es sólo para volver a usar algunos métodos, como implicit def lang(request))

object TemplateMixin extends play.api.mvc.Controller 

Pero creo que debería hacerse con Play framework.

Respuesta

17

La función play.api.i18n.Messages(key) toma un parámetro implícito adicional del tipo Lang. Por lo tanto, cuando escribe Messages("foo") se expande a Messages("foo")(l), donde l es un valor de tipo Lang tomado del alcance implícito actual.

Siempre hay un default implicit lang disponible (que tiene un low priority), utilizando su configuración predeterminada de jvm.

Pero cuando se encuentra dentro de un Controller, se puede encontrar un valor implícito con una prioridad más alta si hay una solicitud implícita. Este valor se ve en el encabezado Accept-Language de la solicitud.

Cuando se encuentre dentro de una plantilla, se utilizará la etiqueta implícita predeterminada a menos que su plantilla importe otra lengua implícita.

Es por eso que, en su ejemplo, los mensajes calculados desde el controlador usan el encabezado de solicitud Accept-Language y los mensajes calculados desde la vista utilizan su configuración regional predeterminada de jvm.

Si se agrega un parámetro implícito del tipo Lang a la plantilla, este parámetro tendrá una prioridad más alta que la lang defecto y se utilizará para calcular mensajes:

@(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> 

Cuando se le llama a la plantilla a partir de una acción del Controlador, su lang implícito se aprobará, por lo que las Vistas y los Controladores utilizarán la misma lang.

+1

Gracias de nuevo. Se debe agregar una buena respuesta a los documentos de play2. – Freewind

+0

¿Por qué no puede ser este el comportamiento predeterminado? Me imagino que la mayoría de las aplicaciones querrían que el Land implícito en la vista sea el mismo que se usa en el controlador. – Ike

+0

Hacer esto el comportamiento predeterminado requeriría diferenciar entre las plantillas destinadas a ser utilizadas con los controladores Java (que no pueden proporcionar valores implícitos) y las plantillas destinadas a ser utilizadas con los controladores Scala. –

Cuestiones relacionadas