Play的国际化操作还是非常简单的。大概分为四步:
1. 首先在${project_home}/conf/application.conf中定义你要用到的哪些国际化语言
application.langs=en,zh
2. 在${project_home}/conf/下新建两个 message 文件,后缀名跟上面定义的语言一样。
message.en
message.zh
message.en
welcome = Welcome to China
message.zh
welcome = 欢迎来到中国
3. 在模板文件里调用这些message
<h1>&{welcome}</h1>
4. 在你的程序启动的时候进行国际化的设置(如果不设置,Play框架会有一套自己的解决方案)
Lang.set("zh")//设置为中文
PS:启动程序之后,你可以在页面上写一个改变国际化语言的按钮,后台处理的时候也是调用这个 Lang.set(locale).
我们来看看Play.Lang类的源代码
package play.i18n;
import java.util.Locale;
import play.Logger;
import play.Play;
import play.mvc.Http;
import play.mvc.Http.Request;
import play.mvc.Http.Response;
/**
* Language support
*/
public class Lang {
public static ThreadLocal<String> current = new ThreadLocal<String>();
/**
* Retrieve the current language or null
* @return The current language (fr, ja, it ...) or null
*/
public static String get() {
String locale = current.get();
if (locale == null) {
// don't have current locale for this request - must try to resolve it
Http.Request currentRequest = Http.Request.current();
if (currentRequest!=null) {
// we have a current request - lets try to resolve language from it
resolvefrom( currentRequest );
} else {
// don't have current request - just use default
setDefaultLocale();
}
// get the picked locale
locale = current.get();
}
return locale;
}
/**
* Force the current language
* @param locale (fr, ja, it ...)
* @return false if the language is not supported by the application
*/
public static boolean set(String locale) {
if (locale.equals("") || Play.langs.contains(locale)) {
current.set(locale);
return true;
} else {
Logger.warn("Locale %s is not defined in your application.conf", locale);
return false;
}
}
/**
* Clears the current language - This wil trigger resolving language from request
* if not manually set.
*/
public static void clear() {
current.remove();
}
/**
* Change language for next requests
* @param locale (fr, ja, it ...)
*/
public static void change(String locale) {
if (set(locale)) {
Response.current().setCookie(Play.configuration.getProperty("application.lang.cookie", "PLAY_LANG"), locale);
}
}
/**
* Guess the language for current request in the following order:
* [list=1]
* [*]if a <b>PLAY_LANG</b> cookie is set, use this value
* [*]if <b>Accept-Language</b> header is set, use it only if the Play! application allows it.<br/>supported language may be defined in application configuration, eg : [i]play.langs=fr,en,de)[/i]
* <li>otherwise, server's locale language is assumed
* [/list]
* @param request
*/
private static void resolvefrom(Request request) {
// Check a cookie
String cn = Play.configuration.getProperty("application.lang.cookie", "PLAY_LANG");
if (request.cookies.containsKey(cn)) {
String localeFromCookie = request.cookies.get(cn).value;
if (localeFromCookie != null && localeFromCookie.trim().length()>0) {
if (set(localeFromCookie)) {
// we're using locale from cookie
return;
}
// could not use locale from cookie - clear the locale-cookie
Response.current().setCookie(cn, "");
}
}
// Try from accept-language - look for an exact match
for (String a: request.acceptLanguage()) {
a = a.replace("-", "_").toLowerCase();
for (String locale: Play.langs) {
if (locale.toLowerCase().equals(a)) {
set(locale);
return;
}
}
}
// now see if we have a country-only match
for (String a: request.acceptLanguage()) {
if (a.indexOf("-") > 0) {
a = a.substring(0, a.indexOf("-"));
}
for (String locale: Play.langs) {
if (locale.equals(a)) {
set(locale);
return;
}
}
}
// Use default
setDefaultLocale();
}
public static void setDefaultLocale() {
if (Play.langs.isEmpty()) {
set("");
} else {
set(Play.langs.get(0));
}
}
/**
*
* @return the default locale if the Locale cannot be found otherwise the locale
* associated to the current Lang.
*/
public static Locale getLocale() {
String lang = get();
Locale locale = getLocale(lang);
if (locale != null) {
return locale;
}
return Locale.getDefault();
}
public static Locale getLocale(String lang) {
for (Locale locale : Locale.getAvailableLocales()) {
if (locale.getLanguage().equals(lang)) {
return locale;
}
}
return null;
}
}
不难看出,Play在获取国际化设置的时候大概是这么处理的:
1.首先从 ThreadLocal 中获取,这个地方是由开发者在代码手动 set 的,也就是 Lang.set("zh")这样的。
2.如果 ThreadLocal 没有,则框架会自己去尝试解决,首先会从 Cookie 中获取,如果没有就从 HTTP 请求中获取 Header 的 accept-language 。如果还没有,那么就会去做一个默认的设置。默认的设置规则是:如果 application.conf 有定义的话,那么取第一个,如果没有,那么设置为空字符串“”。
以上的整个过程仅是我个人见解,欢迎指正:)
PS:eweb4j也马上要支持国际化啦。