一、在SpringMVC中如何做国际化
①编写国际化配置文件(properties类型文件)
②使用ResourceBundleMessageSource管理国际化资源文件
③在页面中使用
二、在SpringBoot中如何做国际化
①编写国际化配置文件:在resources下建i18n文件夹,在i18n文件夹下建xxx_en_US.properties、xxx_zh_CN.properties等国际化配置文件
②SpringBoot已默认配置好了管理里国际化配置文件的组件ResourceBundleMessageSource
@Configuration
@ConditionalOnMissingBean(
value = {MessageSource.class},
search = SearchStrategy.CURRENT
)
@AutoConfigureOrder(-2147483648)
@Conditional({MessageSourceAutoConfiguration.ResourceBundleCondition.class})
@EnableConfigurationProperties
public class MessageSourceAutoConfiguration {
...
@Bean
public MessageSource messageSource() {
MessageSourceProperties properties = this.messageSourceProperties();
ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
if (StringUtils.hasText(properties.getBasename())) {
messageSource.setBasenames(StringUtils.commaDelimitedListToStringArray(StringUtils.trimAllWhitespace(properties.getBasename())));
}
if (properties.getEncoding() != null) {
messageSource.setDefaultEncoding(properties.getEncoding().name());
}
messageSource.setFallbackToSystemLocale(properties.isFallbackToSystemLocale());
Duration cacheDuration = properties.getCacheDuration();
if (cacheDuration != null) {
messageSource.setCacheMillis(cacheDuration.toMillis());
}
messageSource.setAlwaysUseMessageFormat(properties.isAlwaysUseMessageFormat());
messageSource.setUseCodeAsDefaultMessage(properties.isUseCodeAsDefaultMessage());
return messageSource;
}
...
}
在该段代码中有一个对象MessageSourceProperties,该对象的basename值为"messages":
public class MessageSourceProperties {
...
private String basename = "messages";
...
}
这也就是说如果我们的国际化配置文件直接放在类路径的根路径下且文件的基础名(去掉国家语言代码后的国际化文件名称,此时我们写的是login)为"messages"的话,那我们就不需要再做其他的任何配置,我们的国际化配置文件就会生效:
否则我们需要在SpringBoot的主配置文件中通过spring.messages的系列属性来映射MessageSourceProperties,比如其基础名basename,此时我们需要在application.properties中配置:
spring.messages.basename=i18n.login
③在页面上获取国际化配置:由于我们的页面不是jsp,我们无法通过导入fmt标签库来获取国际化配置,但我们可以使用thymeleaf的#{}来获取国际化配置
这里注意checkbox类型的input在取值时不可使用th:text,而是使用了行内表达式[[#{}]]
我们访问页面时可能会发现乱码,如下所示:
这是由于idea的编码所致,我们可以通过修改idea的默认编码为utf-8:
此时的效果:页面会根据浏览器的语言设置切换国际化配置
三、通过点击链接切换国际化
1、在超链接的请求参数上携带国际化信息:
lang='zh_CN')}">中文
lang='en_US')}">English
2、自定义国际化解析器:实现LocaleResolver接口,逻辑中如果请求参数中有"lang"参数则使用自定义的国际化解析器,否则使用SpringBoot默认的国际化解析器
public class MyLocaleResolver implements LocaleResolver {
@Override
public Locale resolveLocale(HttpServletRequest httpServletRequest) {
String lang = httpServletRequest.getParameter("lang");
//请求参数中没有lang时使用SpringBoot默认的Local对象
Locale locale = Locale.getDefault();
if(!StringUtils.isEmpty(lang)){
String[] split = lang.split("_");
locale = new Locale(split[0],split[1]);
}
return locale;
}
@Override
public void setLocale(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Locale locale) {
}
}
3、将自定义的国际化解析器纳入容器管理:在任意一个配置类中添加如下代码
@Bean
public LocaleResolver localeResolver(){
return new MyLocaleResolver();
}
此时只要请求链接中带有参数"lang"就会使用我们自定义的国际化解析器
原理:
SpringMVC在做国际化的时候其实是通过从HTTP请求的请求头中获取一个头信息,然后将其封装为Locale区域信息对象,再通过LocaleResolver解析器获取Locale对象来实现的国际化,SpringBoot在WebMvcAutoConfiguration自动配置中给容器中添加了国际化解析器组件,该组件上使用了@ConditionalOnMissingBean,表示如果我们没有自定义LocaleResolver则使用SpringBoot为我们提供的AcceptHeaderLocaleResolver,否则使用我们自定义的LocaleResolver:
@Bean
@ConditionalOnMissingBean
@ConditionalOnProperty(prefix = "spring.mvc",name = {"locale"})
public LocaleResolver localeResolver() {
if (this.mvcProperties.getLocaleResolver() == org.springframework.boot.autoconfigure.web.servlet.WebMvcProperties.LocaleResolver.FIXED) {
return new FixedLocaleResolver(this.mvcProperties.getLocale());
} else {
AcceptHeaderLocaleResolver localeResolver = new AcceptHeaderLocaleResolver();
localeResolver.setDefaultLocale(this.mvcProperties.getLocale());
return localeResolver;
}
}