`

Play framework 国际化

阅读更多
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也马上要支持国际化啦。
    1
    1
    分享到:
    评论
    3 楼 yangzai911 2013-12-09  
    如果 accept-language中有值,那么也是默认取第一个么?
    2 楼 kelepingzi 2012-05-03  
    ,期待,速度真快。快跟不上了
    1 楼 明心Xin 2012-05-03  

    相关推荐

    Global site tag (gtag.js) - Google Analytics