欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Play framework 国际化

程序员文章站 2022-06-08 12:50:27
...
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也马上要支持国际化啦。