Play/Scala 中的隐式参数和组合视图

Posted

技术标签:

【中文标题】Play/Scala 中的隐式参数和组合视图【英文标题】:Implicit parameters and combined views in Play/Scala 【发布时间】:2015-06-12 19:15:54 【问题描述】:

这个问题建立在我发现的一个案例 here

index.scala.html

@(text: String)(implicit messages: Messages)

@main("Fancy title") 
  <h1>@messages("header.index")</h1>
  <div>@text</div>

ma​​in.scala.html

@(title: String)(content: html)(implicit messages: Messages)
  <html>
  <head>
    <title>@title</title>
  </head>
  <body>
    <h1>@messages("header.main")</h1>
    @content
  <body>
</html>

在此示例中,我有 index 调用 ma​​in,我希望两者都访问 messages

编译器在 index 内给了我“could not find implicit value for parameter messages: play.api.i18n.Messages”,但如果我删除了隐式参数声明从 ma​​in 然后 index 工作正常并收到消息。似乎编译器告诉我它不知道如何将隐式参数向下传递。

在尝试解决方法之前,我想了解为什么这不起作用。

【问题讨论】:

【参考方案1】:

在 Play 2.4 中,您需要在控制器中注入 MessageAPI 并在您的操作中调用首选菜单来创建消息。 如果您将其定义为隐含在您的操作中。然后一切都会好起来的。

【讨论】:

嗨 Soroosh,正如我在我的问题中提到的那样,我通过完全按照您所说的进行部分工作。这是我的控制器: class Application @Inject() (val messagesApi: MessagesApi) extends Controller with I18nSupport def index = Action implicit request =&gt; Ok(views.html.index("blah bla blah")) 当我尝试使用控制器调用的 index 调用的 main 中的消息时,就会出现问题。我正在寻找一种干净的方法来为所有嵌套视图注入一些全局数据(在这种情况下是消息) 在您的操作中调用首选菜单以创建消息究竟是什么意思?【参考方案2】:

首先让我添加控制器的代码,以使我的原始示例更清晰。

Application.scala(原始)

class Application @Inject() (val messagesApi: MessagesApi) extends Controller with I18nSupport  
   def index = Action  implicit request => 
      Ok(views.html.index("blah bla blah")) 

在更详细地研究了 Play Framework 文档 (here) 之后,我了解了一种从模板中访问消息的替代方法(这可能也更简洁)。

Application.scala(新)

class Application extends Controller  
   def index = Action 
      Ok(views.html.index("blah bla blah"))
   

index.scala.html(新)

@import play.i18n._
@(text: String)
@main("Fancy title") 
  <h1>@Messages.get("header.index")</h1>
  <div>@text</div>

ma​​in.scala.html(新)

@import play.i18n._
@(title: String)(content: Html)
  <html>
    <head>
      <title>@title</title>
    </head>
    <body>
      <h1>@Messages.get("header.main")</h1>
      @content
    <body>
  </html>

控制器不再需要所有额外的基础设施。

视图需要添加导入语句,但丢失了隐式参数声明。

使用@Messages.get("xyz") 而不是@Messages("xyz") 访问消息。


目前这种方法适合我的需要。

【讨论】:

这个解决方案比较干净,但是,当你想改变一个语言时,你怎么办?【参考方案3】:

Play 框架会将您的请求隐式转换为 MessagesApi 以供您查看。但是,您确实需要在控制器方法中包含 request =&gt; 隐式参数。还要在你的控制器中包含I18nSupport trait。

import play.api.i18n.MessagesApi, I18nSupport

@Singleton
class HomeController @Inject() (cc: ControllerComponents)
extends AbstractController(cc) with I18nSupport 

  def showIndex = Action  implicit request =>
    Ok(views.html.index("All the langs"))
  

【讨论】:

以上是关于Play/Scala 中的隐式参数和组合视图的主要内容,如果未能解决你的问题,请参考以下文章

如何将参数传递给 Laravel 5 中的隐式控制器?

Scala隐式参数

转载:深入理解Scala的隐式转换系统

深入理解Scala的隐式转换系统

找不到参数元组的隐式值

Scala 类型参数化,Shapeless - 找不到参数 Generic 的隐式值