参考
Spring Boot、SpringMVC进行i18n国际化支持:使用MessageSource
https://www.jianshu.com/p/a354d3f849ec
https://www.jianshu.com/p/69f5a19468db
ResourceBundle.getBundle实现国际化的方法:
https://blog.csdn.net/songzehao/article/details/84349599
另一种国际化实现方式;
https://www.cnblogs.com/nizuimeiabc1/p/13060287.html
国际化参数的国际化:
需要参数国际化的需求很少,集中在系统中定义过的名词上。
这个时候做一个参数检查与替换即可。
即系统中维护一个Map,检测参数是否在Map的key中,如果在就替换为value
为了动态增删,可以将map的初始化用配置文件完成
具体项目
需求:数据库信息展示时要实现国际化
关键核心类:
LocaleMessage.java(@Component注解)
关键对象:
@Autowired
private MessageSource commonMessageSource; // 指明国际化配置源1
@Autowired
private MessageSource operationMessageSource; // 指明国际化配置源2
关键方法:
public String getMessage(String code, Object[] args, String defaultMessage, Locale locale) {
return messageSource.getMessage(code, args, defaultMessage, locale);
}
messageSource通过Spring托管如下代码
@Configuration
public class AppConfig implements WebMvcConfigurer{
@Bean
public MessageSource messageSource() {
ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
// 指明了国际化文件配置位置
messageSource.setBasename("classpath:i18n/messages");
// 也可以指明多个配置路径
// 多个国际化资源文件彼此冲突的情况,以注入顺序为主:
// messageSource.setBasenames("classpath:i18n/messages", "classpath:i18n/OperationMessages", "classpath:i18n/OperationName");
// 先索引OperationMessages的内容,查找到立即返回结果,后面的文件相当于不起作用
messageSource.setDefaultEncoding("UTF-8");
return messageSource;
}
//两个同类型的指明信息source的bean不会互相冲突
@Bean
public MessageSource operationMessageSource() {
ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
messageSource.setBasename("classpath:i18n/OPmessages");
messageSource.setDefaultEncoding("UTF-8");
return messageSource;
}
}
国际化信息转化:
通过拦截器LogInterceptor.java向ThreadContext注入变量,获取国际化等地域信息:
@Override
public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object arg)
throws Exception {
String clientIp = HttpUtil.getClientIp(httpServletRequest);
// 在log4j2的类似于ThreadLocal的类中注明当前线程的上下文信息,这里注入了IP、用户名等
ThreadContext.put(CLIENT_IP, clientIp);
ThreadContext.put(USER_NAME, userName);
// 从http请求中拿到国家语言等信息,用于国际化前置处理
Locale locale = HttpUtil.getLocale(httpServletRequest);
String country = locale.getCountry();
String language = locale.getLanguage();
String variant = locale.getVariant();
ThreadContext.put(LOCALE_LANGUAGE, language);
ThreadContext.put(LOCALE_COUNTRY, country);
ThreadContext.put(LOCALE_VARIANT, variant);
Locale tmp = new Locale(language, country, variant);
String localeStr = HttpUtil.getLocale(httpServletRequest).toString();
return true;
}
在需要转化的地方直接调取ThreadContext(各个线程持有自己的注入变量,不必担心高并发):
public String buildDetail(String code, String... parameters) {
String a = ThreadContext.get(HpcLogInterceptor.LOCALE_LANGUAGE);
String b = ThreadContext.get(HpcLogInterceptor.LOCALE_COUNTRY);
String c = ThreadContext.get(HpcLogInterceptor.LOCALE_VARIANT);
Locale locale = new Locale(ThreadContext.get(LogInterceptor.LOCALE_LANGUAGE),
ThreadContext.get(LogInterceptor.LOCALE_COUNTRY), ThreadContext.get(LogInterceptor.LOCALE_VARIANT));
String detail = localeMessage.getOPMessage(code, parameters, DEFAULT_MESSAGE, locale);
return detail;
}
最后通过LocalMessage类完成国际化信息的转化