我有一个视图,它接受Play的Lang
对象所需的隐式Messages
。此视图的签名是:
@()(implicit lang: Lang)
然后我有一个需要创建视图的控制器:
def createView = Action { request =>
Ok(views.html.showView())
}
然后我有一个隐式方法,我想调用它来创建视图所需的Lang
:
implicit def getLangFromRequest(request: RequestHeader): Lang = {
request.cookies.get("lang") match {
case Some(cookie) => Lang(cookie.value)
case None => Lang("en") // Default
}
}
换句话说,该方法应该从cookie中获取语言,否则使用默认值(我已经修剪了这个问题的错误处理)。
然而,这种隐式转换并未发生。我知道它能够隐式转换,因为通过在控制器中创建一个隐式变量起作用:
def createView = Action { request =>
implicit val lang: Lang = request
Ok(views.html.showView())
}
但我不想在任何地方添加这种锅炉板线。据推测,我必须显式调用该方法,因为在隐式转换之前会使用一些全局Lang
对象。
我有什么选择可以避免在每个控制器中重复此implicit val lang: Lang = request
?
答案 0 :(得分:2)
根据Play文档
如果您在范围内有隐式请求,则会提供 隐含的Lang值对应于提取的首选语言 来自Accept-Language标头并匹配其中一个应用程序 支持的语言。
所以你需要将你的行动改为
def createView = Action { implicit request =>
Ok(views.html.showView())
}
它应该有用。
答案 1 :(得分:0)
为每个控制器调用implicit val lang: Lang = request
似乎需要做很多工作但是当你考虑它时,实际上并没有,你已经调用了Action
方法(它接受了{{1}作为参数无论何时创建新动作。
编写一个Request => Result
,它可以完成查找语言的所有重要逻辑,将其混合到所有控制器中,而不是使用trait
方法,使用您在该特征中编写的方法,接受Action
函数,为语言执行逻辑,然后将函数参数应用于范围中的请求。像这样:
Request => Lang => Result
然后,只需混合特征并使用:
,而不是trait Internationalization { subj: Controller =>
def withLanguage(f: => Request[AnyContent] => Lang => Result) = Action { implicit request =>
val lang = request.cookies.get("lang") match {
case Some(cookie) => Lang(cookie.value)
case None => Lang("en") // Default
}
f(request)(lang)
}
}
def action = Action { ... }