58. Spring Boot國際化(i18n)【從零開始學Spring Boot】

國際化(internationalization)是設計和製造容易適應不一樣區域要求的產品的一種方式。它要求從產品中抽離全部地域語言,國家/地區和文化相關的元素。換言之,應用程序的功能和代碼設計考慮在不一樣地區運行的須要,其代碼簡化了不一樣本地版本的生產。開發這樣的程序的過程,就稱爲國際化。html

       那麼當咱們使用Spring Boot如何進行國際化呢?那麼當你讀完這篇文章你會學到以下知識:前端

(1) spring boot 加入thymeleafjava

(2) 頁面元素國際化;web

(3) spring boot默認國際化原理說明;spring

(4) firefox瀏覽器修改區域語言;sql

(5)chrome瀏覽器修改區域語言;chrome

(6)修改默認messages配置前綴;數據庫

(7) 代碼中如何獲取國際化信息;數組

(8) 優化代碼獲取國際化信息;瀏覽器

(9) 區域解析器之AcceptHeaderLocaleResolver

(10) 會話區域解析器之SessionLocaleResolver

(11) Cookie區域解析器之CookieLocaleResolver

(12)固定的區域解析器之FixedLocaleResolver 

(13)使用參數修改用戶的區域;

 

       接下里咱們看看這些具體應該怎麼操做。

(1) spring boot 加入thymeleaf

       Spring boot集成thymeleaf

18)使用模板(thymeleaf-freemarker)【從零開始學Spring Boot 

這篇文章有介紹過,因此這裏就不過多進行介紹了。在這裏咱們爲以後的講解作點基本準備。

模板文件resources/templates/hello.html :

<!DOCTYPE html>

<html>

<head>

    <meta charset="UTF-8" />

    <title>hello spring boot</title>

</head>

<body>

   

    <p>歡迎你登陸到阿里巴巴網站</p>

       

</body>

</html>

這裏沒有特殊的代碼,訪問就是顯示一些文字,這裏還沒加入國際化的相關東西,以後添加。

 

編寫訪問地址:com.kfit.controller.HelloController

package com.kfit.controller;

 

import org.springframework.stereotype.Controller;

import org.springframework.web.bind.annotation.RequestMapping;

 

@Controller

public class HelloController {

   

    @RequestMapping("/hello")

    public String hello(){

       return  "/hello";

    }

   

}

這裏就是訪問http://127.0.0.1:8080/hello就跳轉到hell.html進行訪問。

到這裏準備工做就行了。

 

(2) 頁面元素國際化;

       咱們觀察hello.html裏面的信息直接就是中文顯示,因此咱們如今的需求是當訪問語言是zh的時候顯示爲中文,當語言爲en的時候顯示爲英文,那麼怎麼操做呢?

首先咱們先定義國際化資源文件,spring boot默認就支持國際化的,並且不須要你過多的作什麼配置,只須要在resources/下定義國際化配置文件便可,注意名稱必須以messages開發。

咱們定義以下幾個文件:

messages.properties (默認,當找不到語言的配置的時候,使用該文件進行展現)。

messages_zh_CN.properties(中文)

messages_en_US.properties(英文)

具體的代碼以下:

messages.properties

welcome = 歡迎你登陸到 阿里巴巴 網站(default

messages_zh_CN.properties

welcome = \u6b22\u8fce\u4f60\u767b\u5f55\u5230 \u963f\u91cc\u5df4\u5df4 \u7f51\u7ad9\uff08\u4e2d\u6587\uff09

對應的信息是:

welcome = 歡迎你登陸到 阿里巴巴 網站(中文)

messages_en_US.properties

welcome = welcome to login to alibaba website(English)

配置信息就這麼簡單,那麼在前端展現怎麼修改呢,修改hello.html文件,使用#{key}的方式進行使用messages中的字段信息:

<!DOCTYPE html>

<html>

<head>

    <meta charset="UTF-8" />

    <title>hello spring boot</title>

</head>

<body>

    <p><label th:text="#{welcome}"></label></p>

</body>

</html>

從新訪問:http://127.0.0.1:8080/hello 應該顯示:

歡迎你登陸到 阿里巴巴 網站(中文)

 

(3) spring boot默認國際化原理說明

       在這裏咱們先打住下,簡單說下原理:

第一個問題,爲何命名必須是messages開頭,須要看一個源碼文件:

org.springframework.boot.autoconfigure.MessageSourceAutoConfiguration

這裏提取部分代碼:

/**

 * {@link EnableAutoConfiguration Auto-configuration} for {@link MessageSource}.

 *

 * @author Dave Syer

 * @author Phillip Webb

 * @author Eddú Meléndez

 */

@Configuration

@ConditionalOnMissingBean(value = MessageSource.class, search = SearchStrategy.CURRENT)

@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE)

@Conditional(ResourceBundleCondition.class)

@EnableConfigurationProperties

@ConfigurationProperties(prefix = "spring.messages")

public class MessageSourceAutoConfiguration {

 

    private static final Resource[] NO_RESOURCES = {};

 

    /**

     * Comma-separated list of basenames, each following the ResourceBundle convention.

     * Essentially a fully-qualified classpath location. If it doesn't contain a package

     * qualifier (such as "org.mypackage"), it will be resolved from the classpath root.

     */

    private String basename = "messages";

 

    /**

     * Message bundles encoding.

     */

    private Charset encoding = Charset.forName("UTF-8");

 

    /**

     * Loaded resource bundle files cache expiration, in seconds. When set to -1, bundles

     * are cached forever.

     */

    private int cacheSeconds = -1;

 

    /**

     * Set whether to fall back to the system Locale if no files for a specific Locale

     * have been found. if this is turned off, the only fallback will be the default file

     * (e.g. "messages.properties" for basename "messages").

     */

    private boolean fallbackToSystemLocale = true;

看到沒有,若是咱們沒有在application.properties中配置spring.messages屬性,那麼使用默認的messages,好了這個問題就這麼簡單解決了。

第二問題:爲何我看到的是中文(或者英文)呢?

       爲了讓web應用程序支持國際化,必須識別每一個用戶的首選區域,並根據這個區域顯示內容。在Spring MVC應用程序中,用戶的區域是經過區域解析器來識別的,它必須是實現LocaleResolver接口。Spring MVC提供了幾個LocaleResolver實現,讓你能夠按照不一樣的條件來解析區域。除此以外,你還能夠實現這個接口建立本身的區域解析器。若是沒有作特殊的處理的話,Spring 採用的默認區域解析器是AcceptHeaderLocaleResolver。它經過檢驗HTTP請求的頭部信息accept-language來解析區域。這個頭部是由用戶的wb瀏覽器底層根據底層操做系統的區域設置進行設定的。請注意,這個區域解析器沒法改變用戶的區域,由於它沒法修改用戶操做系統的區域設置。

       既然沒法修改,那麼咱們的代碼怎麼測試呢?請看以下內容?

 

(4) firefox瀏覽器修改區域語言;

       打開firefox瀏覽器訪問http://127.0.0.1:8080/hello (計算機系統語言是中文的),應該是看到以下信息:

歡迎你登陸到 阿里巴巴 網站(中文)

 

那麼咱們修改咱們的語言呢,在瀏覽器地址欄輸入以下信息:

about:config

回車進入一個警告頁面,而後點擊按鈕【我保證會當心】(注:因爲版本不同,可能會有些不同,可是操做是同樣的)。


<!--[endif]-->

在搜索框輸入accept,而後找到intl.accept_languages修改對應的值,我這裏本來是:

zh-cn, zh, en-us, en

爲了看到效果,修改成:

en-us, en

修改完以後,刷新http://127.0.0.1:8080/hello ,能夠看到信息:

welcome to login to alibaba website(English)

好了,沒有什麼特殊的需求的,記得把intl.accept_languages修改成原來的值。

 

(5)chrome瀏覽器修改區域語言;

       我以爲firefox修改起來真是簡單,chrome瀏覽器就稍微麻煩點了。

第一種方案就是下載插件:Quick Language Switcher,下載完插件以後,默認選項的比較少,你能夠在擴展程序中,打開別的語言選項或者添加自定義的語言。這個只要插件下來來操做就很簡單了,切換語言就會自動刷新頁面,就能看到效果了,特別方便。注意的是:默認有一個English,這個使用的配置文件是:messages_en.properties,因此須要添加一個配置文件才能看到效果。

 

第二種方案是修改本地的一個配置文件,參考以下地址

http://stackoverflow.com/questions/7769061/how-to-add-custom-accept-languages-to-chrome-for-pseudolocalization-testing

可是我這裏無論怎麼修改,重啓瀏覽器以後,就被重置回來了,也就是這種方案我這裏沒有配置成功。第一種方案確定是能夠的。

       別的瀏覽器就自行嘗試了,由於這不是咱們這不是咱們實際使用的重點,那麼接下來纔是重點哦。

 

(6)修改默認messages配置前綴;

       咱們在上面說了,默認的文件名稱前綴是messages_xx.properties,那麼如何修改這個名稱和路徑呢?

       這個也很簡單,只須要修改application.properties文件便可加入以下配置:

########################################################

### i18n setting.

########################################################

#指定messagebasename,多個以逗號分隔,若是不加包名的話,默認從classpath路徑開始,默認: messages

spring.messages.basename=i18n/messages

#設定加載的資源文件緩存失效時間,-1的話爲永不過時,默認爲-1

spring.messages.cache-seconds= 3600

#設定Message bundles的編碼,默認: UTF-8

#spring.messages.encoding=UTF-8

上面各個參數都註釋很清楚了,這裏很少說了,那麼咱們這裏是把文件放到了i18n下,那麼咱們在resources下新建目錄i18n,而後複製咱們建立的messages_xxx.properties文件到此目錄下。爲了區分這是讀取了新的文件,咱們能夠在每一個文件中—i18n以進行區分。

從新訪問http://127.0.0.1:8080/hello 能夠看到最新的效果了。

英文:

welcome to login to alibaba website(English-en)--i18n

中文:

歡迎你登陸到阿里巴巴網站(中文)--i18n

 

(7) 代碼中如何獲取國際化信息;

       以上講的是在模板文件進行國際化,那麼在代碼中如何獲取到welcome呢,這個比較簡單,只要在須要的地方注入類:

@Autowired

private MessageSource messageSource;

須要注意的是messageSource

org.springframework.context.MessageSource

下的類。

那麼怎麼使用了,在使用前咱們須要先知道一個知識點,如何獲得當前請求的Locale

那麼怎麼獲取呢,有兩種獲取方式:

第一種方式是:

Locale locale = LocaleContextHolder.getLocale();

第二種方式是:

Locale locale1= RequestContextUtils.getLocale(request);

我的喜愛第一種方式,由於不須要什麼參數就能夠獲取到,第二種方式依賴於當前的request請求對象。

有了當前請求的Locale剩下的就簡單了:

String msg = messageSource.getMessage("welcome", null,locale);

String msg2= messageSource.getMessage("welcome", null,locale1);

經過以上代碼的其中一種方式就能夠獲取到messages_xxx.properties文件配置的welcome屬性值了。切換區域獲取的信息也是不同的,打印信息以下:

msg=歡迎你登陸到阿里巴巴網站(中文)--i18n

msg2歡迎你登陸到阿里巴巴網站(中文)--i18n

msg=welcome to login to alibaba website(English-en)--i18n

msg2welcome to login to alibaba website(English-en)--i18n

 

(8) 優化代碼獲取國際化信息;

       學習是永無止境的,活到老學到老。查看上面的代碼你會發現這個是實際中使用起來的時候仍是不是很方面,ok,沒有關係,這個小節咱們就對上面的代碼優化下,

自定義咱們本身的MessageSource,具體代碼以下:

package com.kfit.common;

 

import java.util.Locale;

import javax.annotation.Resource;

import org.springframework.context.MessageSource;

import org.springframework.context.i18n.LocaleContextHolder;

import org.springframework.stereotype.Component;

 

@Component

public class LocaleMessageSourceService {

   

    @Resource

    private MessageSource messageSource;

   

    /**

     * @param code 對應messages配置的key.

     * @return

     */

    public String getMessage(String code){

       return getMessage(code,null);

    }

   

    /**

     *

     * @param code 對應messages配置的key.

     * @param args : 數組參數.

     * @return

     */

    public String getMessage(String code,Object[] args){

       return getMessage(code, args,"");

    }

   

 

    /**

     *

     * @param code 對應messages配置的key.

     * @param args : 數組參數.

     * @param defaultMessage : 沒有設置key的時候的默認值.

     * @return

     */

    public String getMessage(String code,Object[] args,String defaultMessage){

       //這裏使用比較方便的方法,不依賴request.

       Locale locale = LocaleContextHolder.getLocale();

       return messageSource.getMessage(code, args, defaultMessage, locale);

    }

   

}

在這個代碼中我封裝了3個經常使用的方法,那麼應該怎麼調用呢?也很簡單,在須要的地方使用以下代碼進行注入:

@Resource

private LocaleMessageSourceService localeMessageSourceService;

在須要的地方使用以下代碼進行調用:

String msg3 = localeMessageSourceService.getMessage("welcome");

這個代碼比以前的代碼使用起來爽多了,還有不少神妙之處,你們本身發現吧。

 

(9) 區域解析器之AcceptHeaderLocaleResolver

       看到上面,你們會認爲國際化也就到此了,可是我告訴你們這以後纔是spring的強大之處呢,考慮的多麼周到呢。

       咱們在以前說過,咱們只因此能夠看到國際化的效果是由於有一個區域解析器在進行處理。默認的區域解析器就是AcceptHeaderLocaleResolver。咱們簡單說明這個解析器:

       Spring採用的默認區域解析器是AcceptHeaderLocaleResolver。它經過檢驗HTTP請求的accept-language頭部來解析區域。這個頭部是由用戶的web瀏覽器根據底層操做系統的區域設置進行設定。請注意,這個區域解析器沒法改變用戶的區域,由於它沒法修改用戶操做系統的區域設置。

       好了,這個默認的介紹到這裏,由於這個咱們沒法改變,因此這種默認的設置在實際中使用的比較少。因此你若是看到當前還沒法知足的需求的話,那麼接着往下看,博主已經幫你都想到了。

 

(10) 會話區域解析器之SessionLocaleResolver

       會話區域解析器也就是說,你設置完只針對當前的會話有效,session失效,還原爲默認狀態。那麼這個具體怎麼操做呢?具體操做起來也是很簡單的,咱們須要在咱們的啓動類App.java(按你的實際狀況進行修改)配置區域解析器爲SessionLocaleResolver,具體代碼以下:

   @Bean

    public LocaleResolver localeResolver() {

        SessionLocaleResolver slr = new SessionLocaleResolver();

        //設置默認區域,

        slr.setDefaultLocale(Locale.CHINA);

        return slr;

    }

其實到這裏咱們就完事了,你能夠經過setDefaultLocale()設置默認的語言,啓動就訪問http://127.0.0.1:8080/hello 進行查看,是否是已經實現國際化了。

       到這裏固然還不是很完美,還須要在進一步的優化了,那麼怎麼在頁面中進行切換呢?那麼假設頁面上有兩個按鈕【切換爲中文】、【切換爲英文】就能夠進行切換了。接下來一塊兒來實現下:在hello.html添加以下代碼:

<form action="/changeSessionLanauage" method="get">

       <input name="lang" type="hidden" value="zh"  />

       <button>切換爲中文</button>

    </form>

   

    <form action="/changeSessionLanauage" method="get">

       <input name="lang" type="hidden" value="en" />

       <button>切換爲英文</button>

    </form>

這裏就是兩個表單,切換語言,那麼/changeSessionLanauage怎麼編寫呢,看以下代碼:

@RequestMapping("/changeSessionLanauage")

    public String changeSessionLanauage(HttpServletRequest request,String lang){

       System.out.println(lang);

       if("zh".equals(lang)){

           //代碼中便可經過如下方法進行語言設置

           request.getSession().setAttribute(SessionLocaleResolver.LOCALE_SESSION_ATTRIBUTE_NAME, new Locale("zh", "CN")); 

       }elseif("en".equals(lang)){

           //代碼中便可經過如下方法進行語言設置

           request.getSession().setAttribute(SessionLocaleResolver.LOCALE_SESSION_ATTRIBUTE_NAME, new Locale("en", "US")); 

       }

       return "redirect:/hello";

    }

這部分代碼最核心的部分就是如何設置會話的區域,也就是以下代碼:

request.getSession().setAttribute(SessionLocaleResolver.LOCALE_SESSION_ATTRIBUTE_NAME, new Locale("en", "US")); 

這個代碼就能夠把當前會話的區域進行切換了,是否是很簡單。以上代碼你會發現只針對會話的設置,咱們在這裏在優化下,針對下面講的Cookie也會做用到,這樣這個代碼就很智能了,代碼修改成以下:

@RequestMapping("/changeSessionLanauage")

    public String changeSessionLanauage(HttpServletRequest request,HttpServletResponse response,String lang){

              System.out.println(lang);

       LocaleResolver localeResolver = RequestContextUtils.getLocaleResolver(request);

       if("zh".equals(lang)){

           localeResolver.setLocale(request, response, new Locale("zh", "CN"));

       }elseif("en".equals(lang)){

           localeResolver.setLocale(request, response, new Locale("en", "US"));

       }

       return "redirect:/hello";

    }

在這裏使用:

LocaleResolver localeResolver = RequestContextUtils.getLocaleResolver(request);

獲取當前使用的區域解析器LocaleResolver 調用裏面的方法

setLocale 設置便可,這樣的代碼就是不論是會話仍是cookie區域解析器都是同樣的代碼了。

 

(11) Cookie區域解析器之CookieLocaleResolver

       Cookie區域解析器也就是說,你設置完針對cookie生效,session失效。那麼這個具體怎麼操做呢?咱們須要在咱們的啓動類App.java(按你的實際狀況進行修改)配置區域解析器爲CookieLocaleResolverSessionLocaleResolver部分請註釋掉),具體代碼以下:

@Bean

    public LocaleResolver localeResolver() {

       CookieLocaleResolver slr = new CookieLocaleResolver();

        //設置默認區域,

        slr.setDefaultLocale(Locale.CHINA);

        slr.setCookieMaxAge(3600);//設置cookie有效期.

        returnslr;

    }

 

其實到這裏咱們就完事了,你能夠經過setDefaultLocale()設置默認的語言,啓動就訪問http://127.0.0.1:8080/hello 進行查看,是否是已經實現國際化了。

       到這裏固然還不是很完美,還須要在進一步的優化了,那麼怎麼在頁面中進行切換呢?

這裏主要是用到了,這個部分咱們在(10)中已經進行配置了,因此到這裏已近是能夠進行使用了,點擊頁面中的按鈕進行體驗。

 

(12)固定的區域解析器之FixedLocaleResolver 

       一直使用固定的Local, 改變Local 是不支持的 。既然沒法改變,那麼不好了,仍是簡單介紹下如何使用吧,仍是在App.java進行編碼:

/**

     * cookie區域解析器;

     * @return

     */

    @Bean

    public LocaleResolver localeResolver() {

       FixedLocaleResolver slr = new FixedLocaleResolver ();

        //設置默認區域,

        slr.setDefaultLocale(Locale.US);

        returnslr;

    }

好了,這個就這麼簡單,沒有別的知識了。

 

(13)使用參數修改用戶的區域;

       除了顯式調用LocaleResolver.setLocale()來修改用戶的區域以外,還能夠將LocaleChangeInterceptor攔截器應用處處理程序映射中,它會發現當前HTTP請求中出現的特殊參數。其中的參數名稱能夠經過攔截器的paramName屬性進行自定義。若是這種參數出如今當前請求中,攔截器就會根據參數值來改變用戶的區域。

       只須要在App.java中加入:

    @Bean

     public LocaleChangeInterceptor localeChangeInterceptor() {

            LocaleChangeInterceptor lci = new LocaleChangeInterceptor();

            // 設置請求地址的參數,默認爲:locale

//          lci.setParamName(LocaleChangeInterceptor.DEFAULT_PARAM_NAME);

            returnlci;

    }

   

    @Override

   public void addInterceptors(InterceptorRegistry registry) {

       registry.addInterceptor(localeChangeInterceptor());

   }

注意這個是能夠和會話區域解析器以及Cookie區域解析器一塊兒使用的,可是不能和FixedLocaleResolver一塊兒使用,不然會拋出異常信息。

 

好了,國際化就到此爲主了,博主也是累了,這部分知識在國內還真沒有,博主也是各類收集資料才總結出了這麼一篇文章,絕對原創,你們都都點贊評論。

Spring Boot 系列博客】

54. spring boot日誌升級篇—logback【從零開始學Spring Boot

 

52. spring boot日誌升級篇—log4j多環境不一樣日誌級別的控制【從零開始學Spring Boot 

 

51. spring boot屬性文件之多環境配置【從零開始學Spring Boot

 

50. Spring Boot日誌升級篇—log4j【從零開始學Spring Boot

 

49. spring boot日誌升級篇理論【從零開始學Spring Boot

 

48. spring boot單元測試restfull API【從零開始學Spring Boot

 

47. Spring Boot發送郵件【從零開始學Spring Boot

 

46. Spring Boot中使用AOP統一處理Web請求日誌

 

45. Spring Boot MyBatis鏈接Mysql數據庫【從零開始學Spring Boot

 

44. Spring Boot日誌記錄SLF4J【從零開始學Spring Boot

 

43. Spring Boot動態數據源(多數據源自動切換)【從零開始學Spring Boot

 

42. Spring Boot多數據源【從零開始學Spring Boot

 

41. Spring Boot 使用Java代碼建立Bean並註冊到Spring中【從零開始學Spring Boot

 

40. springboot + devtools(熱部署)【從零開始學Spring Boot 

 

39.4 Spring Boot Shiro權限管理【從零開始學Spring Boot

 

39.3 Spring Boot Shiro權限管理【從零開始學Spring Boot

 

39.2. Spring Boot Shiro權限管理【從零開始學Spring Boot

 

39.1 Spring Boot Shiro權限管理【從零開始學Spring Boot

 

38 Spring Boot分佈式Session狀態保存Redis【從零開始學Spring Boot 

 

37 Spring Boot集成EHCache實現緩存機制【從零開始學Spring Boot 

 

36 Spring Boot Cache理論篇【從零開始學Spring Boot

 

35 Spring Boot集成Redis實現緩存機制【從零開始學Spring Boot 

 

34Spring Boot的啓動器Starter詳解【從零開始學Spring Boot

 

33 Spring Boot 監控和管理生產環境【從零開始學Spring Boot

 

32 Spring Boot使用@SpringBootApplication註解從零開始學Spring Boot 

 

31 Spring Boot導入XML配置【從零開始學Spring Boot

相關文章
相關標籤/搜索