【问题标题】:Localizable form validation messages可本地化的表单验证消息
【发布时间】:2025-11-30 06:30:01
【问题描述】:

如何在 Play Framework 2.2.1 中声明可本地化的表单验证消息,包括需要参数的消息?

例如,给定conf/messages 中的这些本地化消息:

password.tooShort="Password needs at least {0} characters."
password.doNotMatch="Passwords don't match."

还有这样的表单定义:

val minLength = 8
val changePasswordForm = Form (
  Password ->
    tuple(
      Password1 -> nonEmptyText.verifying("password.tooShort", p => p.length() >= minLength),
      Password2 -> nonEmptyText
    ).verifying("password.doNotMatch", passwords => passwords._1 == passwords._2)
)

如何声明第一个字段 (Password1) 的验证消息以使用适当的参数 (minLength)?

表单定义调用verifying,只接受不带参数的String消息:

def verifying(error: => String, constraint: (T => Boolean)): Mapping[T] = {
  verifying(Constraint { t: T =>
    if (constraint(t)) Valid else Invalid(Seq(ValidationError(error)))
  })
}

此外,在表单定义期间调用 Messages() 不起作用,因为它会导致使用默认语言,而不是每个请求的语言。

【问题讨论】:

    标签: forms scala playframework internationalization playframework-2.2


    【解决方案1】:

    在表单定义期间调用 play.api.i18n.Messages 不起作用,因为范围内没有 play.api.i18n.Lang 对象。将表单定义从 val 更改为 def 并为 Lang 对象添加一个隐式方法参数。

    val minLength = 8
    def changePasswordForm(implicit lang: play.api.i18n.Lang) = Form (
      Password ->
        tuple(
          Password1 -> nonEmptyText.verifying(Messages("password.tooShort",minLength), p => p.length() >= minLength),
          Password2 -> nonEmptyText
        ).verifying(Messages("password.doNotMatch"), passwords => passwords._1 == passwords._2)
    )
    

    您需要在具有隐式请求范围的控制器操作中使用此表单定义。该请求将自动提供 Lang 对象。

    例子:

    def myAction = Action { implicit request =>
        Ok(html.myFormPage(changePasswordForm))
    }
    

    【讨论】:

      【解决方案2】:

      如果您使用内置的 minLength 验证器,这将为您开箱即用。如果您真的想重新实现它,请查看默认的实现方式,其中包含 Play 的源代码,因此您已经在硬盘上拥有它们。你可以在YOUR_PLAY_INSTALLATION/framework/src/play/src/main/scala/play/api/data/validation/Validation.scala中找到内置的验证逻辑

      【讨论】:

        最近更新 更多