1. 默认国际化实现
1.1 添加多语言文件
spring boot 默认实现了国际化多语言配置,打开文件 org.springframework.boot.autoconfigure.context.MessageSourceAutoConfiguration 可以看到,默认的多语言文件放到目录 messages 中,可以通过配置 spring.messages.basename 修改多语言文件存放目录,修改默认配置:
spring: messages: basename: i18n.messages
新建多语言配置文件放到目录 resources/i18n 中:
messages.properties(默认的多语言文件) messages_zh_CN.properties(中文语言文件) messages_en_US.properties(英文语言文件)
messages.properties、messages_zh_CN.properties 中添加如下内容:
login.name=登录
messages_en_US.properties 中添加如下内容:
login.name=Login
1.2 添加控制器
package com.sviping.controller; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.MessageSource; import org.springframework.context.NoSuchMessageException; import org.springframework.context.i18n.LocaleContextHolder; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController public class TestController { @Autowired MessageSource messageSource; @RequestMapping("/test") public String test(){ String message = null; try { message = messageSource.getMessage("login.name", null, LocaleContextHolder.getLocale()); } catch (NoSuchMessageException e) { message = ""; System.out.println(e.getMessage()); } return message; } }
1.3 测试
浏览器中访问地址 localhost:8080/test 可以看到会返回 登录,修改浏览器的默认语言为英文后,刷新浏览器,会返回 Login,此时配置的默认国际会多语言完成。
2. 自定义国际化实现
上面 spring boot 默认的多语言不够灵活,不能方便的切换语言。通过查看类 org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver 可以发现,spring boot 是根据 header 中 Accept-Language 来切换不同的语言,并且该类型实现了接口 org.springframework.web.servlet.LocaleResolver,所以我们要自己实现多语言切换,也需要实现该接口。这里通过采用类似 AcceptHeaderLocaleResolver 要用不同 Accept-Language 来切换不同语言。
2.1 自定义拦截器
通过添加 url 参数来灵活的修改 Accept-Language ,spring boot 中类 org.springframework.web.servlet.i18n.LocaleChangeInterceptor 已经实现了此功能。该类会将接收到的参数放到 cookie 中, cookie 默认名字为 locale ,同时会添加名为 CookieLocaleResolver.class.getName() + ".LOCALE" 的 request 属性,值为 url 参数生成的 Locale 对象,所以我们只需求添加一个拦截器调用即可。
2.2 修改多语言默认实现
文件 org.springframework.boot.autoconfigure.web.servle.WebMvcAutoConfiguration 中方法 localeResolver 为默认多语言的默认实现方式
@Override @Bean @ConditionalOnMissingBean(name = DispatcherServlet.LOCALE_RESOLVER_BEAN_NAME) public LocaleResolver localeResolver() { if (this.webProperties.getLocaleResolver() == WebProperties.LocaleResolver.FIXED) { return new FixedLocaleResolver(this.webProperties.getLocale()); } AcceptHeaderLocaleResolver localeResolver = new AcceptHeaderLocaleResolver(); localeResolver.setDefaultLocale(this.webProperties.getLocale()); return localeResolver; }
通过注解 ConditionalOnMissingBean 可以发现,当 DispatcherServlet.LOCALE_RESOLVER_BEAN_NAME bean 不存在,即 localeResolver bean 不存在,该方法才生效,所以只需要添加 localeResolver bean 就可以自己实现多语言。为了能够实现不用每次都添加 url 参数,所以可以将 url 参数的值保存在 cookie 中,当没有 url 参数时,从 cookie 中取值即可,spring boot 已经通过类 org.springframework.web.servlet.i18n.CookieLocaleResolver 实现了此功能 ,并且该类实现了 org.springframework.web.servlet.LocaleResolver 接口,所以我们只需要添加 localeResolver bean 并实例化 CookieLocaleResolver 即可。 CookieLocaleResolver 通过下面两种方式获取 Locale 对象:
从 request 对象的 CookieLocaleResolver.class.getName() + ".LOCALE" 属性获取,此种方式对应有 url 参数的请求
从名为 locale(默认值) 的 cookie 中获取,此种方式对应没有 url 参数的请求
2.3 完整代码
新建类 MyMvcConfig 并实现接口 WebMvcConfigurer:
package com.sviping.config; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.LocaleResolver; import org.springframework.web.servlet.config.annotation.InterceptorRegistration; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import org.springframework.web.servlet.i18n.CookieLocaleResolver; import org.springframework.web.servlet.i18n.LocaleChangeInterceptor; @Configuration public class MyMvcConfig implements WebMvcConfigurer { @Bean public LocaleResolver localeResolver(){ CookieLocaleResolver cookieLocaleResolver = new CookieLocaleResolver(); cookieLocaleResolver.setCookieName("locale");//LocaleChangeInterceptor 默认会获取url参数 locale return cookieLocaleResolver; } @Override public void addInterceptors(InterceptorRegistry registry) { //多语言 registry.addInterceptor(new LocaleChangeInterceptor()).addPathPatterns("/**"); } }
2.4 测试
在浏览器中输入 localhost:8080/test?locale=en_US 后,即可切换成英文,去掉 locale 参数后,仍为英文,将参数的值改为 zh_CN 后,返回结果变为中文,到此,实现了多语言的自定义切换。