什么是 I18N
- I18N 是 "国际化" 的简称,对于程序来说,在不修改内部代码的情况下,根据不同语言及地区显示相应的界面
Spring Boot 结合 I18N
1. Spring Boot 加入 Thymeleaf
引入 Thymeleaf 依赖库
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
创建模板文件 resources/templates/hello.html
<!DOCTYPE html>
<html lang="en">
<head>
<title>Title</title>
</head>
<body>
<p>欢迎你登录到阿里巴巴网站</p>
</body>
</html>
编写Controller
@Controller
public class HelloController {
@RequestMapping("/hello")
public String hello(){
return "/hello";
}
}
2. 页面元素国际化
- 需求:当访问语言为 zh 时显示中文,当语言为 en 时显示英文
- SpringBoot 默认支持国际画的,只需在 resources/ 下定义国际化配置文件即可,名称必须以 messages 开发
定义国际化文件
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
messages_en_US.properties(英文)
welcome= welcome to login to alibabawebsite(English)
修改模板
<body>
<p><labelth:text="#{welcome}"></label></p>
</body>
测试:访问 http://127.0.0.1:8080/hello 则会显示 欢迎你登录到 阿里巴巴 网站(中文)
3. 默认国际化原理
- 文件命名必须以 messages 开头,这是因为 MessageSourceAutoConfiguration 类中指定了前缀
- SpringMVC 会识别用户的首选地区,根据这个地区显示内容,用户区域通过区域解析器识别,它必须显示 LocaleResolver 接口,默认采用的区域解析器是 AcceptHeaderLocaleResolver,它是验证 HTTP 请求头的头部信息 accept-language 来解析区域,这个头部由用户浏览器底层根据系统的区域进行设定
4. 修改默认 messages 配置前缀
可在 resources 下创建新目录 i18n ,将 messages_xxx.properties 文件到此目录下
#指定message的basename,多个以逗号分隔,如果不加包名的话,默认从classpath路径开始,默认: messages
spring.messages.basename=i18n/messages
#设定加载的资源文件缓存失效时间,-1的话为永不过期,默认为-1
spring.messages.cache-seconds= 3600
5. 代码中使用国际化信息
注入 MessageSource 对象,通过 getMessage 方法获取信息
@RestController
public class HelloController {
@Autowired
private MessageSource messageSource;
@RequestMapping("/hello")
public String hello(){
Locale locale = LocaleContextHolder.getLocale(); //获取区域信息
String welcome = messageSource.getMessage("welcome",null,locale);
return welcome;
}
}
6. 国际化工具类
封装一个国际化工具类优化使用
@Component
public class LocaleMessage {
@Autowired
private MessageSource messageSource;
/**
* @param code:对应文本配置的key.
* @return 对应地区的语言消息字符串
*/
public String getMessage(String code){
return this.getMessage(code,new Object[]{});
}
public String getMessage(String code,String defaultMessage){
return this.getMessage(code,null,defaultMessage);
}
public String getMessage(String code,String defaultMessage,Locale locale){
return this.getMessage(code,null,defaultMessage,locale);
}
public String getMessage(String code,Locale locale){
return this.getMessage(code,null,"",locale);
}
public String getMessage(String code,Object[] args){
return this.getMessage(code,args,"");
}
public String getMessage(String code,Object[] args,Locale locale){
return this.getMessage(code,args,"",locale);
}
public String getMessage(String code,Object[] args,String defaultMessage){
Locale locale = LocaleContextHolder.getLocale();
return this.getMessage(code,args, defaultMessage,locale);
}
public String getMessage(String code,Object[]args,String defaultMessage,Locale locale){
return messageSource.getMessage(code,args, defaultMessage,locale);
}
}
使用方法
@Resource
private LocaleMessageSourceService localeMessageSourceService;
String msg3 = localeMessageSourceService.getMessage("welcome");
7. 会话区域解析器 SessionLocaleResolver
注入 Bean,会话区域解析器只针对当前会话有效
@Bean
public LocaleResolver localeResolver() {
SessionLocaleResolver slr = new SessionLocaleResolver();
//设置默认区域,
slr.setDefaultLocale(Locale.ENGLISH);
return slr;
}
修改模板,可切换中英文
<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>
添加相应控制器
@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"));
}else if("en".equals(lang)){
//代码中即可通过以下方法进行语言设置
request.getSession().setAttribute(SessionLocaleResolver.LOCALE_SESSION_ATTRIBUTE_NAME,new Locale("en","US"));
}
return"redirect:/hello2";
}
- 下面代码会切换当前会话区域
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"));
}else if("en".equals(lang)){
localeResolver.setLocale(request, response, new Locale("en","US"));
}
return"redirect:/hello";
}
8. 通过参数修改用户区域
@Configuration
public class MvcConfig extends WebMvcConfigurerAdapter {
@Bean
public LocaleResolver localeResolver() {
SessionLocaleResolver slr = new SessionLocaleResolver();
// 默认语言
slr.setDefaultLocale(Locale.US);
return slr;
}
@Bean
public LocaleChangeInterceptor localeChangeInterceptor() {
LocaleChangeInterceptor lci = new LocaleChangeInterceptor();
// 参数名
lci.setParamName("lang");
return lci;
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(localeChangeInterceptor());
}
}