8.4 國際化標籤
8.4.1 國際化標籤庫概述
爲了簡化WEB應用的國際化開發,JSTL中提供了一個用於實現國際化和格式化功能的標籤庫,我們將其簡稱爲國際化標籤庫,JSP規範爲國際化標籤庫建議的前綴名爲fmt。國際化標籤庫中包括了一組用於實現WEB國際化功能的標籤,這組標籤封裝了Java語言中java.util和java.text這兩個包中與國際化相關的API類的功能。國際化標籤庫中提供了綁定資源包和從資源包中的本地資源文件內讀取文本內容的標籤,也提供了對數值和日期等本地敏感的數據按本地化信息進行顯示和解析的標籤,還提供了按本地特定的時區來調整時間的標籤。
國際化標籤庫中的標籤可以根據客戶端瀏覽器的信息來自動確定本地信息,也可以由JSP頁面作者顯式地指定本地信息。如果沒有特別指定,本章案例假設默認的本地信息爲“中文(中國)”。
在舉例講解國際化標籤庫中的標籤時, 通常要使用到包含有多個資源文件的資源包,這個資源包中的各個資源文件分別對應幾個不同本地信息。這裏先創建好一組資源包文件。首先按例程8-25和例程8-26創建兩個名稱分別爲greetings.properties和temp.properties的資源文件。
例程8-25 greetings.properties
org.it315.heading=The first WEB application
org.it315.welcome=Welcome to www.it315.org !
org.it315.okKey=Today is {0,date,full}, you have {1,number,currency} dollars.
例程8-26 temp.properties
org.it315.heading=第一個WEB應用程序
org.it315.welcome=歡迎訪問www.it315.org網站!
org.it315.okKey=今天是{0,date,full},你有{1,number,currency}元。
接着使用JDK中提供的native2ascii程序將temp.properties文件中的中文字符轉換成其Unicode碼形式的轉義序列。在命令行窗口中進入temp.properties文件所在的目錄,執行如下命令:
native2ascii -encoding GB2312 temp.properties greetings_zh.properties
上面的命令執行後產生的greetings_zh.properties文件內容如例程8-27所示。
例程8-27 greetings_zh.properties
org.it315.heading=\u7b2c\u4e00\u4e2aWEB\u5e94\u7528\u7a0b\u5e8f
org.it315.welcome=\u6b22\u8fce\u8bbf\u95eewww.it315.org\u7f51\u7ad9!
org.it315.okKey=\u4eca\u5929\u662f{0,date,full}\uff0c\u4f60\u6709{1,number,
currency}\u5143\u3002
英文本地環境所對應的資源文件只需複製greetings.properties文件,並改名爲greetings_en.properties即可。最後將greetings.properties、greetings_en.properties和greetings_zh.properties這三個資源文件保存到<TOMCAT_HOME>\webapps\JSTL\WEB-INF\classes\org\it315\目錄中。
8.4.2 <fmt:setLocale>標籤
<fmt:setLocale>標籤用於在JSP頁面中顯式地設置用戶的本地化信息,並將設置的本地化信息以Locale對象的形式保存在某個Web域中,其在Web域中的屬性名稱爲“javax.servlet.jsp.jstl.fmt.locale”。使用<fmt:setLocale>標籤設置本地化信息後,國際化標籤庫中的其他標籤將使用該本地化信息,而忽略客戶端瀏覽器傳遞過來的本地信息。<fmt:setLocale>標籤的語法格式如下:
<fmt:setLocale value="locale"
[variant="variant"]
[scope="{page|request|session|application}"] />
<fmt:setLocale>標籤的屬性說明如表8.12所示。
表8.12 <fmt:setLocale>標籤的屬性
屬性名 |
是否支持EL |
屬性類型 |
屬 性 描 述 |
value |
true |
String或java.util.Locale |
指定用戶的本地化信息,可以是一個字符串或java.util.Locale實例對象。如果是字符串,則必須包含小寫形式的語言編碼,其後也可以帶有大寫形式的國家編碼,兩者中間用“-”或“_”連接 |
variant |
true |
String |
指定創建Locale實例對象時設置的變量部分,它用於標識開發商或特定瀏覽器爲實現擴展功能而自定義的信息 |
scope |
false |
String |
指定將構造出的Locale實例對象保存在哪個Web作用域中 |
如果<fmt:setLocale>標籤的value屬性值爲null,<fmt:setLocale>標籤將採用客戶端瀏覽器傳遞過來的本地信息。例程8-28是一個使用<fmt:setLocale>標籤的例子程序。
例程8-28 fmt_setLocale.jsp
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<%@ page contentType="text/html;charset=gb2312" %>
<fmt:setLocale value="${param.locale}" />
<fmt:setBundle basename="org.it315.greetings" var="greetings" />
<head>
<title><fmt:message bundle="${greetings}" key="org.it315.heading" /></title>
</head>
<jsp:useBean id="now" class="java.util.Date" />
<%
session.setAttribute("number", new Integer(8888888));
%>
<fmt:message bundle="${greetings}" key="org.it315.welcome" /><br />
<fmt:message bundle="${greetings}" key="org.it315.okKey">
<fmt:param value="${now}" />
<fmt:param value="${number}" />
</fmt:message>
例程8-28中的<fmt:setBundle>標籤用於根據<fmt:setLocale>標籤設置的本地化信息綁定一個資源包,其細節請參看8.4.3節;<fmt:message>標籤用於從一個資源包中讀取信息並進行格式化輸出,其細節請參看8.4.5節;<fmt:param>標籤用於爲格式化文本串中的佔位符設置參數值,其細節請參看8.4.6節。
在瀏覽器地址欄輸入如下地址訪問fmt_setLocale.jsp頁面:
http://localhost:8080/JSTL/fmt_setLocale.jsp?locale=en_US
例程8-28的運行結果如圖8.22所示。
圖8.22
將上面的訪問地址中的locale參數設置爲zh_CN後訪問fmt_setLocale.jsp頁面,例程8-28的運行結果如圖8.23所示。
圖8.23
8.4.3 <fmt:setBundle>標籤
<fmt:setBundle>標籤用於根據<fmt:setLocale>標籤設置的本地化信息創建一個資源包(ResourceBundle)實例對象,並將其綁定到一個Web域的屬性上。<fmt:setBundle>標籤的語法格式如下:
<fmt:setBundle basename="basename"
[var="varName"]
[scope="{page|request|session|application}"] />
<fmt:setBundle>標籤的屬性說明如表8.13所示。
表8.13 <fmt:setBundle>標籤的屬性
屬性名 |
是否支持EL |
屬性類型 |
屬 性 描 述 |
basename |
true |
String |
指定創建ResourceBundle實例對象的基名 |
var |
false |
String |
指定將創建出的ResourceBundle實例對象保存到Web域中的屬性名稱 |
scope |
false |
String |
指定將創建出的ResourceBundle實例對象保存在哪個Web作用域中 |
<fmt:setBundle>標籤有如下一些特性:
(1)如果basename屬性的值爲null或空字符串,或找不到basename屬性指定的資源,<fmt:setBundle>標籤保存到Web域中的屬性的值爲null。
(2)如果指定了var屬性,<fmt:setBundle>標籤將把ResourceBundle實例對象以var屬性的值作爲域屬性名稱保存到Web域中。
(3)如果沒有指定var屬性,<fmt:setBundle>標籤將把ResourceBundle實例對象以域屬性名javax.servlet.jsp.jstl.fmt.localizationContext保存到Web域中。所有沒有嵌套在<fmt:bundle>標籤中且未指定bundle屬性的<fmt:formatDate>都將使用該標籤創建的資源包。
在前面的例程8-28中已經使用了<fmt:setBundle>標籤,這裏就不再對<fmt:setBundle>標籤進行舉例講解了。
8.4.4 <fmt:bundle>標籤
<fmt:bundle>標籤與<fmt:setBundle>標籤的功能類似,但它創建的ResourceBundle實例對象只在其標籤體內有效。<fmt:bundle>標籤的語法格式如下:
<fmt:bundle basename="basename"
[prefix="prefix"]>
body content
</fmt:bundle>
<fmt:bundle>標籤的屬性說明如表8.14所示。
表8.14 <fmt:bundle>標籤的屬性
屬性名 |
是否支持EL |
屬性類型 |
屬 性 描 述 |
basename |
true |
String |
指定創建ResourceBundle實例對象的基名 |
prefix |
true |
String |
指定追加到嵌套在<fmt:bundle>標籤內的<fmt:message>標籤的key屬性值前面的前綴 |
如果設置了<fmt:bundle>標籤的prefix屬性,則其中嵌套的<fmt:message>標籤的key屬性值中就可以省略prefix屬性設置的前綴部分,這對要使用具有相同前綴的多個關鍵字的情況提供了一些簡便。
例程8-29是一個使用<fmt:bundle>標籤的例子程序,其中分別演示了設置和不設置prefix屬性的情況。
例程8-29 fmt_bundle.jsp
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<%@ page contentType="text/html;charset=gb2312" %>
沒有設置prefix屬性的情況:<br />
<fmt:bundle basename="org.it315.greetings">
<fmt:message key="org.it315.heading" /><br />
<fmt:message key="org.it315.welcome" /><br /><hr />
</fmt:bundle>
設置prefix屬性的情況:<br />
<fmt:bundle basename="org.it315.greetings" prefix="org.it315.">
<fmt:message key="heading" /><br />
<fmt:message key="welcome" />
</fmt:bundle>
例程8-29的運行結果如圖8.24所示。
圖8.24
8.4.5 <fmt:message>標籤
<fmt:message>標籤用於從一個資源包中讀取信息並進行格式化輸出,它有如下一些使用語法格式:
語法1,沒有標籤體的情況:
<fmt:message key="messageKey"
[bundle="resourceBundle"]
[var="varName"]
[scope="{page|request|session|application}"] />
語法2,在標籤體中指定格式化文本串中的佔位符參數的情況:
<fmt:message key="messageKey"
[bundle="resourceBundle"]
[var="varName"]
[scope="{page|request|session|application}"]>
<fmt:param>subtags
</fmt:message>
語法3,在標籤體中指定消息關鍵字和可選擇的佔位符參數:
<fmt:message [bundle="resourceBundle"]
[var="varName"]
[scope="{page|request|session|application}"]>
key
optional <fmt:param>subtags
</fmt:message>
<fmt:message>標籤的屬性說明如表8.15所示。
表8.15 <fmt:message>標籤的屬性
屬性名 |
是否支持EL |
屬性類型 |
屬 性 描 述 |
key |
true |
String |
指定要輸出的信息的關鍵字 |
bundle |
true |
LocalizationContext |
指定ResourceBundle對象在Web域中的屬性名稱 |
var |
false |
String |
用於指定將格式化結果保存到某個Web域中的某個屬性的名稱 |
scope |
false |
String |
指定將格式化結果保存到哪個Web域中 |
<fmt:message>標籤有如下一些特性:
l 如果指定的資源不存在,輸出“???<key>???”形式的錯誤信息。
l 如果ResouceBundle中不存在key屬性指定的信息,輸出“???<key>???”形式的錯誤信息。
l 如果key屬性的值爲null或空字符串,輸出“??????”形式的錯誤信息。
l 如果沒有指定var屬性,<fmt:message>標籤將直接輸出格式化的結果;如果指定了var屬性,則<fmt:message>標籤將格式化的結果保存在scope屬性指定的Web域中,保存在Web域中的屬性名稱爲var屬性指定的值。如果指定了scope屬性,就必須指定var屬性。
l 要輸出的消息的關鍵字可以使用key屬性指定,也可以在標籤體中指定。如果<fmt:message>標籤嵌套在<fmt:bundle>標籤內,並且<fmt:bundle>標籤設置了prefix屬性,則該屬性的值追加到<fmt:message>標籤指定的關鍵字的前面。
l 可以通過在<fmt:message>標籤內嵌套<fmt:param>標籤來指定格式化文本串中的佔位符的參數值,每個<fmt:param>標籤分別設置一個參數,各個<fmt:param>標籤的順序與格式化字符串的參數相對應,即第一個<fmt:param>標籤對應于格式化字符串中的第一個參數,第二個<fmt:param>對應于格式化字符串中的第二個參數,依次類推。
l 如果<fmt:message>標籤處理的格式化文本串中包含有參數,但其中沒有嵌套與該參數對應<fmt:param>標籤,則直接輸出該參數在格式化文本串中的原始形式。
例程8-30是一個使用<fmt:message>標籤的例子程序。
例程8-30 fmt_message.jsp
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<%@ page contentType="text/html;charset=gb2312" %>
<jsp:useBean id="now" class="java.util.Date" />
<%
session.setAttribute("number", new Integer(8888888));
%>
<fmt:setBundle basename="org.it315.greetings" var="greetings" />
<fmt:message>標籤內嵌套<fmt:param>標籤的情況:<br />
<fmt:message bundle="${greetings}">
org.it315.okKey
<fmt:param value="${now}" />
<fmt:param value="${number}" />
</fmt:message><br /><hr />
<fmt:message>標籤內沒有嵌套<fmt:param>標籤的情況:<br />
<fmt:bundle basename="org.it315.greetings" prefix="org.it315.">
<fmt:message key="okKey" />
</fmt:bundle>
例程8-30的運行結果如圖8.25 所示。
圖8.25