在完成本文所有內容的閱讀和實踐前,本文假定您已具備了 Java ResouceBundle、 Java Locale和J2EE方面的知識,同時熟悉Eclipse IDE開發環境以及Eclipse插件的安裝 、配置和使用。
IGT開發背景
軟件全球化支持,被公認為是電子商務市場成功的一個關鍵部分。實時請求方式的電 子商務,在"提供英語或其它語言版本的問題解答"方面,面臨了新的挑戰。在過去幾年中 ,為了符合 "IBM的全球化標准",無論是那些新開發的,抑或是那些以英文版用戶為設計 初衷的軟件產品,都要求能夠被全球化。為使運行在單機服務器或終端處理機上的軟件, 能夠在多語言環境(例如互聯網)中,進行正確的多語言數據處理,數據顯示以及日志,軟 件開發者不得不耗費巨大的精力。那麼,如何才能成功解決這種新的需求難題呢?
全球化開發過程中,我們找到了一個有效的解決方案,即使用一個功能增強的Eclipse 插件來簡化全球化開發工作。在Eclipse 3.0版本中,Eclipse已為使用者提供了一個名為 "Externalize String"的插件(外部化字符串插件)。雖然此Externalize String插件已 具備了"提取字符串,修改代碼,以及自動創建屬性文件"的功能。但是經此插件處理的軟 件,不能在復雜的Internet環境中分離地處理多語言的數據顯示和日志記錄, 所以不適 用於多用戶的B/S應用。
基於以上各因素,最終我們開發出了一個新的Eclipse插件來實現軟件國際化的目標。 與原先的"Externalize String"插件相比,功能增強後的全球化插件--IBM Globalization Tool(簡稱為IGT),不僅完善了Externalize String所具有的"抽取核心 字符串,修改代碼,以及自動創建屬性文件"的功能,還為用戶提供了一個具有 "處理客 戶端地域信息,響應不同用戶請求,以及創建多語言日志"功能的中間層。IGT允許一個服 務實例,通過用一個在全球化過程中自動創建的稱之為"XX Resources"的集合類對象,使 得應用程序軟件能夠根據客戶端的實際位置信息來顯示多語言數據。在這個被稱為"XX Resources"集合類中,每個被稱為"資源入口(Resource Entry)"類的對象,都對應地指 向了某個存放在屬性文件裡的消息字符串。而這種 "資源入口(Resource Entry)" 對象 ,既可以被開發人員自行實現或者使用默認由工具生成的。 基於這種理念設計出的IGT, 為我們提供了一個更為靈活和快捷的國際化J2EE 企業級應用程序的方式。
下載組件
需要下載並安裝的組件列表
表 1. 在這篇文章中用到的組件及版本
Component Version Eclipse IDE 3.1/3.0 IGT 1.0 Java SDK 1.4.1 1.4.2 Tomcat 5.0.16
下載需要的組件你需要的,站點被列在了資源一節中。
安裝IGT
您需要根據您Eclipse版本, 把IGT解壓到Eclipse的plugin文件夾下,重新啟動 Eclipse就可以完成IGT的安裝了。驗證IGT的安裝從Eclipse界面, 如下圖所示。
(圖1 Eclipse菜單欄和工具欄界面)
實例1, 使用IGT實現一個C/S應用的全球化支持
本文將首先通過一個簡單的C/S應用的實例(實例1簡稱例1)向您介紹IGT的使用方法 。
例1實現一個簡單的C/S應用程序,客戶機Client和服務器(Server)能夠進行基於 Socket方式的通信。程序模擬了位於不同地區的客戶機,同時向服務器提出服務請求。服 務器在接收到客戶機的請求後進行相應的處理,並將結果返回給客戶機,同時在服務器上 按照指定語言顯示日志信息。
例1中用MultipleClients類和SocketServer類分別實現客戶機和服務器的功能。
MultipleClients類創建了5個分別來自Japan,US,France,German,China的客戶機 類的實例。它們同時向服務器提出logon,Add, Update,Remove, Rollback和Logoff 這5 類不同的服務請求,同時接受服務器的返回信息,並將返回的信息顯示在客戶端。
new ClientThread( addr , port, "Locale.US", "Login/Add/Remove/Update/Logoff" ),模擬了一個位於US的客戶機向服務器發出連續的 "Login/Add/Remove/Update/Logoff" 五種動作的請求。
SocketServer類主要實現的功能:1、服務器響應客戶機請求。2、顯示動作請求在服 務端. 3, 返回相應動作結素消息給客戶機。
在未使用IGT去實現程序的全球化支持時,客戶端和服務端的運行結果如下:
客戶端
Server response to client 0[client:US] : Login server succefully!
Server response to client 4[client:GERMAN] : Login server succefully!
Server response to client 4[client:GERMAN] : Perform action Add succefully!
Server response to client 4[client:GERMAN] : Perform action Rollback succefully!
Server response to client 4[client:GERMAN] : Perform action Remove succefully!
Server response to client 3[client:FRANCE] : Login server succefully!
Server response to client 2[client:JAPAN] : Login server succefully!
Server response to client 3[client:FRANCE] : Perform action Remove succefully!
Server response to client 0[client:US] : Perform action Add succefully!
Server response to client 1[client:CHINA] : Login server succefully!
Server response to client 4[client:GERMAN] : Perform action Logoff succefully!
….
服務端
Server Started the service......
US logged on.
CHINA logged on.
GERMAN logged on.
FRANCE logged on.
JAPAN logged on.
US perfom action Add.
GERMAN perfom action Add.
GERMAN perfom action Rollback.
GERMAN perfom action Remove.
…
從以上顯示結果中,可以發現服務器的日志信息和反饋信息都是英語。對於非英語用 戶來說軟件的易用性不好。
下面,我們將在Eclipse平台下使用IGT插件實現增加服務器端程序的多語言支持,不 同語言的客戶得到不同語言的反饋, 並以指定語言記錄日志信息。
使用IGT實現C/S應用程序的多語言支持
首先,選擇要進行全球化的程序文件。為使服務器能夠"根據客戶端的語言信息,對客 戶端提交的申請做出相應的語言處理,並將相應的語言顯示結果返回客戶端",所以我們 只需要對服務器程序(SocketServer.java)中的處理信息字符串做全球化的處理,主要 處理硬編碼的字符串信息。然後,啟動"IGT全球化向導"應用程序去完成硬編碼字符串的 抽取,以及生成必要的輔助類和資源文件。接下來,我們需要對服務端代碼做簡單的修改 去設置語言參數。最後,為其他語言創建資源文件。
使用"IGT全球化向導"
本節將向您介紹使用"IGT向導"應用程序的具體步驟:
步驟1:在SocketServer.java的編輯窗口中,以下三個方式的任一種啟動IGT全球化向 導。
1. 點擊上圖的IGT菜單
2. 點擊上圖的IGT按鈕圖標
3. 單擊右鍵,在活動菜單欄中找到"Globalization Tool…"菜單項。
步驟2:全球化字符串首頁--資源配置窗口。
在此窗口中,選擇您資源入口類和資源裝載類的存放路徑和存放的包名。在這裡, 我 們將這兩個類存放在IGT_CS中的nls包。默認使用源文件所在的包。點擊"Next"進入下一 步。
步驟3:全球化字符串操作窗口。
Enter common prefix for generated MessageIDs (EntryNames): IGT將自動在輸入 內容添加後綴,為您自動生成相應的變量名。默認為源文件類名
Ignore :放棄對此字符串做全球化處理。
Restore:將全球化處理後的字符還原為原來字符。
String to globalize欄:IGT自動為您從源文件中抽取出來的所有字符串顯示在此欄 中。您可以從中選擇要進行全球化處理的字符串。Substitution pattern:選擇字符串替 換的方式。IGT為您提供了 tologgingString()和toString()兩種替換方式。這兩種替換 方式的區別在於:
toString():此方法用於處理那些將顯示給客戶機的字符串信息。
tologgingString():用於處理那些將寫入服務器端日志的或標准輸出的字符串信息。
context欄:顯示正在進行處理的字符串信息在源代碼文件中的位置和內容。
例1的字符串處理內容顯示如下:(×號表示不做處理;√表示進行處理。)
完成上述處理後,點擊"Next",進入下一步。
步驟4:此窗口顯示IGT創建過程中遇見的問題。不需做如何操作直接點擊"Next",進 入下一步。
步驟5:進入如下所示的窗口,此窗口為您顯示IGT將執行的處理內容。
從上圖的窗口中您可以看到,IGT主要對以下兩方面進行處理:
A. 用新創建的SocketServerResources文件中對應的靜態資源入口類對象替換掉源文 件中需要進行全球化處理的字符串內容。
B. 創建的新的資源文件、資源入口類、資源裝載類等文件。
步驟6:點擊"Finish",結束IGT全球化過程。
設置客戶機和服務器的語言環境參數,創建資源文件
經過"IGT全球化向導"的全球化應用程序的6個步驟,您已完成了全球化應用程序的大 部分工作。但是,因為在本例中C/S應用的socket 服務端還不能處理客戶端語言信息,我 們需要對源程序作一些簡單的修改,設置客戶機和服務器的語言環境,創建基於各種語言 的資源文件。
首先,我們在程序中添加"設定客戶機和服務器的語言環境信息"的代碼。IGT通過在資 源加載類(ResourceLoader)中提供的 setActiveLocale(Locale locale)和 setLoggingLocale(Locale locale)接口分別實現了對客戶端和服務器端語言環境的設 置。我們需要在應用程序中調用以上兩個接口。
在Server.java中添加以下3部分的代碼,Ctrl + Shift + O 重新組織導入的類庫。
1) 在SocketServer.java中添加setLocale方法(清單2前面部分注釋掉的那段代碼) :
public static void setLocale(String str){
if(str.equals("Locale.US")){
ResourceLoader.setActiveLocale(Locale.US);
}else if(str.equals("Locale.CHINA")){
ResourceLoader.setActiveLocale(Locale.CHINA);
}else if(str.equals("Locale.JAPAN")){
ResourceLoader.setActiveLocale(Locale.JAPAN);
}else if(str.equals("Locale.FRANCE")){
ResourceLoader.setActiveLocale(Locale.FRANCE);
}else if(str.equals("Locale.GERMAN")){
ResourceLoader.setActiveLocale(Locale.GERMAN);
}
}
根據客戶機傳遞過來的字符串值,判斷其對應的語言環境值(Locale值),並對客戶 機的語言環境值(Locale值)進行設定。在你的實際應用中你可以選擇其他的方式來通知 服務端設置合適的語言,例如,通過增加RMI調用借口,或者把其封裝在連接對象中。
2) 在performAction()方法體中的if (action.equals(ActionDef.LOGIN)) 語句的 執行語句體前,添加這樣的一條語句:"ResourceLoader.setActiveLocale (clientLocale); "。添加這條語句的目的在於:在客戶機登錄服務器時,獲取客戶機 Locale信息,
if (action.equals(ActionDef.LOGIN)) {
setLocale(clientLocale);
//Bind client locale to entry object.
setLocale(clientLocale);
…
3) 在main()函數中,在接受客戶機請求信息的處理代碼前添加如下的一條語句:
ResourceLoader.setLoggingLocale(Locale.JAPAN);將服務器本地語言環境設置為 JAPAN。
public static void main(String[] args) throws IOException {
ServerSocket s = new ServerSocket(PORT);
System.out.println("Server Started the service......");
//Set Server locale
ResourceLoader.setLoggingLocale(Locale.JAPAN);
…
}
創建對應5種語言版本的資源文件:
IGT會為您自動地創建一個和原程序文件名一致的默認屬性文件,本例自動創建的默認 屬性文件是SocketServer.properties。您需要拷貝這個文件在同一目錄下,並重命名為 :
SocketServer_en_US.properrties
SocketServer_zh_CN.properties
SocketServer_ja_JP.properties
SocketServer_de.properties
SocketServer_fr_FR.properties
為了簡化問題的實際操作步驟,我們只是在屬性文件中的原字符串後面加上語言環境 的簡寫名稱(如zh_CN等)來標識在不同語言環境中顯示的處理信息。
例如:SocketServer0=\ logged on ########[ja_JP].
在實際應用中,你應該替換為相應語言字符為Unicode編碼。
例如:SocketServer0=\ 成功登錄
提示: 您可以通過JDK中提供的native2ascii程序來進行Unicode編碼的轉化。
測試全球化後的程序的執行結果
完成以上的所有步驟後,您已經成功使用IGT實現了應用程序全球化。
再次運行服務器端和客戶端程序,您可以看到的顯示結果分別如下:
客戶機獲得的服務器返回結果。
Server response to client 3[client:FRANCE] : Login server
succefully!########[fr_FR]
Server response to client 3[client:FRANCE] : Perform action Remove
succefully!########[fr_FR]
Server response to client 1[client:CHINA] : Login server
succefully!########[zh_CN]
Server response to client 2[client:JAPAN] : Login server
succefully!########[ja_JP]
Server response to client 4[client:GERMAN] : Login server
succefully!########[de]
Server response to client 3[client:FRANCE] : Perform action Add
succefully!########[fr_FR]
Server response to client 0[client:US] : Login server succefully!
Server response to client 4[client:GERMAN] : Perform action Add
succefully!########[de]
Server response to client 2[client:JAPAN] : Perform action Rollback
succefully!########[ja_JP]
…
服務器顯示的日志信息
Locale.FRANCE logged on ########[ja_JP].
Locale.CHINA logged on ########[ja_JP].
Locale.US logged on ########[ja_JP].
Locale.GERMAN logged on ########[ja_JP].
Locale.JAPAN logged on ########[ja_JP].
Locale.FRANCE perfom action Remove.########[ja_JP]
Locale.FRANCE perfom action Add.########[ja_JP]
Locale.JAPAN No action to perform.########[ja_JP]
Locale.GERMAN perfom action Add.########[ja_JP]
Locale.CHINA No action to perform.########[ja_JP]
Locale.JAPAN perfom action Rollback.########[ja_JP]
Locale.CHINA No action to perform.########[ja_JP]
Locale.US perfom action Add.########[ja_JP]
…
比較使用IGT前、後的程序執行結果,服務器程序不僅能為客戶機反饋基於客戶機語言 版本的顯示信息,還能以指定語言的記錄日志信息。
實例2,使用IGT實現一個簡單的B/S類型的應用的全球化支持
上節向您介紹了如何使用IGT全球化C/S類型的應用程序,本節將通過一個簡單的B/S應 用實例(實例2簡稱例2)為你演示使用IGT全球化B/S 應用程序的全部過程。你可以通過 本頁的下載鏈接去獲得示例工程。並工程中WebContent 文件夾以/IGT_BS部署在Tomcat上 。
例2演示了一個簡單的web響應。網站服務器程序夠根據訪問網站的用戶的語言環境, 向用戶返回對應其語言的消息,同時在服務器端,根據指定的語言記錄下用戶的活動日志 信息。
1.welcome.html:一個簡單的頁面,用戶可以選擇登陸和購買三種商品。在單擊 Perform按鈕後,簡單的返回成功執行的消息。
2. StoreActionBean:一個簡單Javabean用來執行業務邏輯針對用戶請求,在這裡僅 僅返回反饋信息,並記錄日志。
例如,[Logging Locale:zh_CN]Done to add chocolate!
3.StoreServlet 處理用戶請求,調用後台的Javabean,組織響應信息。
例如,[Browser's locale is: zh_CN] Done to add chocolate!
測試
模擬使用語言為的用戶登錄網站,您可以通過修改浏覽器的默認Language 通過 點擊 工具 > Internet 選項 > 常規 > 語言, 移動"德語"到頂部。登陸 welcome.html,點擊Perform按鈕。
日志
[Logging Locale:zh_CN]Login Successfully!
從以上兩個圖中可以看出:後台的Javabean沒有實現多語言支持
使用IGT全球化B/S類型的應用程序
首先,確定需要進行全球化處理的源程序文件。在這裡我們只集中精力於業務邏輯層 StoreActionBean.java。
其次,激活"IGT全球化向導"進行處理。
最後,創建和配置相應的資源屬性文件以及設置服務器和客戶的語言環境參數。
使用"IGT全球化向導"
確定好需要作全球化處理的源文件後,接著的就是使用IGT向導來完成全球化過程。具 體的操作步驟,本文已在例1做了詳細的介紹,例2中就不再作贅述了。
1. 選擇IGT_BS工程的nls包作為輸出路徑,單擊Next。
2. 全球化字符串操作窗口中,修改配置如下圖。單擊Next。
即對那些返回浏覽器的信息做toStrring()方式的處理,對服務器的日志信息做 toLoggingString()的處理。
3. 單擊Finish結束。
創建屬性文件,設置浏覽器和服務器的語言環境參數
完成IGT向導的相關操作後,接下來需要在進行全球化的源程序文件中,設置服務器 Locale和浏覽器的Locale,以及創建所需語言版本的資源屬性文件。
I. 設置服務器和浏覽器Locale。在StoreActionBean.java中取消以下兩條語句的注釋 ,分別完成服務器日志和浏覽器的語言地域的設置, Ctrl + Shift + O 重新組織引用。
ResourceLoader.setLoggingLocale(_serverLocale);
ResourceLoader.setActiveLocale(_clientLocale);
II. 創建所需語言版本的屬性文件(Property File):
創建對應5種語言版本的資源文件:
IGT會為您自動地創建一個和原程序文件名一致的默認屬性文件,本例自動創建的默認 屬性文件是StoreActionBean.properties。您需要拷貝這個文件在同一目錄下,並重命名 為:
StoreActionBean_en_US.properrties
StoreActionBean_zh_CN.properties
StoreActionBean_ja_JP.properties
StoreActionBean_de.properties
StoreActionBean_fr_FR.properties
類似於例1,我們也只是在原字符串中添加了一些說明語言版本的文字。在實際應用中 ,你應該替換相應語言字符為Unicode編碼。
測試:
經過以上步驟的處理,您已完成例2程序的全球化全過程。重新發布一下這個web應用 ,分別修該浏覽器的語言設置為"德語","中文",登錄 http://localhost:8080/IGT_BS/Welcome.html。單擊Perform按鈕,浏覽器獲得服務器的 返回結果分別如下:
比較浏覽器前後的顯示結果,可以發現服務器返回給浏覽器的消息是根據浏覽器的語 言設置自動選擇的。同時從服務器顯示的日志信息中,您可以發現服務器能不受浏覽器語 言環境的影響,根據自身語言環境正確地顯示日志信息。
[Logging Locale:zh_CN]Done to add chocolate!####[zh_CN]####
[Logging Locale:zh_CN]Done to add chocolate!####[zh_CN]####
實例3,使用IGT實現一個簡單的RMI類型的應用的全球化支持
在開始之前,你需要通過下載鏈接去獲得實例工程IGT_RMI,並在命令行中執行以下名 令生成RMI的存根,
{$IGT_RMI_Project_location}>rmic server.RMIObjectImpl
在這個工程中我們僅需要對RMIObjectImpl.java應用IGT, 你可以使用相似的步驟去完 成全球化向導。簡要設置如下。
在完成全球化向導之後,添加如下行在RMIObjectImpl的構造方法中
ResourceLoader.setLoggingLocale(Locale.getDefault());
添加如下語句在setClientLocale()方法中。Ctrl + Shift + O 重新組織引用。
ResourceLoader.setActiveLocale(_clientLocale);
創建對應5種語言版本的資源文件並為其增加標示,
RMIObjectImpl_en_US.properrties
RMIObjectImpl_zh_CN.properties
RMIObjectImpl_ja_JP.properties
RMIObjectImpl_de.properties
RMIObjectImpl_fr_FR.properties
測試
在Eclipse 中啟動RMIServer, 並運行RMIClient程序。執行結果如下
客戶端反饋消息
Done to add ####[zh_CN]####1998
Done to remove ####[zh_CN]####9
Done to add ####[de]####1998
Done to remove ####[de]####9
服務端日志
RMIServer starts on //localhost/RMIServer
Client's locale is: ####[zh_CN]####zh_CN
Perform Add ####[zh_CN]####1998
Perform Remove ####[zh_CN]####9
Client's locale is: ####[zh_CN]####de
Perform Add ####[zh_CN]####1998
Perform Remove ####[zh_CN]####9
可以看出RMI應用已經成功的實現了全球化語言支持。
結束語
在本文中,我們已經介紹了如何通過IGT實現C/S, B/S, RMI企業級應用的多語言(國 際化)支持。您可以感受到通過使用IGT,實現多種類型的Java企業級應用的國際化變的 如此簡單。另外IGT還提供了方便的增刪改的功能,使得你的國際化支持的開發工作更加 的簡潔高效。如果你對IGT有更多的建議,你可以登陸論壇 http://www.alphaworks.ibm.com/tech/igt/forum發表你的觀點或聯系我們。
本文配套源碼