基于springboot i18n國際化后臺多種語言設置的方式
之前有做過手機端后臺的國際化,因為手機統(tǒng)一傳遞了language參數(shù)
所以只要設置LocaleChangeInterceptor就行了
/**
* 配置國際化語言
*/
@Configuration
public class LocaleConfig extends WebMvcConfigurerAdapter{
/**
* 默認解析器 其中l(wèi)ocale表示默認語言
*/
@Bean
public LocaleResolver localeResolver() {
SessionLocaleResolver localeResolver = new SessionLocaleResolver();
localeResolver.setDefaultLocale(Locale.CHINA);
return localeResolver;
}
//springboot1.5
@Override
public void addInterceptors(InterceptorRegistry registry) {
LocaleChangeInterceptor localeInterceptor = new LocaleChangeInterceptor();
localeInterceptor.setParamName("language");
registry.addInterceptor(localeInterceptor);
}
}
對于某些特殊的后臺運行代碼,比如定時器,我則使用getByLanguage方法
/**
* 國際化工具類
*/
@Component
public class MessageUtils{
private static MessageSource messageSource;
static SysErrorLogDao sysErrorLogDao;
@Resource
public void setSysErrorLogDao(SysErrorLogDao sysErrorLogDao) {
MessageUtils.sysErrorLogDao = sysErrorLogDao;
}
private static Logger logger = LoggerFactory.getLogger(MessageUtils.class);
public MessageUtils(MessageSource messageSource) {
MessageUtils.messageSource = messageSource;
}
/**
* 獲取單個國際化翻譯值
* @param msgKey
* @param defaultMsg
* @return
*/
public static String get(String msgKey, String defaultMsg) {
try {
return messageSource.getMessage(msgKey, null, LocaleContextHolder.getLocale());
} catch (Exception e) {
logger.error(e.getMessage(), e);
String message = StringUtils.getExceptionStackTraceMessage(e);
if(message != null && message.length() > 1000) {
message = message.substring(0, 999);
}
SysErrorLogModel errorLog = new SysErrorLogModel();
errorLog.setContent(msgKey);
errorLog.setType("messageUtils");
errorLog.setCreateDate(new Date());
errorLog.setClassName(MessageUtils.class.getName());
errorLog.setMessage(message);
sysErrorLogDao.save(errorLog);
return defaultMsg;
}
}
/**
* 獲取多個參數(shù)取代的國際化翻譯值
* @param msgKey
* @param defaultMsg
* @param arg
* @return
*/
public static String get(String msgKey, String defaultMsg, Object... arg) {
try {
msgKey = messageSource.getMessage(msgKey, arg, LocaleContextHolder.getLocale());
return msgKey;
} catch (Exception e) {
logger.error(e.getMessage(), e);
String message = StringUtils.getExceptionStackTraceMessage(e);
if(message != null && message.length() > 1000) {
message = message.substring(0, 999);
}
SysErrorLogModel errorLog = new SysErrorLogModel();
errorLog.setContent(msgKey);
errorLog.setType("messageUtils");
errorLog.setCreateDate(new Date());
errorLog.setClassName(MessageUtils.class.getName());
errorLog.setMessage(message);
sysErrorLogDao.save(errorLog);
return MessageFormat.format(defaultMsg, arg);
}
}
/**
* 指定語言獲得單個國際化翻譯值
* @param msgKey
* @param defaultMsg
* @param language
* @return
*/
public static String getByLanguage(String msgKey, String defaultMsg, String language) {
try {
Locale locale = new Locale(language);
msgKey = messageSource.getMessage(msgKey, null, locale);
return msgKey;
} catch (Exception e) {
logger.error(e.getMessage(), e);
String message = StringUtils.getExceptionStackTraceMessage(e);
if(message != null && message.length() > 1000) {
message = message.substring(0, 999);
}
SysErrorLogModel errorLog = new SysErrorLogModel();
errorLog.setContent(msgKey);
errorLog.setType("messageUtils");
errorLog.setCreateDate(new Date());
errorLog.setClassName(MessageUtils.class.getName());
errorLog.setMessage(message);
sysErrorLogDao.save(errorLog);
return defaultMsg;
}
}
/**
* 指定語言獲取多參數(shù)取代的國際化翻譯值
* @param msgKey
* @param defaultMsg
* @param language
* @param arg
* @return
*/
public static String getByLanguage(String msgKey, String defaultMsg, String language, Object... arg) {
try {
Locale locale = new Locale(language);
msgKey = messageSource.getMessage(msgKey, arg, locale);
return msgKey;
} catch (Exception e) {
logger.error(e.getMessage(), e);
String message = StringUtils.getExceptionStackTraceMessage(e);
if(message != null && message.length() > 1000) {
message = message.substring(0, 999);
}
SysErrorLogModel errorLog = new SysErrorLogModel();
errorLog.setContent(msgKey);
errorLog.setType("messageUtils");
errorLog.setCreateDate(new Date());
errorLog.setClassName(MessageUtils.class.getName());
errorLog.setMessage(message);
sysErrorLogDao.save(errorLog);
return MessageFormat.format(defaultMsg, arg);
}
}
}
但是后面又要做網(wǎng)頁的國際化,因為網(wǎng)頁沒有傳遞統(tǒng)一的語言參數(shù),如果要一一添加的話太過麻煩,于是就要用到cookie來保存?zhèn)鬟f語言
這個時候就要實現(xiàn)自己的解析器了
public class MyLocaleResolver implements LocaleResolver {
@Override
public Locale resolveLocale(HttpServletRequest httpServletRequest) {
Locale locale = Locale.getDefault();
{
//通過參數(shù)解析locale,language參數(shù)優(yōu)先
String temp = httpServletRequest.getParameter("language");
if (!StringUtils.isEmpty(temp)) {
locale = new Locale(temp);
return locale;
}
}
//得到cookie,解析locale
Cookie[] cookies = httpServletRequest.getCookies();
if(cookies != null) {
for (Cookie cookie : cookies) {
if (cookie.getName().equals("userLanguage")) {
String temp = cookie.getValue();
if (!StringUtils.isEmpty(temp)) {
locale = new Locale(temp);
}
continue;
}
}
}
return locale;
}
@Override
public void setLocale(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Locale locale) {
}
}
@Configuration
public class LocaleConfig extends WebMvcConfigurerAdapter{
@Bean
public LocaleResolver localeResolver() {
MyLocaleResolver localeResolver = new MyLocaleResolver();
return localeResolver;
}
}
這樣就實現(xiàn)了使用cookie來設置語言
不過最后還是有所遺漏,因為我們的分布式項目中用到了很多http的內(nèi)部調(diào)用,用不上cookie,也沒有l(wèi)anguage參數(shù)。
但是大部分的內(nèi)部調(diào)用都有傳遞公司id,可以通過公司獲得公司對應的語言。
可以在攔截器里面直接加入對companyId的解析但是我考慮有沒有通用的實現(xiàn)方法,就是在任何地方,甚至的運行到一半中途設置語言的辦法。
初步想法是拿到線程中的Locale進行設置
然后我看了下源碼LocaleContextHolder.getLocale()

發(fā)現(xiàn)調(diào)用的是一個LocaleContext類的方法。
然后查詢哪些地方調(diào)用了LocaleResolver.resolveLocale


發(fā)現(xiàn)第一個方法里面返回了一個匿名函數(shù)LocaleContext,其getLocale就是直接調(diào)用localeResolver.resolveLocale方法。
于是我合理的猜想框架里不是通過攔截器設置一個locale,而是每次調(diào)用LocaleContextHolder.getLocale()都會執(zhí)行l(wèi)ocaleResolver.resolveLocale(request)方法,所以我們只要設置request屬性就行了
public class MyLocaleResolver implements LocaleResolver {
@Override
public Locale resolveLocale(HttpServletRequest httpServletRequest) {
//得到cookie,解析locale
Locale locale = Locale.getDefault();
{
//通過參數(shù)解析locale
String temp = httpServletRequest.getParameter("language");
if (!StringUtils.isEmpty(temp)) {
locale = new Locale(temp);
return locale;
}
}
{
String temp = (String) httpServletRequest.getAttribute("language");
if (!StringUtils.isEmpty(temp)) {
locale = new Locale(temp);
return locale;
}
}
Cookie[] cookies = httpServletRequest.getCookies();
if(cookies != null) {
for (Cookie cookie : cookies) {
if (cookie.getName().equals("userLanguage")) {
String temp = cookie.getValue();
if (!StringUtils.isEmpty(temp)) {
locale = new Locale(temp);
}
continue;
}
}
}
return locale;
}
@Override
public void setLocale(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Locale locale) {
}
}
@RequestMapping("/test")
public String test(HttpServletRequest request) {
String result = "";
request.setAttribute("language", "ch");
result += MessageUtils.get("test", "測試");
request.setAttribute("language", "en");
result += MessageUtils.get("test", "測試");
return result;
}
messages_ch.properties
test=測試
messages_en.properties
test=test

這樣我們就實現(xiàn)了在任何地點,甚至中途變換語言了
發(fā)現(xiàn)LocaleContextHolder.getLocale()在實體類中也可以調(diào)用。因此可以后臺保存json格式,在get方法中根據(jù)語言返回相應的值。
我本來想直接改造原來的字段,但是發(fā)現(xiàn)緩存會直接讀取get中的值,下次讀取就不是json了,所以只好麻煩點增加一個字段了
public String getFullNameByLanguage() {
String language = LocaleContextHolder.getLocale().getLanguage();
Map<String, String> map;
try {
map = JsonUtil.string2Obj(fullName);
return map.get(language);
} catch (IOException e) {
return fullName;
}
}
當使用@Async異步方法時,LocaleContext就是空的。這時候需要強制設置語言LocaleContextHolder.setLocale(Locale locale),當然一般的方法也可以用這個來設置語言,不過這樣的話就不會再調(diào)用localeResolver.resolveLocale(request)方法了
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關文章
Java 中的CharArrayReader 介紹_動力節(jié)點Java學院整理
CharArrayReader 是字符數(shù)組輸入流。它和ByteArrayInputStream類似,只不過ByteArrayInputStream是字節(jié)數(shù)組輸入流,而CharArray是字符數(shù)組輸入流。CharArrayReader 是用于讀取字符數(shù)組,它繼承于Reader2017-05-05
IDEA報java:?java.lang.OutOfMemoryError:?Java?heap?space錯誤
這篇文章主要給大家介紹了關于IDEA報java:?java.lang.OutOfMemoryError:?Java?heap?space錯誤的解決辦法,文中將解決的辦法介紹的非常詳細,需要的朋友可以參考下2024-01-01
intellij idea快速查看當前類中的所有方法(推薦)
這篇文章主要介紹了intellij idea快速查看當前類中的所有方法,本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-09-09
SpringCloud實現(xiàn)Redis在各個微服務的Session共享問題
Redis是運行在內(nèi)存中,查取速度很快。本文重點給大家介紹SpringCloud實現(xiàn)Redis在各個微服務的Session共享,感興趣的朋友一起看看吧2018-08-08

