§使用訊息進行國際化
§指定應用程式支援的語言
使用語言標籤來指定應用程式的語言,語言標籤是特別格式化的字串,用於識別特定語言。語言標籤可以指定簡單的語言,例如「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.fr
或 conf/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
由於通常需要使用訊息而不需要提供參數,因此您可以將給定的 Lang
與 MessagesApi
包裝在一起,以建立 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")
§與控制器一起使用訊息
您可以透過延伸 MessagesAbstractController
或 MessagesBaseController
,將 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
request.messages
會使用隱含式MessagesApi
傳回Messages
的實例request.lang
會使用隱含式MessagesApi
傳回偏好的Lang
偏好的語言會從 Accept-Language
標頭(以及語言 Cookie,視情況而定)中擷取,並使用 messagesApi.preferred
比對 MessagesApi
支援的語言之一。
§語言 Cookie 支援
I18nSupport
也會將兩個方便的方法新增至 Result
result.withLang(lang: Lang)
用於使用 Play 的語言 Cookie 設定語言。result.withoutLang
用於清除語言 Cookie。
例如
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。有問題或建議要分享?前往 我們的社群論壇 與社群開始對話。