i18n 错误:控制器和模板使用不同的隐式语言 [英] i18n error: controller and templates uses different implicit languages
问题描述
控制器:
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=该字段必填
尝试
使用英文 Firefox,它发送请求标头
Accept-Language:en-us,en;q=0.5
以访问test
操作.结果是:
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: 该字段必填
使用中文谷歌浏览器发送请求头Accept-Language:zh-CN,zh;q=0.8
来访问它.结果是:
Language: Lang(zh,CN), Message: 该字段必填
Message in view: 该字段必填
从测试中,我们知道:
- 控制器中的隐式语言来自请求头的
Accept-Language
- 模板中使用的隐式语言由操作系统决定
环境:
- Play 2 是来自 GitHub 的最新 play2.1-SNAPSHOT (2012-03-16)
- 我的操作系统是 Windows 7 x64 中文版
我认为 Play 2 应该对控制器和视图使用相同的隐式语言.我可以通过在 Build.sbt
中添加一些东西来修复它:
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._")
)
TemplateMixin
的位置:
object TemplateMixin extends play.api.mvc.Controller
(它扩展了Controller,只是为了复用一些方法,比如implicit def lang(request)
.)
(It extends Controller and is just to reuse some methods, like implicit def lang(request)
.)
但我认为应该由 Play 框架来完成.
But I think it should be done by the Play framework.
推荐答案
play.api.i18n.Messages(key)
函数需要一个额外的 Lang
.因此,当您编写 Messages("foo")
时,它会扩展为 Messages("foo")(l)
,其中 l
是一个值Lang
类型取自当前隐式作用域.
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.
总是有一个可用的 默认隐式语言(它有一个 低优先级),使用您的 jvm 默认语言环境.
There’s always an available default implicit lang (which has a low priority), using your jvm default locale.
但是当你在一个 Controller,如果有隐式请求,可以找到优先级更高的隐式值.该值在请求的 Accept-Language
标头中查找.
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.
当您在模板中时,将使用默认的隐式 lang,除非您的模板导入另一个隐式 lang.
When you are inside a template, the default implicit lang will be used unless your template imports another implicit lang.
这就是为什么在您的示例中,从 Controller 计算的消息使用 Accept-Language
请求标头,而从 View 计算的消息使用您的 jvm 默认语言环境.
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.
如果您向模板中添加类型为 Lang
的隐式参数,则此参数将具有比默认 lang 更高的优先级,并将用于计算消息:
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.
这篇关于i18n 错误:控制器和模板使用不同的隐式语言的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!