关于JSTL里的资源文件绑定和Locale设置
jstl寻找合适的Locale的过程是:
- 看是否通过jsp标签<fmt:setLocale value="zh_CN" />或嵌套的<fmt:bundle设置了Locale,
- 找Config是否设置了javax.servlet.jsp.jstl.fmt.locale参数,
- 否则就由客户端浏览器的语言设置决定,
- 如果没有找到匹配的Locale那么寻找Config里的javax.servlet.jsp.jstl.fmt.fallbackLocale参数
JSTL的message标签,如<fmt:message key="403.title"/>,对Locale=zh能正常显示中文,而对于Locale=zh_CN却不能正常工作。
原因是jstl包里的类org.apache.taglibs.standard.tag.common.fmt.BundleSupport.java居然有BUG:
private static ResourceBundle findMatch(String basename, Locale pref) {
ResourceBundle match = null;
try {
ResourceBundle bundle =
ResourceBundle.getBundle(basename, pref,
Thread.currentThread().getContextClassLoader());//执行了这个方法后,下面的bundle.getLocale()方法只要pref参数是zh_CN的将会丢失language和country属性,导致之后的判断失误。
Locale avail = bundle.getLocale();
if (pref.equals(avail)) {
// Exact match
match = bundle;
} else {
if (pref.getLanguage().equals(avail.getLanguage())
&& ("".equals(avail.getCountry()) || pref.getCountry().equals(avail.getCountry()))) {
match = bundle;
}
}
match = bundle;
} catch (MissingResourceException mre) {
}
return match;
}
所以使用jstl要使你的Java应用支持包括zh_CN在内的国际化,应该修改jstl源代码BundleSupport.java,重写方法:
private static ResourceBundle findMatch(String basename, Locale pref) {
ResourceBundle match = null;
try {
ResourceBundle bundle =
ResourceBundle.getBundle(basename, pref,
Thread.currentThread().getContextClassLoader());
match=bundle;
return match;
}
- 在jsp里绑定特定的资源文件,classpath下有ApplicationResources_zh_CN.properties:
<fmt:setLocale value="zh_CN" />
<fmt:setBundle basename="ApplicationResources" var="applicationBundle"/>
<title><fmt:message key="403.title"/></title>
<fmt:bundle basename="ApplicationResources">
<content tag="heading"><fmt:message key="403.title" bundle="${applicationBundle}" /></content><p>
<fmt:message key="403.message" bundle="${applicationBundle}">
<fmt:param><c:url value="/"/></fmt:param>
</fmt:message>
</p>
</fmt:bundle>
<fmt:bundle basename="labels">
Hello: <fmt:message key="hello" />
Goodbye: <fmt:message key="goodbye" />
</fmt:bundle>
- 在web.xml里绑定一个资源文件:
<context-param>
<param-name>javax.servlet.jsp.jstl.fmt.localizationContext</param-name>
<param-value>ApplicationResources</param-value>
</context-param><context-param>
<param-name>javax.servlet.jsp.jstl.fmt.fallbackLocale</param-name>
<param-value>zh_CN</param-value>
</context-param>
<context-param>
<param-name>
javax.servlet.jsp.jstl.fmt.locale
</param-name>
<param-value>
zh_CN
</param-value>
</context-param>
- 设置缺省的Locale:
There are two ways to change the default locale. The first is to set it on the command line:
> java -Duser.language=2-char-language-code -Duser.region=2-char-country-code MyApp // Set only language code > java -Duser.language=fr -Duser.region= MyApp // Set language and country code > java -Duser.language=fr -Duser.region=CA MyAppThe second way to change the default locale is to call
Locale.setDefault()
:// Get default locale Locale locale = Locale.getDefault(); // Set the default locale to pre-defined locale Locale.setDefault(Locale.FRENCH); // Set the default locale to custom locale locale = new Locale("fr", "CA"); Locale.setDefault(locale);