9

Controller:i18n errore: controller e modelli utilizzano diversi linguaggi impliciti

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> 

Messaggi risorsa, conf/messages.zh-CN:

error.required=该字段必填 

Cercando

  1. Utilizza un Firefox inglese che invia l'intestazione della richiesta Accept-Language:en-us,en;q=0.5 per visitare l'azione test. Il risultato è:

    Language from controller: Lang(en,), Message: This field is required 
    Message in view: 该字段必填 
    
  2. utilizza un Google Chrome cinese che manda l'intestazione della richiesta Accept-Language:zh-CN,zh;q=0.8 a visitarla. Il risultato è:

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

Dai test, sappiamo che:

  1. La lingua implicita nel controller è da Accept-Language
  2. La lingua implicita della intestazione di richiesta utilizzato in modello è determinato dal sistema operativo

Ambiente:

  1. Play 2 è l'ultima play2.1-SNAPSHOT da GitHub (2012-03-16)
  2. Il mio sistema operativo è Windows 7 x64   versione cinese

penso Play 2 dovrebbe utilizzare la stessa implicita lingua per controllori e viste. Posso risolvere il problema con l'aggiunta di qualcosa in Build.sbt:

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

Qualora il TemplateMixin è solo: (. Si estende Controller e è solo quello di riutilizzare alcuni metodi, come implicit def lang(request))

object TemplateMixin extends play.api.mvc.Controller 

Ma penso che dovrebbe essere fatto dal framework Play.

risposta

17

La funzione play.api.i18n.Messages(key) accetta un ulteriore parametro implicito di tipo Lang. Pertanto, quando si scrive Messages("foo"), viene esteso a Messages("foo")(l), dove l è un valore di tipo Lang ricavato dall'ambito implicito corrente.

C'è sempre uno default implicit lang disponibile (che ha un low priority), utilizzando le impostazioni internazionali predefinite di jvm.

Ma quando si è all'interno di un Controller, è possibile trovare un valore implicito con una priorità più elevata se è presente una richiesta implicita. Questo valore viene visualizzato nell'intestazione Accept-Language della richiesta.

Quando si è all'interno di un modello, verrà utilizzato il lang implicito predefinito a meno che il modello non importi un altro lang implicito.

Ecco perché, nel tuo esempio, i messaggi calcolati dal controller utilizzano l'intestazione della richiesta Accept-Language e i messaggi calcolati dalla vista utilizzano le impostazioni internazionali predefinite di jvm.

Se si aggiunge un parametro implicito di tipo Lang al modello, questo parametro avrà una priorità maggiore di quella predefinita Lang e sarà utilizzato per calcolare i messaggi:

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

Quando si chiama il modello da un'azione Controller, verrà passata la sua lingua implicita, quindi lo stesso lang verrà utilizzato da entrambe le viste e dai controller.

+1

Grazie ancora. Una buona risposta dovrebbe essere aggiunta ai documenti di play2. – Freewind

+0

Perché non può essere il comportamento predefinito? Immagino che la maggior parte delle app vorrebbe che la Land implicita nella vista sia la stessa utilizzata nel controller. – Ike

+0

Per rendere questo comportamento predefinito è necessario distinguere tra i modelli destinati ad essere utilizzati con i controller Java (che non possono fornire valori impliciti) e i modelli destinati ad essere utilizzati con i controller Scala. –