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 the test
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:
Accept-Language
Environment:
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 type Lang
. So when you write Messages("foo")
it is expanded to Messages("foo")(l)
, where l
is a value of type Lang
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:
@(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>
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With