1

This question builds upon a case I found here

index.scala.html

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

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

main.scala.html

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

In this example I have index calling main and I would like both to access messages.

The compiler gives me "could not find implicit value for parameter messages: play.api.i18n.Messages" inside of index but if I remove the implicit parameter declaration from main then index works fine and gets the message. It seems like the compiler is telling me that it doesn't know how to pass the implicit parameter down the line.

Before trying with workarounds I would like to understand why this doesn't work.

3 Answers 3

1

In Play 2.4 you need to Inject MessageAPI in your controller and call preferred menu in your action to create message. if you define it as implicit in your action. Then everything will work.

Sign up to request clarification or add additional context in comments.

3 Comments

Hi Soroosh, as I mention in my question I got this to work partially by doing exactly what you are saying. Here's my controller:
class Application @Inject() (val messagesApi: MessagesApi) extends Controller with I18nSupport { def index = Action { implicit request => Ok(views.html.index("blah bla blah")) } The issue arises when I try to use messages inside main which is called by index which is called by the controller. I'm looking for a clean way to inject all nested views with some global data (in this case the messages)
what do you exactly mean by call preferred menu in your action to create message?
1

First of all let me add the code for the controller in order to make my original example clearer.

Application.scala (original)

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

After studying the Play Framework docs in greater detail (here) I learned about an alternative approach for accessing messages from within the templates (which is probably cleaner as well).

Application.scala (new)

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

index.scala.html (new)

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

main.scala.html (new)

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

The controller does not need all the additional infrastructure anymore.

The views need to add an import statement but lose the implicit param declaration.

The Messages are accessed using @Messages.get("xyz") instead of @Messages("xyz").


For the time being this approach suits my needs.

1 Comment

This solution is cleaner, but, how do you do when you want to change a lang?
0

Play framework will implicitly convert your request to the MessagesApi for your view. However, you do need to include the request => implicit parameter in your controller method. Also include the I18nSupport trait in your controller.

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"))
  }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.