0%

Spring Boot国际化(i18n)

一、介绍

i18n是internationalization(国际化单词的缩写,i和n之间有18个字母)

二、依赖

1
2
3
4
5
<!-- 只需要导入web包 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>

三、语言配置文件

创建配置文件存放不同语言的消息文本:

message.properties(此默认配置是必须的,兜底的配置):

1
2
3
test=默认
abc=默认abc
arg=默认第{0}个参数

message_en_US.properties(英文配置):

1
2
test=test
arg=test{0}

message_zh_CN.properties(中文配置):

1
2
test=中文
arg=第{0}个参数

当指定的语言文件中找不到对应的key时,会查询默认文件,如abc找到默认abc;默认文件也不存在时,会报org.springframework.context.NoSuchMessageException: No message found under code 'a' for locale ''.这里的a就是操作的key

四、yml配置

1
2
3
4
5
6
spring:
application:
name: test-i18n
messages:
basename: static/i18n/message #语言配置文件的基础名称(注意,message为语言配置文件的前缀)
encoding: UTF-8

五、session默认解析器(指定默认的locale)

1
2
3
4
5
6
7
8
9
10
11
12
13
@Configuration
public class LocaleConfig {
/**
* 默认解析器 其中locale表示默认语言,当请求中未包含语种信息,则设置默认语种
* 当前默认为CHINA,zh_CN
*/
@Bean
public SessionLocaleResolver localeResolver() {
SessionLocaleResolver localeResolver = new SessionLocaleResolver();
localeResolver.setDefaultLocale(Locale.CHINA);
return localeResolver;
}
}

六、拦截器(设置客户端语言locale)

1
2
3
4
5
6
7
8
9
10
11
public class MyInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
String lang = request.getHeader("lang");
//拦截客户端传送的语言标识,获取对应的语言locale,没有传送则走默认
if(StringUtils.hasText(lang)){
LocaleContextHolder.setLocale(new Locale(lang));
}
return true;
}
}

七、注册拦截器

1
2
3
4
5
6
7
8
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new MyInterceptor())
.addPathPatterns("/**");
}
}

八、控制器

1
2
3
4
5
6
7
8
9
10
11
@RestController
public class I18nController {
@Autowired
private MessageSource messageSource;

@GetMapping("/in")
public String getMessage(String param){
//第一个参数是语言配置的key、第二个参数是对象数组,对应语言包中的变量如{0}进行填充、第三个参数是语言区域对象
return messageSource.getMessage(param,null, LocaleContextHolder.getLocale());
}
}

九、工具类

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
public class LocaleMessageUtils {

/**
* 根据key获取国际语言配置文件中对应的值
* @param key 语言配置文件中的key值
*/
public static String getMessage(String key) {
MessageSource messageSource = SpringContextHolder.getBean("messageSource");
return messageSource.getMessage(key, null, LocaleContextHolder.getLocale());
}

/**
* 根据key和指定的区域语言获取国际语言配置文件中对应的值
* @param key 语言配置文件中的key值
* @param locale 区域语言对象
*/
public static String getMessage(String key, Locale locale) {
MessageSource messageSource = SpringContextHolder.getBean("messageSource");
return messageSource.getMessage(key, null, locale);
}


/**
* 根据key获取国际语言配置文件中对应的值,并填充参数
* @param key 语言配置文件中的key值
* @param args values值中对应的填充参数
*/
public static String getMessage(String key, Object[] args) {
MessageSource messageSource = SpringContextHolder.getBean("messageSource");
return messageSource.getMessage(key, args, LocaleContextHolder.getLocale());
}

/**
* 根据key和指定的区域语言获取国际语言配置文件中对应的值,并填充参数
* @param key 语言配置文件中的key值
* @param locale 区域语言对象
* @param args values值中对应的填充参数
*/
public static String getMessage(String key, Object[] args, Locale locale) {
MessageSource messageSource = SpringContextHolder.getBean("messageSource");
return messageSource.getMessage(key, args, locale);
}

/**
* 获取当前区域上下文对应的语言
* @return 当前环境语言
*/
public static String getLanguage(){
return LocaleContextHolder.getLocale().getLanguage();
}
}

十、总结

通过拦截器截取客户端放入head中的语言标识,生成对应的locale放入LocaleContextHolder中,线程走对应方法操作时,通过LocaleContextHolder.getLocale()可以获取其对应的语言区域,再从对应的语言配置文件获取文本。