Spring Boot 国际化

前言

在信息技术领域,国际化与本地化(英文:internationalization and localization)是指修改软件使之能适应目标市场的语言、地区差异以及技术需要。

国际化是指在设计软件,将软件与特定语言及地区脱钩的过程。当软件被移植到不同的语言及地区时,软件本身不用做内部工程上的改变或修正。本地化则是指当移植软件时,加上与特定区域设置有关的信息和翻译文件的过程。

国际化和本地化之间的区别虽然微妙,但却很重要。国际化意味着产品有适用于任何地方的“潜力”;本地化则是为了更适合于“特定”地方的使用,而另外增添的特色。用一项产品来说,国际化只需做一次,但本地化则要针对不同的区域各做一次。这两者之间是互补的,并且两者合起来才能让一个系统适用于各地。

基于他们的英文单字长度过长,常被分别简称成i18n(18意味着在“internationalization”这个单字中,i和n之间有18个字母)及L10n。使用大写的L以利区分i18n中的i和易于分辨小写l与1。

定义国际化配置文件

国际化配置文件

  • messages.properties(默认,当找不到语言的配置的时候,使用该文件语言进行展示)
  • messages_en.properties(英语)
  • messages_de.propertie(德语)
  • messages_fr.properties(法语)
  • messages_zh_TW.properties(中文-繁体)

将这些文件放到 classpath:resources/i18n 目录下即可,如图:
avatar

国际化配置文件内容

messages.properties

1
2
ERROR=unknown
SUCCESS=unknown

messages_en.properties

1
2
ERROR=error
SUCCESS=success

messages_de.properties

1
2
ERROR=Fehler
SUCCESS=Erfolg

messages_fr.properties

1
2
ERROR=Échec
SUCCESS=Le succès

messages_zh_TW.properties

1
2
ERROR=失敗(繁體)
SUCCESS=成功(繁體)

Spring Boot 配置

定义一个区域解析器,在应用程序上下文中注册一个 LocaleResolver 类型的区域解析器 Bean,Bean的名称设置为 localeResolver,这样 DispatcherServlet 才能自动侦测到它。

方法一

添加 I18nConfiguration 配置类,使用 Accept-Language Header 区域解析器
特点:配置简单,使用方便,推荐使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
/**
* 国际化配置
*
* @author Leaves
* @version 1.0.0
* @date 2018/8/6
*/
@Configuration
public class I18nConfiguration {

/**
* Accept-Language Header 区域解析器
*/
@Bean(value = "localeResolver")
public LocaleResolver acceptHeaderLocaleResolver() {
AcceptHeaderLocaleResolver acceptHeaderLocaleResolver = new AcceptHeaderLocaleResolver();
acceptHeaderLocaleResolver.setDefaultLocale(Locale.US);
return acceptHeaderLocaleResolver;
}

/**
* 加载国际化配置文件资源
*/
@Bean
public ReloadableResourceBundleMessageSource messageSource() {
ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
//设置国际化配置文件存放目录
messageSource.setBasename("classpath:i18n/messages");
//设置加载资源的缓存失效时间,-1表示永久有效,默认为-1
messageSource.setCacheSeconds(-1);
//设定 Resource Bundle 编码方式,默认为UTF-8
messageSource.setDefaultEncoding("UTF-8");
return messageSource;
}
}

方法二

使用 SessionLocaleResolver 或 CookieLocaleResolver

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
/**
* 国际化配置
*
* @author Leaves
* @version 1.0.0
* @date 2018/8/6
*/
@Configuration
public class I18nConfiguration extends WebMvcConfigurerAdapter {

/**
* Session 区域解析器
*/
@Bean(value = "localeResolver")
public LocaleResolver sessionLocaleResolver() {
SessionLocaleResolver sessionLocaleResolver = new SessionLocaleResolver();
sessionLocaleResolver.setDefaultLocale(Locale.US);
return sessionLocaleResolver;
}

/**
* 注册 LocaleChangeInterceptor 拦截器,并将其引用到任何需要支持多种语言的处理器映射
*/
private LocaleChangeInterceptor localeChangeInterceptor() {
LocaleChangeInterceptor localeChangeInterceptor = new LocaleChangeInterceptor();
localeChangeInterceptor.setParamName("locale");
return localeChangeInterceptor;
}

/**
* LocaleChangeInterceptor 拦截器注册
*/
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(localeChangeInterceptor());
}

/**
* 加载国际化配置文件资源
*/
@Bean
public ReloadableResourceBundleMessageSource messageSource() {
ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
//设置国际化配置文件存放目录
messageSource.setBasename("classpath:i18n/messages");
//设置加载资源的缓存失效时间,-1表示永久有效,默认为-1
messageSource.setCacheSeconds(-1);
//设定 Resource Bundle 编码方式,默认为UTF-8
messageSource.setDefaultEncoding("UTF-8");
return messageSource;
}
}

国际化使用

Spring Boot 通过以上两步就完成了国际化配置,那怎么使用呢?
首先定义一个测试接口

1
2
3
4
5
6
7
8
9
@Autowired
private MessageSource messageSource;

@RequestMapping(value = "/test", method = RequestMethod.GET)
public String languageTest(@RequestParam(value = "result", required = false) String result) {
Locale locale = LocaleContextHolder.getLocale();
logger.info(locale.toString());
return messageSource.getMessage(result == null ? "SUCCESS" : result, null, "unknown", locale);
}

LocaleContextHolder.getLocale() 是获取语言的关键方法,通过 MessageSource 的 String getMessage(String var1, Object[] var2, String var3, Locale var4) 接口获取国际化配置文件(messages_xx.properties)中的不同语言内容。

测试

接下来我将使用 Postman 工具来进行测试
设置语言的关键在于 HTTP Header 上加上 Accept-Language 参数

下面是两个国际化方法的几种语言测试结果:

方法一测试结果

avatar
avatar
avatar
avatar

方法二测试结果

avatar
avatar
avatar
avatar

到这里,Spring Boot 的国际化就完成了~~

区域解析器

AcceptHeaderLocaleResolver

Spring 采用的默认区域解析器是 AcceptHeaderLocaleResolver。它通过检验 HTTP 请求的 Accept-Language 头部来解析区域。这个头部是由用户的 Web 浏览器根据底层操作系统的区域设置进行设定或者 Web 端设定。

SessionLocaleResolver

Session 区域解析器,会从用户请求相关的 Session 中获取本地化信息。如果不存在,它会根据 Accept-Language 头部确定默认区域,只针对当前的会话有效,Session 失效,还原为默认状态。

CookieLocaleResolver

Cookie 区域解析器,检查客户端中的 Cookie 是否包含本地化信息,如果有的话就使用。当配置这个解析器的时候,可以指定 Cookie 名,以及 Cookie 的最长生存期。

FixedLocaleResolver

固定区域解析器,一直使用固定的 Local, 改变 Local 是不支持的,一旦程序启动时设定,则无法改变 Local。

通过 url 中的参数修改语言

除了显式调用 LocaleResolver.setLocale() 来修改用户的区域之外,还可以将 LocaleChangeInterceptor 拦截器应用到处理程序映射中(如方法二),它会发现当前 HTTP 请求中出现的特殊参数。其中的参数名称可以通过拦截器的 paramName (默认值 locale) 属性进行自定义。如果这种参数出现在当前请求中,拦截器就会根据参数值来改变区域。
注:LocaleChangeInterceptor 可以和 SessionLocaleResolver、CookieLocaleResolver 一起使用,但不能和FixedLocaleResolver 一起使用,否则会抛出异常信息。

If these articles are helpful to you, you can donate comment here.