Reputation: 7563
I am trying to put internationalization on my Play for Scala example. I am following the book Play for Scala. I am getting errors about which parameter long use (play.i18n.Lang
or play.api.i18n.Messages
). The problem is that when I use play.api.i18n.Messages
the method @Messages("products.form")
and I have to use @Messages.get("products.form")
from play.i18n.Lang
. The errors are:
[info] Compiling 21 Scala sources and 1 Java source to /home/felipe/workspace-play/products/target/scala-2.11/classes...
[error] /home/felipe/workspace-play/products/app/controllers/Products.scala:34: could not find implicit value for parameter lang: play.i18n.Lang
[error] Ok(views.html.products.details(product))
[error] ^
[error] /home/felipe/workspace-play/products/app/views/products/editProduct.scala.html:13: could not find implicit value for parameter messages: play.api.i18n.Messages
[error] @helper.inputText(productForm("ean"))
[error] ^
[error] /home/felipe/workspace-play/products/app/views/products/editProduct.scala.html:14: could not find implicit value for parameter messages: play.api.i18n.Messages
[error] @helper.inputText(productForm("name"))
[error] ^
[error] /home/felipe/workspace-play/products/app/views/products/editProduct.scala.html:15: could not find implicit value for parameter messages: play.api.i18n.Messages
[error] @helper.textarea(productForm("description"))
[error] ^
[error] /home/felipe/workspace-play/products/app/views/products/list.scala.html:4: could not find implicit value for parameter lang: play.i18n.Lang
[error] @main(Messages.get("application.name")) {
[error] ^
[error] 5 errors found
My controller :
package controllers
import models.Product
import play.api.mvc.{Action, Controller}
import play.api.data.Form
import play.api.data.Forms.{mapping, longNumber, nonEmptyText}
import play.api.mvc.Flash
import play.i18n._
// import play.api.i18n.Messages
// import play.api.Play.current
// import play.api.i18n.Messages.Implicits._
/**
* Created by felipe on 6/4/16.
*/
class Products extends Controller {
private val productForm: Form[Product] = Form(
mapping(
"ean" -> longNumber.verifying(
"validation.ean.duplicate", Product.findByEan(_).isEmpty),
"name" -> nonEmptyText,
"description" -> nonEmptyText
)(Product.apply)(Product.unapply)
)
def list = Action { implicit request =>
val products = Product.findAll
Ok(views.html.products.list(products))
}
def show(ean: Long) = Action { implicit request =>
Product.findByEan(ean).map { product =>
Ok(views.html.products.details(product))
}.getOrElse(NotFound)
}
def save = Action { implicit request =>
val newProductForm = productForm.bindFromRequest()
newProductForm.fold(
hasErrors = { form =>
Redirect(routes.Products.newProduct()).
flashing(Flash(form.data) +
("error" -> Messages.get("validation.errors")))
},
success = { newProduct =>
Product.add(newProduct)
val message = Messages.get("products.new.success", newProduct.name)
Redirect(routes.Products.show(newProduct.ean)).flashing("success" -> message)
}
)
}
def newProduct = Action { implicit request =>
val form = if (request.flash.get("error").isDefined)
productForm.bind(request.flash.data)
else
productForm
Ok(views.html.products.editProduct(form))
}
}
My view:
@(productForm: Form[Product])(implicit flash: Flash, lang: Lang)
@import play.i18n._
@import helper._
@main(Messages.get("products.form")) {
<h2>@Messages.get("products.form")</h2>
@helper.form(action = routes.Products.save()) {
<fieldset>
<legend>
@Messages.get("products.details", Messages.get("products.new"))
</legend>
@helper.inputText(productForm("ean"))
@helper.inputText(productForm("name"))
@helper.textarea(productForm("description"))
</fieldset>
<p>
<input type="submit" class="btn primary" value='@Messages.get("products.new.submit")'>
</p>
}
}
Upvotes: 1
Views: 2574
Reputation: 7563
I got it to work! Thanks anyway. Here is my solution based on this question.
I am using view form helpers (such as @inputText
) requires you to pass an implicit play.api.i18n.Messages
parameter to your view. You can do this adding (implicit messages: Messages
) to the signature. Then I am using application controller with this parameter implicitly available in my scope. The simplest way to do this is to implement play's I18nSupport
trait.
package controllers
import javax.inject.Inject
import models.Product
import play.api.mvc.{Action, Controller}
import play.api.data.Form
import play.api.data.Forms.{longNumber, mapping, nonEmptyText}
import play.api.i18n.{I18nSupport, Messages, MessagesApi}
import play.api.mvc.Flash
/**
* Created by felipe on 6/4/16.
*/
class Products @Inject()(val messagesApi: MessagesApi) extends Controller with I18nSupport {
private val productForm: Form[Product] = Form(
mapping(
"ean" -> longNumber.verifying(
"validation.ean.duplicate", Product.findByEan(_).isEmpty),
"name" -> nonEmptyText,
"description" -> nonEmptyText
)(Product.apply)(Product.unapply)
)
def list = Action { implicit request =>
val products = Product.findAll
Ok(views.html.products.list(products))
}
def show(ean: Long) = Action { implicit request =>
Product.findByEan(ean).map { product =>
Ok(views.html.products.details(product))
}.getOrElse(NotFound)
}
def save = Action { implicit request =>
val newProductForm = productForm.bindFromRequest()
newProductForm.fold(
hasErrors = { form =>
Redirect(routes.Products.newProduct()).
flashing(Flash(form.data) +
("error" -> Messages("validation.errors")))
},
success = { newProduct =>
Product.add(newProduct)
val message = Messages("products.new.success", newProduct.name)
Redirect(routes.Products.show(newProduct.ean)).flashing("success" -> message)
}
)
}
def newProduct = Action { implicit request =>
val form = if (request.flash.get("error").isDefined)
productForm.bind(request.flash.data)
else
productForm
Ok(views.html.products.editProduct(form))
}
}
The view:
@(productForm: Form[Product])(implicit flash: Flash, messages: Messages)
@import helper._
@main(Messages("products.form")) {
<h2>@Messages("products.form")</h2>
@helper.form(action = routes.Products.save()) {
<fieldset>
<legend>
@Messages("products.details", Messages("products.new"))
</legend>
@helper.inputText(productForm("ean"))
@helper.inputText(productForm("name"))
@helper.textarea(productForm("description"))
</fieldset>
<p>
<input type="submit" class="btn primary" value='@Messages("products.new.submit")'>
</p>
}
}
Upvotes: 1