對於一個面向全球的Web應用程序,按著不同國家的要求顯示相關信息(稱為國際化)顯得尤為重要。國際化的工作非常復雜和繁瑣。因為要翻譯很多Web界面,信息格式等。然而,Struts為我們提供了完成國際化工作的更容易的方式。在本文將介紹如何使用Struts來簡化國際化的工作。
一、處理客戶端界面的編碼問題
由於Web浏覽器可以使用不同的編碼格式來解析客戶端代碼,這主要取決於用戶的默認設置或偏好。由於存在這種情況,因此,在服務端向客戶端發送數據時,就必須使用和客戶端一致的編碼格式。
通常的做法是使用Internet上比較常用的UTF-8編碼,這主要是因為UTF-8編碼格式所描述的字符包括了世界上所有以知國家和地區的語言編碼。這樣服務端就不用根據客戶端的編碼格式不斷地調整服務端響應信息的編碼格式了。對於JSP頁面來說,可以使用page指定來設置響應信息的編碼格式,如下面代碼所示:
<%@ page contentType="text/html; charset=UTF-8" %>
當然,如果我們在Web程序中使用了Struts框架,還可以在struts-config.xml文件中使用如下的代碼來設置編碼格式:
<controller contentType="text/html; charset=UTF-8" />
如果使用上面的設置,所有通過.do或<forward>元素訪問的頁面都會繼承這一編碼設置。但是如果單獨訪問JSP頁面,就會繞過Struts的這個設置。
對於靜態頁面(如HTML)來說,需要使用<meta>元素來設置編碼格式,如下面代碼所示:
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
</head>
除了使用通用的UTF-8編碼格式外,也可以從HTTP請求頭字段Accept- Charset中獲得客戶端的編碼格式。然後根據這個編碼格式來設置響應信息的編碼格式。然而,雖然根據HTML4.0規范,Web浏覽器可以設置 Accept-Charset字段,但是有很多浏覽器可以會忽略這一字段,因此,只使用這個字段來確定Web浏覽器所使用的編碼格式是不可靠的。所以最好的國際化編碼格式解決方案仍然是UTF-8。
二、本地化屬性文件
本地化最重要的部分就是根據用戶所處的語言環境來顯示響應語言的界面,如用戶在英文操作系統下,就會顯示英文界面,如果在中文操作系統下,就會顯示中文界面。最理想的情況是這種顯示效果的切換是完全透明的。
在Struts中提供了這種技術,使我們可以更容易地實現透明地界面切換。在Struts Bean標簽庫中有一個<bean:message>標簽,它可以根據客戶端浏覽器所處的語言環境自動選擇相應的屬性文件來讀取界面顯示信息。為了演示如何使用<bean:message>以及不同的屬性文件來實現國際化的程序。讓我們先來看一個例子。
在本例中,選用了三個國家的語言環境(中文、英文和法文)來演示國際化的實現。由於讀者可能不便於輸入法文,因此,法文信息仍然用中文代替,只是後面多了個“(法文)”作為標識。我們需要如下四步來完成這個例子:
【第1步】建立一個默認的屬性文件
在<samples工程目錄>\src\struts目錄中建立一個application.properties文件,內容如下:
title=這是一個國際化的web程序(默認值)
name=姓名(默認值)
submit=提交(默認值)
application.properties文件是默認的屬性文件,如果客戶端浏覽器所處的語言環境在服務端未找到相應的屬性文件,<bean:message>標簽就會從application.properties文件中讀取字符串信息。
在Eclipse中編輯非ISO 8859-1編碼格式的字符時,應使用在《屬性(資源)文件亂碼問題的解決之道》介紹的兩個Eclipse插件,或使用native2ascii.exe命令進行轉換。否則在顯示屬性文件中的信息時會出現亂碼。
【第2步】在struts-config.xml文件中配置屬性文件
在Struts中所有的屬性文件都必須在struts-config.xml文件中配置。否則<bean:message>標簽就會由於無法找到相應的屬性文件而拋出異常。
為了配置application.properties,需要在struts-config.xml文件中的<struts-config>標簽中加入如下的代碼:
<message-resources parameter="struts.application" key = "global"/>
由於在struts-config.xml文件中已經有一個ErrorDescription.properties作為默認的屬性文件,因此,application.properties文件要使用一個key加以標識。在使用<bean:message>標簽時必須要使用bundle屬性指定這個key才能找到application.properties文件。
【第3步】加入不同語言的屬性文件
在這一步我們來加入中文、英文、法文的屬性文件。這三個屬性文件的文件名如下:
中文:application_zh.properties
英文:application_en.properties
法文:application_fr.properties
將這三個文件放到<samples工程目錄>\src\struts目錄中。它們的內容如下:
application_zh.properties
title=這是一個國際化的web程序
name=姓名
submit=提交
application_en.properties
title=Thisisaninternationalizationwebprogram.
name=name
submit=submit
application_fr.properties
title=這是一個國際化的web程序(法語)
name=姓名(法語)
submit=提交(法語)
這三個屬性文件是不需要在struts-config.xml中配置的。Struts會自動根據客戶端浏覽器所處的語言環境來尋找這三個文件。
【第4步】編寫JSP頁面
在這個JSP頁面中使用了<bean:message>來根據客戶端浏覽器所處的語言環境來讀取相應的屬性文件中的內容。在web根目錄中建立一個global.jsp文件,代碼如下:
<%@ page pageEncoding="UTF-8" %>
<%@ taglib uri="http://struts.apache.org/tags-bean" prefix="bean"%>
<html>
<head>
<title>國際化</title>
</head>
<body>
<bean:message key="title" bundle="global" /><p/>
<form action="">
<bean:message key="name" bundle="global" />:
<input type="text" name="name" /><p/>
<input type="submit" value=<bean:message key="submit" bundle="global"/> />
</form>
</body>
</html>
由於安裝不同語言的操作系統很不方便,在這裡我們采用另一種方法來模擬不同的語言環境測試這個程序。首先在IE中使用【工具】>【Internet 選項】> 【常規】>【語言】來打開“語言首選項”對話框,使用“添加”按鈕添加“中文 [zh]”、“英文 [en]”和“法語(法國) [fr]”,再添加一種其他語言,如“梵文 [sa]”。添加後的界面如下圖所示。
然後分別將這四種語言上移到列表頂端。然後點擊“確定”按鈕保存設置。在啟動Tomcat後,在IE中輸入如下的URL:
http://localhost:8080/samples/global.jsp
根據語言設置的不同,在IE中會顯示不同語言的界面,如中文和英文的頁面分別如下面兩個圖所示。
如果在刷新時頁面語言未更新,可能是因為IE的Cache的原因,讀者可以啟一個新的IE窗口,再進行測試。
讀者在使用屬性文件進行國際化時應注意如下三點:
1. 由於語言還可以繼續細分,如中文可以分為簡體和繁體,英文也可以分為不同國家或地區的英文,如愛爾蘭、澳大利亞等。因此,對於更細化的語言,可以在屬性文件後面再加一個代表國家或地區的後綴,如application_zh_TW.properties代表中國台灣所使用的繁體中文,application_en_AU.properties代表澳大利亞英文。Struts在尋找屬性文件時,會首先查找帶有國家或地區後綴的屬性文件,如果這類文件不存在,會繼續查找只有語言後綴的屬性文件,如果還不存在,最後會讀取默認屬性文件,也就是application.properties的內容。假設我們在“語言首選項”中選擇了“中文(台灣) [zh-tw]”,那麼讀取文件的順序(從最左邊開始,如果文件不存在,依次讀取右邊的文件)如下:
application_zh_TW.properties > application_zh.properties > application.properties
如果選擇的語言是“中文 [zh]”,那麼就直接從application_zh.properties開始讀取。
2.在建立屬性文件時要注意,後綴的連接符為下劃線( _ ),而不能用減號( - )。
3. 代表語言的後綴(如zh、fr、en等)必須小寫,而代表國家或地區的後綴(如CN、TW、AU等)必須大寫。如寫成application_ZH_tw.properties是不正確的。
在Struts HTML標簽庫中的標簽中以key為後綴的屬性值就是屬性文件中的key,如下面的代碼所示:
<html:submitvalue="提交" titleKey="title" bundle="global"/>
上面的代碼將<html:submit>標簽的title屬性值設為屬性文件的title鍵的值。但是在<html:submit>標簽中的value屬性無法使用屬性文件中的鍵值,解決的方法是使用< html:submit>標簽的另一種寫法,代碼如下:
<html:submit>
<bean:messagekey=“title” bundle=“global”/>
</html:submit>
三、實現多種語言界面的Web程序
在上面所講的國際化只是根據客戶端浏覽器所處的語言環境來自動設置界面語言。而我們在Internet上會看到很多Web程序在主界面上都提供了對不同語言的選擇。在本節我們就來講一下如何通過編程的方式來干預服務端對屬性文件的選擇。
實現上,Java使用java.util.Locate類來描述語言,一個Locate類的對象實例就代表一種語言。並且從客戶端獲得的語言信息使用“org.apache.struts.action.LOCALE”保存在了session中,因此,我們只要在調用<bean:message>或其他使用屬性文件的語句之前修改session中保存的Locale對象,就可以達到我們的目的。現在我們來對global.jsp頁面進行修改(新建一個文件newGlobal.jsp)。global.jsp中所有的代碼都不用動,只需要在第一個<bean:message>標簽的前面加上如下的代碼:
……
<%
if("en".equals(request.getParameter("language")))
session.setAttribute("org.apache.struts.action.LOCALE",new java.util.Locale("en"));
else if("zh".equals(request.getParameter("language")))
session.setAttribute("org.apache.struts.action.LOCALE",new java.util.Locale("zh"));
else if("fr".equals(request.getParameter("language")))
session.setAttribute("org.apache.struts.action.LOCALE",new java.util.Locale("fr"));
%>
<bean:messagekey="title" bundle="global"/>
……
在Web根目錄中建立一個mainGlobal.jsp文件,如下面的代碼所示:
<%@ page pageEncoding="UTF-8"%>
<html>
<head>
<title>多語言支持</title>
</head>
<body>
<a href="newGlobal.jsp?language=en" target="_blank">英文</a><p/>
<a href="newGlobal.jsp?language=zh" target="_blank">中文</a><p/>
<a href="newGlobal.jsp?language=fr" target="_blank">法文</a>
</body>
</html>
啟動Tomcat後,在IE中輸入如下的URL:
http://localhost:8080/samples/mainGlobal.jsp
點擊mainGlobal.jsp頁面上的三個鏈接,就會分別顯示三種語言的頁面。
在Struts Action類中的也可以使用Action類提供的setLocale方法來設置語言。如在execute方法中設置語言的代碼如下:
setLocale(request,new java.util.Locale("zh","TW"));
使用setLocale方法設置語言時應注意兩點:
1. java.util.Locale的構造方法的第一個參數表示語言,第二個參數表示國家或地區,這兩個參數值和屬性文件的後綴不同,它不區分大小寫,因此,也可以寫成如下的形式:
setLocale(request,new java.util.Locale("ZH","tw"));
2.所有經過<forward>元素或.do的程序都會繼承setLocale方法設置後的語言,但<action>元素的forward和input屬性所指的頁面除外。