控制器中的 Play Framework Lang 未发生隐式转换
Implicit conversion not taking place for Play Framework Lang in controller
我有一个视图接受 Play 的 Messages
对象所需的隐式 Lang
。此视图的签名是:
@()(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
?
根据 Play 文档
If you have an implicit Request in the scope, it will provide an
implicit Lang value corresponding to the preferred language extracted
from the Accept-Language header and matching one of the application
supported languages.
因此您需要将操作更改为
def createView = Action { implicit request =>
Ok(views.html.showView())
}
它应该可以工作。
必须为每个控制器调用 implicit val lang: Lang = request
似乎需要做很多工作,但当您考虑它时,实际上并非如此,您已经调用了 Action
方法(它接受一个 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 { ... }
,只需混合特征并使用:
def action = withLanguage { request => implicit lang =>
Ok(views.html.showView())
}
我有一个视图接受 Play 的 Messages
对象所需的隐式 Lang
。此视图的签名是:
@()(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
?
根据 Play 文档
If you have an implicit Request in the scope, it will provide an implicit Lang value corresponding to the preferred language extracted from the Accept-Language header and matching one of the application supported languages.
因此您需要将操作更改为
def createView = Action { implicit request =>
Ok(views.html.showView())
}
它应该可以工作。
必须为每个控制器调用 implicit val lang: Lang = request
似乎需要做很多工作,但当您考虑它时,实际上并非如此,您已经调用了 Action
方法(它接受一个 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 { ... }
,只需混合特征并使用:
def action = withLanguage { request => implicit lang =>
Ok(views.html.showView())
}