Facebook Twitter LinkedIn E-mail
magnify
Home 2014 十一月

Play Framework Web开发教程(36): 多国语言支持

你所写的Web应用的用户可能来自不同的国家,他们使用不同的语言,已经使用不同的数字,日期等格式,Play提供了一些工具来帮助你支持应用的国际化。
不同的语言和格式规则成为”locale”,应用适应不同的”locale”称为国际化和本地化。国际化和本地化比较容易混淆,国际化指去除应用中和某些特定“locale”相关的代码。而本地化指构造某个特定locale的应用版本。对于一个支持国际化的应用来说,它应该支持多种可选的语言。在实际应用中,国际化和本地化是同时使用的。
本篇侧重介绍国际化应用中的静态部分(通常你在模板中hardcode的部分或是一些错误信息)。
配置message文件
在Play构造一个本地化的应用涉及如何书写message文件。比如,避免在应用中直接使用如”Log in”,”Thank you for your order”或”Email is required”等文字,我们可以定义一个message文件,对于不同的语言支持,我们分别构造对于的message文件:比如:

welcome = Welcome!
users.login = Log in
shop.thanks = Thank you for your order

这里我们可以看到如果使用message键值来替代实际显示的文字。 这里”.”没有特殊的意义,但可以帮助消息分组。

为了支持多国语言,我们需要在应用的配置文件中定义所要支持的语言,例如,我们修改application.conf文件,支持以下几种语言:

application.langs="en,en-US,nl"

支持的语言使用逗号隔开,支持的语言使用ISO 639-2 语言代码,加上可选的国家代码。比如上面的en-US代码美国英语。

然后,对于不同的语言,我们在conf目录构造对应的message文件,其命名规则为 messages.LANG ,其中LANG 使用具体的语言代码替代。比如法语fr,我们使用messages.fr文件名。
除此之外,我们创建一个不带后缀名的文件messages作为缺省语言,如果某个message没有翻译成所需的语言,那么就使用定义在messages文件中的定义。因此使用多国语言一般首先定义messages文件,确保定义完整的message。这样解释你忘记在某种语言的messages.LANG忘记定义某个键,那么还会显示缺省的文字。

在应用中使用message

在应用中使用message,你可以使用Messages的apply方法,例如:

Messages("users.login")(Lang("en"))

这个方法有两个参数列表,第一个参数列表为消息和消息参数,第二个参数列表为Lang参数,这个参数是一个implicit定义,通常Play应用提供了隐含的Lang定义,这个Lang定义基于机器缺省的locale定义。

Play 框架定义了由Request到Lang的隐含转换,这给我们带来很大的便利。如果在当前作用域有一个隐含的Request,那么就会有一个隐含的Lang定义(基于request的Accept-Language消息头)。比如你有如下的一个action方法:

def welcome() = Action { implicit request =>
  Ok(Messages("welcome"))
}

Play根据请求的消息头来决定使用哪种语言。如果消息头指明可以接受多种语言,那么Play就依次尝试这些语言,然后选取第一个可用的语言。如果消息头没有定义语言,那么Play选用application.conf定义的第一个语言。

同样,你可以在View模板中使用同样的语法来使用消息:

@()
<h1>@Messages("welcome")</h1>

要注意的是,如果你需要支持自动选取语言,那么你需要引入隐含的Request做为模板参数:

@(implicit request: Request)
<h1>@Messages("welcome")</h1>

此外,message 不仅仅支持前面定义的简单的文字串,也可以使用java.text.MessageFormat来格式化,也就是意味着你可以使用参数来定义字符串,例如:

validation.required={0} is required

然后再使用时,使用实际的文字来替换这些参数:

Messages("validation.required", "email")

再比如,你需要根据参数显示不同的信息,比如根据购物框中物品的数量显示不同的信息,可以定义如下的message:

shop.basketcount=Your cart {0,choice,0#is empty|1#has one item
|1< has {0} items}.

然后在应用中如果我们使用如下调用:

<p>@Messages("shop.basketcount", 0)</p>
<p>@Messages("shop.basketcount", 1)</p>
<p>@Messages("shop.basketcount", 10)</p>

那么实际显示:

Your cart is empty.
Your cart has one item.
Your cart has 10 items.