中國(guó)長(zhǎng)江三峽集團(tuán)公司 李 哲 羅惠恒 周 容
軟件國(guó)際化(Inter nat ional ization, 又稱(chēng)I18N),是指在軟件設(shè)計(jì)和文檔開(kāi)發(fā)過(guò)程中,為了代碼設(shè)計(jì)與功能實(shí)現(xiàn)能處理多種語(yǔ)言和文化習(xí)俗,從而創(chuàng)建不同語(yǔ)言版本時(shí),不需要重新設(shè)計(jì)原程序代碼的軟件工程方法。
軟件本地化(Local izat ion,又稱(chēng)L10N),是指將一個(gè)軟件產(chǎn)品按特定國(guó)家/地區(qū)或語(yǔ)言市場(chǎng)的需要進(jìn)行加工,使之滿(mǎn)足特定市場(chǎng)上的用戶(hù)對(duì)語(yǔ)言和文化的特殊要求的軟件生成活動(dòng)。即針對(duì)某一地域所支持的編碼字符集、語(yǔ)言和地域習(xí)慣為軟件建立符合本地要求的信息的過(guò)程[1]。
主流的J2EE的表現(xiàn)層框架如Spr ing MVC、St r ut s等對(duì)國(guó)際化或多或少有相應(yīng)的解決方案。但上述方案并不能適配所有場(chǎng)景,隨著RESTFUL風(fēng)格的興起,越來(lái)越多的數(shù)據(jù)展示和格式化工作直接交給了前端模板或組件,這需要客戶(hù)端Javascr ipt(簡(jiǎn)稱(chēng)JS)腳本國(guó)際化的支持。本文介紹了一種針對(duì)基于J2EE三層架構(gòu)[2]WEB項(xiàng)目的多語(yǔ)言解決方案,有效解決了國(guó)際化過(guò)程中的相關(guān)問(wèn)題。
多語(yǔ)言的網(wǎng)站根據(jù)語(yǔ)言的組織方式可以分為有如下的兩種構(gòu)成類(lèi)型:
(1)單站點(diǎn)類(lèi)型。不同語(yǔ)言的網(wǎng)站作為一個(gè)站點(diǎn),然后采用各種手段實(shí)現(xiàn)頁(yè)面的多語(yǔ)言。利用如第三方插件翻譯、針對(duì)不同語(yǔ)言頁(yè)面分目錄、動(dòng)態(tài)內(nèi)容產(chǎn)生[3]等方式實(shí)現(xiàn)國(guó)際化。
(2)多站點(diǎn)類(lèi)型。不同語(yǔ)言的網(wǎng)站作為多個(gè)站點(diǎn),保存在不同的服務(wù)器。服務(wù)器之間不存在任何聯(lián)系,即一系列內(nèi)容相關(guān)的網(wǎng)站集合。
采用單站點(diǎn)模式[4]可以有效減少不必要的服務(wù)器開(kāi)銷(xiāo)、降低開(kāi)發(fā)及維護(hù)成本適用于大多數(shù)企業(yè)的信息系統(tǒng)建設(shè)。由于界面的風(fēng)格以及展示的功能相對(duì)固定,翻譯的精細(xì)化程度相對(duì)較高,采用動(dòng)態(tài)內(nèi)容產(chǎn)生作的手段可以在保證功能的前提下,有效減少開(kāi)發(fā)前端代碼的工作量。
動(dòng)態(tài)內(nèi)容產(chǎn)生模式進(jìn)行國(guó)際化主要包含兩個(gè)步驟:一是對(duì)語(yǔ)言的解析,二是根據(jù)所解析的語(yǔ)言進(jìn)行本地化內(nèi)容填充。下面以基于J2EE的三層架構(gòu)的WEB系統(tǒng)為例對(duì)其流程進(jìn)行說(shuō)明:
服務(wù)器在接收到請(qǐng)求后首先進(jìn)行語(yǔ)言解析,依據(jù)請(qǐng)求中包含的參數(shù)確定出響應(yīng)頁(yè)面的語(yǔ)言種類(lèi)。然后依據(jù)所解析的語(yǔ)言種類(lèi),在不同層次完成國(guó)際化的工作。
一部分UI頁(yè)面直接在表現(xiàn)層的對(duì)模板(JSP)進(jìn)行編譯時(shí)完成;一部分UI頁(yè)面通過(guò)JS、CSS在客戶(hù)端瀏覽器渲染時(shí)完成。
由于JS對(duì)于國(guó)際化的支持相對(duì)Java較弱,所以擬將語(yǔ)言解析放在服務(wù)器端完成。J2SE中用地區(qū)(l ocal e)的概念代表用戶(hù)選擇的顯示語(yǔ)言以及日期、時(shí)間、貨幣等方面的格式化約定,這里選擇將該值作為解析的結(jié)果。
通常基于MVC的表現(xiàn)層框架都提供了幾種默認(rèn)的地區(qū)解析器。例如在Spr ing MVC中,通過(guò)攔截器的方式配置地區(qū)解析器,默認(rèn)通過(guò)HTTP請(qǐng)求頭部解析區(qū)域acceptl anguage設(shè)置l ocal e。對(duì)語(yǔ)言解析的方式可以通過(guò)配置id為l ocal eResol ver的bean對(duì)象進(jìn)行修改,實(shí)現(xiàn)方式包括:根據(jù)session解析、根據(jù)cookie解析、固定地區(qū)等,當(dāng)有特殊要求時(shí)也可通過(guò)自定義方式實(shí)現(xiàn)。
圖1 語(yǔ)言參數(shù)解析流程圖
在根據(jù)session解析的方式中,標(biāo)識(shí)語(yǔ)言的參數(shù)作為session的一個(gè)屬性保存。該參數(shù)會(huì)隨著會(huì)話的結(jié)束而丟失。在根據(jù)cookie解析的方式中,標(biāo)識(shí)語(yǔ)言的參數(shù)會(huì)在cookie中長(zhǎng)期保存更加符合現(xiàn)實(shí)中的應(yīng)用場(chǎng)景。對(duì)于沒(méi)有采用MVC框架的表現(xiàn)層,可以借鑒框架的結(jié)構(gòu)自定義過(guò)濾器(f il ter)來(lái)完成對(duì)語(yǔ)言的解析工作。
如圖1所示,解析完成后,表現(xiàn)層的控制器可以獲取該值,并將其關(guān)聯(lián)到對(duì)應(yīng)線程的上下文中傳遞給業(yè)務(wù)邏輯層進(jìn)而完成業(yè)務(wù)動(dòng)態(tài)數(shù)據(jù)國(guó)際化。
為了實(shí)現(xiàn)主動(dòng)切換語(yǔ)言的功能,需要提供一個(gè)服務(wù)直接修改地區(qū)判據(jù)。具體實(shí)現(xiàn)可以通過(guò)一個(gè)控制器修改cookie中的參數(shù)。
服務(wù)器端的國(guó)際化包含兩個(gè)方面:消息等靜態(tài)數(shù)據(jù)的國(guó)際化和動(dòng)態(tài)數(shù)據(jù)的國(guó)際化。
基于MVC的表現(xiàn)層框架通常對(duì)J2EE中的消息機(jī)制進(jìn)行了加強(qiáng),已經(jīng)實(shí)現(xiàn)在解析出l ocal e對(duì)象后自動(dòng)加載對(duì)應(yīng)語(yǔ)言名稱(chēng)后綴的消息配置文件的功能??刂破鞲鶕?jù)請(qǐng)求參數(shù)調(diào)用不同的視圖(JSP)和模型組合并成返回的UI頁(yè)面。視圖中的消息預(yù)先定義在不同語(yǔ)言的消息配置文件中,依據(jù)l ocal e調(diào)用不同的消息配置文件,將其填充進(jìn)UI頁(yè)面。
對(duì)于沒(méi)有采用MVC框架的項(xiàng)目,同樣可以利用JTSL的消息機(jī)制,但須自行完成不同種語(yǔ)言的標(biāo)簽庫(kù)的加載工作。這里可以通過(guò)將這一部分工作直接放在語(yǔ)言解析過(guò)濾器中實(shí)現(xiàn),通過(guò)代碼:Conf ig.set(r equest, Conf ig.FMT_LOCALE,l ocal e)修改JSTL的配置對(duì)象Conf ig即可。
動(dòng)態(tài)數(shù)據(jù)的國(guó)際化較為復(fù)雜,依賴(lài)于業(yè)務(wù)邏輯層將語(yǔ)言作為參數(shù)進(jìn)行處理。一般需要對(duì)數(shù)據(jù)訪問(wèn)層以及數(shù)據(jù)庫(kù)層進(jìn)行修改。常見(jiàn)的方案是根據(jù)語(yǔ)言參數(shù)在關(guān)系數(shù)據(jù)庫(kù)中按照單表或分表方式對(duì)不同語(yǔ)言的數(shù)據(jù)進(jìn)行存儲(chǔ),可以采用基于AOP的動(dòng)態(tài)數(shù)據(jù)國(guó)際化方案[5]實(shí)現(xiàn)。
在瀏覽器進(jìn)行頁(yè)面渲染時(shí),JS控件、前端模板(EJS)等對(duì)所展示數(shù)據(jù)進(jìn)行內(nèi)容填充、格式化時(shí)需要完成國(guó)際化操作。
通用的JS控件一般都包含獨(dú)立的本地化文件,采用多個(gè)文件分散管理標(biāo)簽的方式雖然簡(jiǎn)單,但是沒(méi)有達(dá)到與后臺(tái)標(biāo)簽的統(tǒng)一管理的目的。因此,可以選擇采用在前端實(shí)現(xiàn)通用的標(biāo)簽加載器的方式進(jìn)行改進(jìn)并達(dá)到上述目的,如圖2所示。
圖2 i18n標(biāo)簽加載器的工作流程
由于語(yǔ)言的解析工作已在服務(wù)器端完成,頁(yè)面在加載時(shí)僅需根據(jù)l ocal e參數(shù)向服務(wù)器請(qǐng)求不同的JS、CSS文件。在開(kāi)始渲染之前,利用一個(gè)通用的i18n標(biāo)簽加載器發(fā)出Aj ax請(qǐng)求從服務(wù)器端獲取對(duì)應(yīng)l ocal e的標(biāo)簽文件(.pr oper t ies),并按照各個(gè)UI控件的需求由i18n加載器轉(zhuǎn)換為特定的JS對(duì)象供UI組件使用。
此外對(duì)于貨幣、時(shí)間等信息的國(guó)際化,一部分利用JSTL標(biāo)簽在服務(wù)器端處理,還有一部分必須在前端完成處理的利用For mat Js、Moment Js等通用格式化組件進(jìn)行。
由于本方案采用唯一的配置文件管理頁(yè)面上幾乎所有的靜態(tài)標(biāo)簽(消息),配置文件的體積會(huì)隨著系統(tǒng)的增大而不斷擴(kuò)大,不利于提高運(yùn)行和維護(hù)的效率。為了解決上述問(wèn)題,需要建立通用的標(biāo)簽命名規(guī)則和標(biāo)簽控制界面。
擬采用統(tǒng)一的命名方式: <應(yīng)用名>_<標(biāo)簽類(lèi)型>_<標(biāo)簽名稱(chēng)>。企業(yè)內(nèi)部根據(jù)系統(tǒng)名稱(chēng)確定唯一的<應(yīng)用名>,<標(biāo)簽類(lèi)型>分為m(message/消息)和l(l abel/標(biāo)簽),<標(biāo)簽名稱(chēng)>盡量采用標(biāo)簽顯示值得英文單詞駝峰形式(可根據(jù)情況選取縮寫(xiě))。
為了減少標(biāo)簽的數(shù)量,規(guī)定m類(lèi)型標(biāo)簽區(qū)分大小寫(xiě),l類(lèi)型不區(qū)分。對(duì)l類(lèi)型的標(biāo)簽的格式化通過(guò)設(shè)置CSS3的t ext-t r ansf or m或者JS函數(shù)進(jìn)行。
建另外,需要立統(tǒng)一的標(biāo)簽管理頁(yè)面,并采用如spr ing中提供的動(dòng)態(tài)加載資源文件的模式(Rel oadabl eR esour ceBundl eMessageSour ce)加載消息配置文件。后期用戶(hù)如果對(duì)WEB界面上的任意標(biāo)簽值不滿(mǎn)意,可以通過(guò)的標(biāo)簽管理界面查詢(xún)標(biāo)簽并修改,并且能夠?qū)崟r(shí)地看到效果,避免用戶(hù)直接接觸到配置文件。
本文通過(guò)對(duì)現(xiàn)有國(guó)際化方案的比較和分析,針對(duì)企業(yè)基于J2EE三層結(jié)構(gòu)的信息系統(tǒng)設(shè)計(jì)了一整套國(guó)際化方案,并提出利用統(tǒng)一的資源文件管理前后端標(biāo)簽,并創(chuàng)建標(biāo)簽管理頁(yè)面進(jìn)行后續(xù)維護(hù)。該方案已在公司內(nèi)部的信息系統(tǒng)項(xiàng)目中得到驗(yàn)證。
[1]董俊龍,王武魁.淺議基于JSF的Java國(guó)際化編程及其實(shí)現(xiàn)[J].微計(jì)算機(jī)信息,2009,25:170-171.
[2]陸榮幸,郁洲,阮永良,等.J2EE平臺(tái)上MVC設(shè)計(jì)模式的研究與實(shí)現(xiàn)[J].計(jì)算機(jī)應(yīng)用研究,2003,20:144-146.
[3]周中雨,呂琳琳.J2EE平臺(tái)下WEB應(yīng)用國(guó)際化的研究與實(shí)現(xiàn)[J].計(jì)算機(jī)系統(tǒng)應(yīng)用,2006,09(9):69-71.
[4]張菲菲,薛賀,李建良.多語(yǔ)言Web網(wǎng)站的設(shè)計(jì)與實(shí)現(xiàn)[J].微電子學(xué)與計(jì)算機(jī),2008,5:43-45.
[5]胡泊.基于JSF的國(guó)際化框架的設(shè)計(jì)與實(shí)現(xiàn)[D].北京郵電大學(xué),2009.