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

相关文章
相关标签/搜索