Blackbird
Blackbird

Reputation: 2378

Setting implicit language in i18n Play 2.4 Scala template

Hello Stackoverflow community!

I have i18n working in my Play 2.4 application, so that's a good start.

What I want to do now is to override the implicit Lang sent to a template. For example, if the IP address is located in Sweden, I want to set the implicit Lang to Swedish regardless of what preferred language is set in the browser. How to do this?

This is my code:

My Application.scala controller:

package controllers

import javax.inject.Inject

import play.api.i18n.{I18nSupport, Lang, MessagesApi}
import play.api.mvc._

class Application @Inject() (val messagesApi: MessagesApi) extends Controller with I18nSupport {
  def index = Action { implicit request =>
    if (isIpAddressLocatedInSweden) {
      implicit val langFromIp = Lang.apply("sv")
      Logger.info("Language set to Swedish")
    }

    Ok(views.html.index())
  }

  private def isIpAddressLocatedInSweden: Boolean = {
    [...]
  }
}

My index.scala.html view:

@()(implicit messages: Messages, lang: Lang)

@main("Page Title") {
<span>@lang.toString()</span>
<h1>@Messages("home.title")</h1>
}

Unfortunately, the result is:

Thanks for any help!

Upvotes: 2

Views: 2585

Answers (3)

Blackbird
Blackbird

Reputation: 2378

This is the cleanest way I got it to work:

Code of my Application.scala controller:

class Application @Inject()(val messagesApi: MessagesApi) extends Controller with I18nSupport {
  def index = Action { implicit request =>
    val lang = if (isIpAddressLocatedInSweden) {
      Lang.apply("sv")
    } else {
      Lang.preferred(request.acceptLanguages)
    }

    Ok(views.html.index()).withLang(lang)
  }

  private def isIpAddressLocatedInSweden: Boolean = {
    [...]
  }
}

The code of the index.scala.html view is unchanged.

Upvotes: 0

Alvaro Silvino
Alvaro Silvino

Reputation: 9763

I've done a little bit different: I forced the result to the language in the query string. It's a good form to keep the work and look for better approach later:

NOTE: I USED THE "MessagesApi" to make it happen.

package controllers

import play.api._
import play.api.mvc._
import play.api.i18n.I18nSupport
import play.api.i18n.Messages.Implicits._
import play.api.i18n.MessagesApi
import javax.inject.Inject
import play.api.i18n.Lang
import play.api.i18n._
class Application@ Inject()(val messagesApi: MessagesApi) extends Controller with I18nSupport {

  def index = Action {
    implicit request =>
      request.getQueryString("lang") match {
        case Some(lang) => messagesApi.setLang(Ok(views.html.index()(messagesApi, Lang(lang))), Lang(lang))
        case None => messagesApi.setLang(Ok(views.html.index()(messagesApi, Lang("en"))), Lang("en"))
      }
  }

}
conf/application.conf:
play.i18n.langs=["en","pt","fr"]
@()(implicit message: MessagesApi ,l: Lang)
<header>
  <li>
    <!-- change the language -->
    <a href="./?lang=en">
      <img src="@routes.Assets.versioned(" images/BR.png ")" />
    </a>
  </li>
  <li>
    <a href="./?lang=en">
      <img src="@routes.Assets.versioned(" images/US.gif ")" />
    </a>
  </li>
  <h1>@message("intro")</h1>
</header>
<p>@Html(message("description"))</p>
<p>@Html(message("description.education"))</p>

Upvotes: 1

Sully
Sully

Reputation: 544

Conflicting implicits prevent exactly overriding Messages on Play 2.4 but I believe you can get what you were roughly looking for with the code below.

This is my code:

My conf/Application.conf:

# The application languages
# ~~~~~
play.i18n.langs = [ "en", "sv" ]

My conf/messages.sv

home.title=Svedish

My Application.scala controller:

package controllers

import javax.inject.Inject

import play.api.i18n.{I18nSupport, Lang, MessagesApi}
import play.api.mvc._

class IPMessages(lang: Lang, messages: MessagesApi) extends play.api.i18n.Messages(lang, messages){}

class Application @Inject() (val messagesApi: MessagesApi) extends Controller with I18nSupport {
  def index = Action { implicit request =>
    val langFromIp = if (isIpAddressLocatedInSweden) {
       new Lang("sv") 
    } else {
        request.acceptLanguages.head
    }
    implicit val ipMessages: IPMessages = new IPMessages(langFromIp, messagesApi) 
    Ok(views.html.index())
  }

  private def isIpAddressLocatedInSweden: Boolean = true

}

My index.scala.html view:

@()(implicit messages: IPMessages)

@main("Page Title") {
<span>@messages.toString()</span>
<h1>@messages("home.title")</h1>
}

Upvotes: 0

Related Questions