国际化
写在前面:你被哪些傻逼bug困扰过?
前面有一篇博客中,写有我实现国际化,但失败的问题,原因是读取不到需要的国际化配置文件
今天机缘巧合之下解决了。解决方法是:将浏览器默认添加的语言删掉,手动添加
若使用默认的第四个英语来,读取不到配置文件,因为程序获取的locale信息是en,而不是你配置的en_US,
使用美国的那个英语获取的locale信息才会是en_US
为什么会发现这样子,是因为复习到国际化的时候,写了一个controller
@Autowired
private MessageSource messageSource;
@RequestMapping("/locales")
public String getLocale(Locale locale) {
--
如果使用浏览器本身带的那个英语,得到的是en。
--
System.out.println(locale);
String wel = messageSource.getMessage("welcomeinfo",null,locale);
System.out.println(wel);
return "locale";
}
国际化的实现方式
1、根据浏览器语言设置的情况对文本, 时间, 数值进行本地化处理
使用 JSTL 的 fmt 标签
在 bean 中注入 ResourceBundleMessageSource 的实例, 使用其对应的getMessage 方法
可以在 bean 中获取国际化资源文件 Locale 对应的消息
String wel = messageSource.getMessage("welcomeinfo",null,locale);
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h1>success</h1>
<fmt:message key="welcomeinfo"/>
</h1>
<form action="" method="post">
<fmt:message key="username"/>:<input /><br/>
<fmt:message key="password"/>:<input /><br/>
<input type="submit" value='<fmt:message key="loginBtn"/>'/>
</form>
</body>
控制层代码如上个controller代码所示
2、通过超链接切换 Locale
2.1自定义LocalResolver
MyLocaleResolver
public class MyLocaleResolver implements LocaleResolver {
@Override
public Locale resolveLocale(HttpServletRequest request) {
Locale l = null;
String locale = request.getParameter("locale");
if (locale != null && !"".equals(locale)) {
//带了,就用你带了的区域信息
l = new Locale(locale.split("_")[0], locale.split("_")[1]);
}else {
//没带,用默认的
l = request.getLocale();
}
return l;
}
@Override
public void setLocale(HttpServletRequest request, HttpServletResponse response, Locale locale) {
//不会写,就直接抄源码的实现
throw new UnsupportedOperationException(
"Cannot change HTTP accept header - use a different locale resolution strategy");
}
controller
@RequestMapping("/login")
public String indexlocale(Locale locale, HttpServletRequest request) {
System.out.println(locale);
String s = request.getParameter("locale");
System.out.println(s);
return "login";
}
jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<fmt:message key="welcomeinfo"/>
</h1>
<form action="" method="post">
<fmt:message key="username"/>:<input /><br/>
<fmt:message key="password"/>:<input /><br/>
<input type="submit" value='<fmt:message key="loginBtn"/>'/>
<!-- 切换语言 -->
</form>
<a href="/login?locale=zh_CN">中文</a> | <a href="login?locale=en_US">英语</a>
</body>
</html>
web.xml
<bean id="localeResolver" class="com.lly.LocaleReslover.MyLocaleResolver"></bean>
总结:其实就是替代了默认的AcceptHeaderLocaleResolver,根据你超链接携带的区域化信息新建一个Locale
2.2SessionLocaleResolver & LocaleChangeInterceptor
在以上代码的基础上,将自己写的自定义区域信息解析器注释掉,加入SessionLocaleResolver配合拦截器LocaleChangeInterceptor使用
<!-- <bean id="localeResolver" class="com.lly.LocaleReslover.MyLocaleResolver"></bean>-->
<bean id="localeResolver" class="org.springframework.web.servlet.i18n.SessionLocaleResolver"></bean>
<mvc:interceptors>
<bean class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor"></bean>
</mvc:interceptors>
LocaleChangeInterceptor原理–preHandle
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws ServletException {
--
//获取参数--locale的值
--
String newLocale = request.getParameter(getParamName());
if (newLocale != null) {
if (checkHttpMethod(request.getMethod())) {
--
//获取请求的区域信息解析器
--
LocaleResolver localeResolver = RequestContextUtils.getLocaleResolver(request);
if (localeResolver == null) {
throw new IllegalStateException(
"No LocaleResolver found: not in a DispatcherServlet request?");
}
try {
--
//将区域信息设置进解析器
--
localeResolver.setLocale(request, response, parseLocaleValue(newLocale));
}
catch (IllegalArgumentException ex) {
if (isIgnoreInvalidLocale()) {
logger.debug("Ignoring invalid locale value [" + newLocale + "]: " + ex.getMessage());
}
else {
throw ex;
}
}
}
}
// Proceed in any case.
return true;
}
ps:你也可以在方法内将locale的信息设置进session中,如此只需配SessionLocaleResolver就行
四种区域信息解析器
AcceptHeaderLocaleResolver:根据 HTTP 请求头的 Accept-Language 参数确定本地化类型,
如果没有显式定义本地化解析器, SpringMVC 使用该解析器。
CookieLocaleResolver:根据指定的 Cookie 值确定本地化类型
SessionLocaleResolver:根据 Session 中特定的属性确定本地化类型
LocaleChangeInterceptor:从请求参数中获取本次请求对应的本地化类型。