FMT Tag何用
如果我们要编写国际化的程序,就涉及很多本地化的场景,使用不同的语言,使用不同的时间、金钱等表述习惯。J2EE提供了i18n来实现国际化的框架,在这个框架下,我们可以为不同的地区进行本地化的设置(即L10n)。
其核心是:为不同的地区设置不同的资源文件,当不同地区的用户使用时,根据资源文件,显示不同的内容。 JSLT提供了fmt tag( Internationalization and Formatting library,缩写为fmt)来支持国际化和本地化。
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
资源文件
在J2EE种,这些资源文件是*.properities,称为bundle,文件名后缀表示不同的语言和不同的地区,例如:
mybundle_en.properties //英语
mybundle_zh.properties //中文
mybundle_en_US.properties //美国英语
其中语言的缩写可以在 http://www.loc.gov/standards/iso639-2/php/code_list.php 中查到,而地区代码可以在 http://www.iso.org/iso/home/standards/country_codes/iso-3166-1_decoding_table.htm 中查到。如果同时提供语言和地区,语言放在前面。例如AddressBook-messages_zh_CN.properties,如果文件不存在,则查找AddressBook-messages_zh.properties,如果还不存在,则使用AddressBook-messages.properties。
这些properties文件位于resource/下
testfmt_en.properities的内容
cn.wei.flowingflying.hello = Hello,World
store.greeting = There are {0} products in the store
cn.wei.flowingflying.books = There are {0} books and {1} pens.
testfmt_zh.properities的内容
cn.wei.flowingflying.hello = \u60A8\u597D //中文的您好,Eclipse自动翻译了。
store.greeting = \u5546\u5E97\u91CC\u6709{0}\u4EF6\u5546\u54C1\u3002 //商店里有{0}件商品。
cn.wei.flowingflying.books = \u6709{0}\u672C\u4E66\u548C{1}\u652F\u7B14 //有{0}本书和{1}支笔
确定使用的bundle文件
这些bundle文件根据我们的需要可以有多个,加以不同的语言和/或地区的后缀,如何定位使用的bundle文件?
配置全局的缺省的bundle文件
缺省的bundle文件可以在web.xml中进行定义:
<web-app ....>
<context-param>
<param-name>javax.servlet.jsp.jstl.fmt.localizationContext</param-name>
<param-value>testfmt</param-value>
</context-param>
......
<web-app>
在jsp中指定:fmt:bundle和fmt:setBundle
我们也可以在jsp文件中指定
<fmt:bundle basename="testfmt">
... 这里面将使用testfmt bundle ...
</fmt:bundle>
还可以将bundle的名字存放在参数中,在设置bundle的basename中使用。
<fmt:setBundle basename="testfmt" var="test" />
<fmt:bundle basename="${test}">
... 这里面将使用fmt:setBundle中定义在test参数的bundle ...
</fmt:bundle>
bundle作为fmt:message,也可以在调用时具体指定:
<fmt:message key="cn.wei.flowingflying.hello" bundle="${test}"/>
使用bundle:fmt:message
前面bundle文件的例子,我们可以看到采用<key>=<value>的格式。fmt:message通过引用key,得到value。
无参数的fmt:message
<fmt:bundle basename="testfmt">
<fmt:message key="cn.wei.flowingflying.hello"/>
</fmt:bundle>
如果是中文环境,这里将显示testfmt_zh.properities中设置的“您好”,如果是英文环境,这里将显示testfmt_en.properities中设置的“Hello,World”。
带参数的fmt:message
在testfmt bundle中,store.greeting带有一个参数{0},cn.wei.flowingflying.books带两个参数{0},{1},这里{n}表示第n个参数,从0开始编号。不同语言顺序可能不一样,有时会{1}放在前面,{0}放在后面
<fmt:message key="store.greeting" >
<fmt:param value="${numberOfProducts}" /> //numberOfProducts作为EL参数从servlet中传递过来
</fmt:message>
如果numberOfProducts=34,在中文环境中显示“商店里有34件商品。”,在英文环境中显示“There are 34 products in the store”
<fmt:message key="cn.wei.flowingflying.books">
<fmt:param value="${books}" /> //定义{0}参数的值
<fmt:param value="${pens}" /> //定义{1}参数的值
</fmt:message>
如果books=3,pens=4,在中文环境中显示:有3本书和4支笔,在英文环境中显示“There are 3 books and 4 pens.”
确定具体使用哪个后缀的资源:fmt:setLocale
一般而言,不需要特别的设置,用户的客户端,如浏览器会根据系统的设置在http请求中带有相关的信息(Accept-Languange)
我们也可以通过fmt:locale强行进行设定。
<fmt:setLocale value="en"/> //将在该语句后面有效,后续的将选择xxx_en.properities。
<fmt:setLocale value="en_US"/> //将在该语句后面有效,后续的将选择xxx_en_US.properities文件。
我们也可以在java code中进行设定,例如下面设定为en_US的后缀。
String language = request.getParameter("language");
if("english".equalsIgnoreCase(language)){
Config.set(request, Config.FMT_LOCALE, Locale.US);
}