Controller:
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))
}
View:
@(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>
Messages resource, conf/messages.zh-CN
:
error.required=该字段必填
Trying
Uses an English Firefox which sends the request header
Accept-Language:en-us,en;q=0.5
to visit thetest
action. The result is:Language from controller: Lang(en,), Message: This field is required Message in view: 该字段必填
Uses an Chinese Google Chrome which sends the request header
Accept-Language:zh-CN,zh;q=0.8
to visit it. The result is:Language: Lang(zh,CN), Message: 该字段必填 Message in view: 该字段必填
From the tests, we know that:
- The implicit language in the controller is from the request header's
Accept-Language
- The implicit language used in template is determined by the OS
Environment:
- Play 2 is latest play2.1-SNAPSHOT from GitHub (2012-03-16)
- My OS is Windows 7 x64 Chinese version
I think Play 2 should use the same implicit language for controllers and views. I can fix it by adding something in Build.sbt
:
val main = PlayProject(...) (
templatesImport ++= Seq("utilis.TemplateMixin._")
)
Where the TemplateMixin
is just:
object TemplateMixin extends play.api.mvc.Controller
(It extends Controller and is just to reuse some methods, like implicit def lang(request)
.)
But I think it should be done by the Play framework.
The
play.api.i18n.Messages(key)
function takes an additional implicit parameter of typeLang
. So when you writeMessages("foo")
it is expanded toMessages("foo")(l)
, wherel
is a value of typeLang
taken from the current implicit scope.There’s always an available default implicit lang (which has a low priority), using your jvm default locale.
But when you are inside a Controller, an implicit value with a higher priority can be found if there is an implicit request. This value looks in the
Accept-Language
header of the request.When you are inside a template, the default implicit lang will be used unless your template imports another implicit lang.
That’s why, in your example, messages computed from the Controller use the
Accept-Language
request header and messages computed from the View use your jvm default locale.If you add an implicit parameter of type
Lang
to your template, this parameter will have a higher priority than the default lang and will be used to compute messages:When you’ll call the template from a Controller action, its implicit lang will be passed, so the same lang will be used by both your Views and your Controllers.