文件

§使用訊息進行國際化

§指定應用程式支援的語言

使用語言標籤來指定應用程式的語言,語言標籤是特別格式化的字串,用於識別特定語言。語言標籤可以指定簡單的語言,例如「en」代表英文,語言的特定區域方言(例如「en-AU」代表澳洲使用的英文),語言和文字系統(例如「az-Latn」代表以拉丁文字系統書寫的亞塞拜然語),或這些選項的組合(例如「zh-cmn-Hans-CN」代表中文、普通話、簡體字,在中國使用)。

首先,您需要在 conf/application.conf 檔案中指定應用程式支援的語言

play.i18n.langs = [ "en", "en-US", "fr" ]

這些語言標籤將用於建立 play.api.i18n.Lang 實例。若要存取應用程式支援的語言,您可以將 play.api.i18n.Langs 元件注入您的類別

import javax.inject.Inject

import play.api.i18n.Lang
import play.api.i18n.Langs
import play.api.mvc.Action
import play.api.mvc.AnyContent
import play.api.mvc.BaseController
import play.api.mvc.ControllerComponents

class ScalaI18nService @Inject() (langs: Langs) {
  val availableLangs: Seq[Lang] = langs.availables
}

個別的 play.api.i18n.Lang 可以透過使用 lang.toLocale 轉換為 java.util.Locale 物件

val locale: java.util.Locale = lang.toLocale

§外部化訊息

您可以在 conf/messages.xxx 檔案中外部化訊息。

預設的 conf/messages 檔案符合所有語言。此外,您可以指定特定語言的訊息檔案,例如 conf/messages.frconf/messages.en-US

訊息可透過 MessagesApi 實例取得,該實例可透過注入新增。然後,您可以使用 play.api.i18n.MessagesApi 物件擷取訊息

import play.api.i18n.MessagesApi

class MyService @Inject() (langs: Langs, messagesApi: MessagesApi) {
  val lang: Lang = langs.availables.head

  val title: String = messagesApi("home.title")(lang)
}

您也可以讓語言隱含,而不是宣告語言

class MyOtherService @Inject() (langs: Langs, messagesApi: MessagesApi) {
  implicit val lang: Lang = langs.availables.head

  lazy val title: String = messagesApi("home.title")
}

Play 提供預先定義的訊息來驗證表單。您可以使用預設訊息檔案或任何語言特定的訊息檔案覆寫這些訊息。您可以在下方看到哪些訊息可以覆寫

# Copyright (C) from 2022 The Play Framework Contributors <https://github.com/playframework>, 2011-2021 Lightbend Inc. <https://www.lightbend.com>

# Default messages

# --- Constraints
constraint.required=Required
constraint.min=Minimum value: {0}
constraint.max=Maximum value: {0}
constraint.minLength=Minimum length: {0}
constraint.maxLength=Maximum length: {0}
constraint.email=Email
constraint.pattern=Required pattern: {0}

# --- Formats
format.date=Date (''{0}'')
format.numeric=Numeric
format.real=Real
format.uuid=UUID

# --- Patterns for Formats
formats.date=yyyy-MM-dd

# --- Errors
error.invalid=Invalid value
error.invalid.java.util.Date=Invalid date value
error.required=This field is required
error.number=Numeric value expected
error.real=Real number value expected
error.real.precision=Real number value with no more than {0} digit(s) including {1} decimal(s) expected
error.min=Must be greater or equal to {0}
error.min.strict=Must be strictly greater than {0}
error.max=Must be less or equal to {0}
error.max.strict=Must be strictly less than {0}
error.minLength=Minimum length is {0}
error.maxLength=Maximum length is {0}
error.email=Valid email required
error.pattern=Must satisfy {0}
error.date=Valid date required
error.uuid=Valid UUID required

error.expected.date=Date value expected
error.expected.date.isoformat=Iso date value expected
error.expected.time=Time value expected
error.expected.jsarray=Array value expected
error.expected.jsboolean=Boolean value expected
error.expected.jsnumber=Number value expected
error.expected.jsobject=Object value expected
error.expected.jsstring=String value expected
error.expected.jsnumberorjsstring=String or number expected
error.expected.keypathnode=Node value expected
error.expected.uuid=UUID value expected
error.expected.validenumvalue=Valid enumeration value expected
error.expected.enumstring=String value expected

error.path.empty=Empty path
error.path.missing=Missing path
error.path.result.multiple=Multiple results for the given path

§使用訊息和 MessagesProvider

由於通常需要使用訊息而不需要提供參數,因此您可以將給定的 LangMessagesApi 包裝在一起,以建立 play.api.i18n.Messages 執行個體。如果您想直接建立一個執行個體,play.api.i18n.MessagesImpl 案例類別會實作 Messages 特質

val messages: Messages = MessagesImpl(lang, messagesApi)
val title: String      = messages("home.title")

您也可以使用單例物件方法,並使用隱含的 play.api.i18n.MessagesProvider

implicit val messagesProvider: MessagesProvider = {
  MessagesImpl(lang, messagesApi)
}
// uses implicit messages
val title2 = Messages("home.title")

play.api.i18n.MessagesProvider 是一個特質,可以依需求提供 Messages 物件。Messages 的執行個體會延伸 MessagesProvider,並傳回它自己。

當由非 Messages 的項目延伸時,MessagesProvider 最為有用

implicit val customMessagesProvider: MessagesProvider = new MessagesProvider {
  // resolve messages at runtime
  override def messages: Messages = { ... }
}
// uses implicit messages
val title3: String = Messages("home.title")

§與控制器一起使用訊息

您可以透過延伸 MessagesAbstractControllerMessagesBaseController,將 Messages 支援新增到您的要求

import javax.inject.Inject

import play.api.i18n._

class MyMessagesController @Inject() (mcc: MessagesControllerComponents) extends MessagesAbstractController(mcc) {
  def index = Action { implicit request: MessagesRequest[AnyContent] =>
    val messages: Messages = request.messages
    val message: String    = messages("info.error")
    Ok(message)
  }

  def messages2 = Action { implicit request: MessagesRequest[AnyContent] =>
    val lang: Lang      = request.messages.lang
    val message: String = messagesApi("info.error")(lang)
    Ok(message)
  }

  def messages4 = Action { implicit request: MessagesRequest[AnyContent] =>
    // MessagesRequest is an implicit MessagesProvider
    Ok(views.html.formpage())
  }
}

或將 play.api.i18n.I18nSupport 特質新增至控制器,並確保 MessagesApi 的實例在作用範圍內,它將使用隱含式來轉換要求。

import javax.inject.Inject

import play.api.i18n._

class MySupportController @Inject() (val controllerComponents: ControllerComponents)
    extends BaseController
    with I18nSupport {
  def index: Action[AnyContent] = Action { implicit request =>
    // type enrichment through I18nSupport
    val messages: Messages = request.messages
    val message: String    = messages("info.error")
    Ok(message)
  }

  def messages2: Action[AnyContent] = Action { implicit request =>
    // type enrichment through I18nSupport
    val lang: Lang      = request.lang
    val message: String = messagesApi("info.error")(lang)
    Ok(message)
  }

  def messages3: Action[AnyContent] = Action { request =>
    // direct access with no implicits required
    val messages: Messages = messagesApi.preferred(request)
    val lang               = messages.lang
    val message: String    = messages("info.error")
    Ok(message)
  }

  def messages4: Action[AnyContent] = Action { implicit request =>
    // takes implicit Messages, converted using request2messages
    // template defined with @()(implicit messages: Messages)
    Ok(views.html.formpage())
  }
}

Twirl 範本中的所有表單輔助程式都會採用 MessagesProvider,並且假設在處理表單時,會將 MessagesProvider 作為隱含式參數傳遞至範本。

@(form: Form[Foo])(implicit messages: MessagesProvider)

@helper.inputText(field = form("name")) @* <- takes MessagesProvider *@

§從 HTTP 要求中擷取支援的語言

您可以擷取特定 HTTP 要求所支援的語言

def index: Action[AnyContent] = Action { request =>
  Ok("Languages: " + request.acceptLanguages.map(_.code).mkString(", "))
}

§要求類型

I18nSupport 特質會將下列方法新增至 Request

偏好的語言會從 Accept-Language 標頭(以及語言 Cookie,視情況而定)中擷取,並使用 messagesApi.preferred 比對 MessagesApi 支援的語言之一。

I18nSupport 也會將兩個方便的方法新增至 Result

例如

def homePageInFrench: Action[AnyContent] = Action {
  Redirect("/user/home").withLang(Lang("fr"))
}

def homePageWithDefaultLang: Action[AnyContent] = Action {
  Redirect("/user/home").withoutLang
}

withLang 方法會設定名為 PLAY_LANG 的 Cookie,供未來要求使用,而 withoutLang 會捨棄 Cookie,而 Play 會根據客戶端的 Accept-Language 標頭選擇語言。

可以透過變更設定參數來變更 Cookie 名稱:play.i18n.langCookieName

§隱含語言轉換

可以在控制器上宣告 LangImplicits 特質,以在給定隱含 Lang 實例的情況下,將要求隱含轉換為 Messages

import play.api.i18n.LangImplicits

class MyClass @Inject() (val messagesApi: MessagesApi) extends LangImplicits {
  def convertToMessage: Unit = {
    implicit val lang: Lang = Lang("en")
    val messages: Messages  = lang2Messages // implicit conversion
  }
}

§訊息格式

訊息使用 java.text.MessageFormat 函式庫進行格式化。例如,假設您有定義類似這樣的訊息

files.summary=The disk {1} contains {0} file(s).

然後您可以指定參數為

Messages("files.summary", d.files.length, d.name)

§關於撇號的注意事項

由於訊息使用 java.text.MessageFormat,請注意單引號用作轉譯參數替換的元字元。

例如,如果您有定義下列訊息

info.error=You aren''t logged in!
example.formatting=When using MessageFormat, '''{0}''' is replaced with the first parameter.

您應該會看到下列結果

messagesApi("info.error") == "You aren't logged in!"
messagesApi("example.formatting") == "When using MessageFormat, '{0}' is replaced with the first parameter."

§明確的 MessagesApi

MessagesApi 的預設實作是 DefaultMessagesApi。您可以在文件中的測試區段看到 單元測試功能測試 範例。

您也可以在測試中使用 Helpers.stubMessagesApi() 來提供預先製作的空 MessagesApi

下一頁:相依性注入


在此文件發現錯誤?此頁面的原始碼可在此處找到 here。在閱讀 文件指南 後,請隨時貢獻一個 pull request。有問題或建議要分享?前往 我們的社群論壇 與社群開始對話。