摘 要: 針對飛行員飛行品質(zhì)評估系統(tǒng)中的多語言界面問題,采用擴展XML外部語言包的方法,,結(jié)合反射技術(shù),,實現(xiàn)了C#語言環(huán)境下對應(yīng)用軟件的多語言支持。實現(xiàn)過程中對界面文字的導(dǎo)入/導(dǎo)出功能進行了封裝處理,,消除了冗余代碼,。該方法對源程序修改較少,而擴展性強,、維護成本小、程序直觀性好,。
關(guān)鍵詞: XML,;反射技術(shù);多語言界面,;C#
為保證飛行安全,、降低事故發(fā)生率,國內(nèi)外民航系統(tǒng)普遍重視飛行員的培訓(xùn)工作,。目前,,國內(nèi)飛行員培訓(xùn)中心對飛行員操作水平的評估一般都是采用教練員觀察和打分的方式,,不夠客觀和全面。飛行員飛行品質(zhì)評估系統(tǒng)是一個能夠?qū)崿F(xiàn)自動規(guī)范評分的軟件,,它面向的客戶是訓(xùn)練中心的教員,、各航空公司的受訓(xùn)飛行員和高層管理者等,因此,,要求軟件能夠針對不同國家的用戶,,提供不同語言版本的界面,以便于用戶能夠更快地接受和使用該產(chǎn)品,。
多語言界面軟件的設(shè)計,,通常采取應(yīng)用程序和界面文字顯示相分離的技術(shù)[1]:程序代碼獨立編寫,語言資源從核心代碼中分離出來儲存到文件,,運行時根據(jù)用戶需求選擇相應(yīng)的語言資源文件并顯示,。常用的方法有:(1)將系統(tǒng)支持的語言資源生成一個多語言的可執(zhí)行文件或獨立的資源文件[2]。這種方法比較常用,,但是資源更新時需要重新編譯,,擴展性差;(2)將支持的語言資源存放在外部語言包中,,通過替換語言包達到切換語種的目的[3-4],。這種方法不需要重新編譯程序,外部語言包保持獨立,,可以動態(tài)修改,。
基于軟件開發(fā)過程中提出的對源程序進行最少的修改,達到盡可能高的效率,、可靠性和擴展性的要求,,本文利用XML外部語言包實現(xiàn)多語言界面,并且在系統(tǒng)運行的同時生成語言包文件,,便于擴展,;對界面文字的導(dǎo)入/導(dǎo)出功能進行了封裝處理,避免了代碼的冗余,,對源程序修改代價最小,,后期維護方便;在語言包處理過程中運用了.NET的反射技術(shù)以提取和組裝界面提示文字信息,,增加了程序的靈活性和直觀性,。
1 XML語言文件包格式
實現(xiàn)多語言界面的一個重要步驟是設(shè)計外部語言包文件??蓴U展標記語言XML具有自解釋性和靈活的結(jié)構(gòu),,可實現(xiàn)跨平臺交互,表述任意復(fù)雜程度的數(shù)據(jù)格式和無限量的自定義格式描述符,適合作為語言包的格式,。
用戶從軟件獲取的信息都顯示在用戶界面上,,用戶界面由控件對象組成,而語言信息都是由文本控件對象的屬性值來體現(xiàn)的,。建立XML語言包文件的基本思想,,就是從用戶界面中獲取所有文本控件的標識和屬性值,按照結(jié)構(gòu)類別存放到XML文檔中,,這樣語言包文件即可通過控件的標識映射到用戶界面,。應(yīng)用程序的用戶界面通常包含的文本組件如圖1所示。
用戶界面要處理的文本控件對象主要有以下部分:
?。?)Framework:菜單欄,、工具欄、狀態(tài)欄等顯示文本信息的窗體框架,,其文字信息包括各欄框架Bar的Text屬性,、各欄菜單項baritem的Caption屬性(顯示文字)和Hint屬性(提示文字)?;诿阑缑婧头奖闶褂玫囊?,本文中使用BarManager控件來組裝Framework,在程序中分別遍歷其Bar和Items成員即可獲取框架和菜單項的信息,。
?。?)TextControl:只具有(需要)顯示文字功能的控件,如標簽控件Label等,。
?。?)PromptMsg:人機交互過程中顯示的提示信息。提示信息是解決方案中所有窗體共用的,,因此,,將其以公共靜態(tài)變量的形式存放在一個全局靜態(tài)類中。軟件運行時,,利用C#的反射技術(shù)動態(tài)獲取該類的信息,,或創(chuàng)建類的實例并調(diào)用和訪問這些實例。
?。?)UIText:在程序中需要處理而在界面上沒有顯示(或需要經(jīng)過處理后顯示)的文字信息,,如表格控件GridView的表頭等。
為確保切換語言時能夠置換所有的界面文字信息,,所有的文本控件對象都必須在XML語言包中有唯一的節(jié)點與之對應(yīng),。本文中設(shè)定的XML語言包文件的結(jié)構(gòu)如圖2所示。
根據(jù)文本控件在軟件界面中的關(guān)系,,采用樹形結(jié)構(gòu)來描述語言環(huán)境,以解決方案為根節(jié)點;所有的窗體都是解決方案的子節(jié)點,,其子節(jié)點是窗體中各種結(jié)構(gòu)類別的文本控件,;解決方案根節(jié)點的子節(jié)點還包括全局提示信息,其子節(jié)點是所有的全局提示信息,。
2 多語言界面的實現(xiàn)
2.1 軟件模塊與數(shù)據(jù)結(jié)構(gòu)設(shè)計
程序設(shè)計中采用獨立界面獨立模塊的模式,,每個模塊均由一個獨立界面提供相應(yīng)功能。.NET中定義Form類為所有窗體類的基類,,項目中窗體間的關(guān)系如圖3所示,。
程序運行前選擇需要的語言包文件。運行后每個窗體被打開時,,首先在構(gòu)造函數(shù)中完成必要的數(shù)據(jù)結(jié)構(gòu)填充,,繼而在加載基類時實現(xiàn)語言信息的導(dǎo)出與載入,最后加載窗體,。只要每個派生的Form類填充了相應(yīng)的數(shù)據(jù)結(jié)構(gòu),,即可以利用基類中的語言信息導(dǎo)出與載入功能,實現(xiàn)整個軟件所有窗體的語言替換,。
2.2 界面文字信息的導(dǎo)出
對于大型的工程項目,,窗體數(shù)目多、組件復(fù)雜,,手動建立XML語言包文檔不僅耗費大量時間,,而且容易出錯。因此,,本文在程序運行時生成XML文檔,,每打開一個窗體都將其界面文字信息導(dǎo)入到XML語言包文檔。反射是.NET中的重要機制,,它使得.NET中的類型(包括類,、結(jié)構(gòu)、委托和枚舉等)可以通過名稱動態(tài)檢索成員信息,,并且允許在運行的程序中操作這些信息,。本文運用反射技術(shù)動態(tài)地提取界面提示文字信息,具體的實現(xiàn)方法如下:
?。?)程序啟動時,,創(chuàng)建XML文檔,寫入解決方案根節(jié)點,。
?。?)打開一個窗體,在窗體的構(gòu)造函數(shù)中完成該窗體的數(shù)據(jù)結(jié)構(gòu)填充,,加載時完成文字信息的導(dǎo)入,。
?。?)若當(dāng)前處理的窗體未被處理過,在XML文檔根節(jié)點下創(chuàng)建一個新的Form子節(jié)點,,寫入窗體的名稱和標題欄文本等屬性,,并標記處理過的窗體以防重復(fù)處理。對于窗體的Framework控件,,在Form節(jié)點下創(chuàng)建bars節(jié)點和baritem節(jié)點,,將所有的框架和菜單項的名稱和文本以item節(jié)點的形式分別添加到這兩個節(jié)點下;對于TextControl類控件,,在Form節(jié)點下創(chuàng)建textcontrol節(jié)點,,將所有該類控件的名稱和文本以item節(jié)點的形式添加到textcontrol節(jié)點下;對于UIText類組件,,在Form節(jié)點下創(chuàng)建uitext節(jié)點,,將該類組件的名稱和文本以item節(jié)點的形式添加到uitext節(jié)點下。
?。?)全部窗體處理結(jié)束(即退出程序時),,在根節(jié)點下創(chuàng)建globalpromptmsg子節(jié)點,利用反射機制獲取全局靜態(tài)類Globalpromptmsg聲明的所有字段信息,,將所有字段的名稱和文本寫到globalpromptmsg節(jié)點下item節(jié)點的name屬性和text屬性,。全部字段處理結(jié)束后向XML文檔中寫入結(jié)束標志,完成界面文字信息的導(dǎo)出,。其程序如下:
Type type = Globalpromptmsg.GetType(),;
FieldInfo[] currfiledinfos=type.GetFields(BindingFlags.Public|BindingFlags.Static|BindingFlags.Instance);
foreach (FieldInfo filedinfo in currfiledinfos)
{
XmlWriter.WriteStartElement("item"),;
XmlWriter.WriteAttributeString("name",,filedinfo.Name);
XmlWriter.WriteAttributeString("text",,filedinfo.GetValue(filedinfo).ToString()),;
XmlWriter.WriteEndElement();
}
字段是在類中定義的變量,,字段信息從元數(shù)據(jù)中獲取,,F(xiàn)ieldInfo類發(fā)現(xiàn)字段屬性并提供對字段元數(shù)據(jù)的訪問權(quán)。FieldInfo類沒有公共構(gòu)造函數(shù),,故先用GetType方法獲取全局靜態(tài)類的Type對象(關(guān)于類型聲明的信息),,然后調(diào)用Type對象的GetFields方法來獲取FieldInfo對象。FieldInfo對象通過GetValue方法返回給定字段的值,。
系統(tǒng)支持的語言擴展時,,只要將生成的語言包文檔中各文本控件節(jié)點的text屬性值翻譯成目標語言,即可得到需要的語言包文件,。
2.3 界面文字信息的導(dǎo)入
在創(chuàng)建了語言包文件的基礎(chǔ)上,,如何將程序和語言包文件結(jié)合起來,,成為實現(xiàn)多語言界面的最后一個難題。本文在程序啟動時讀取選擇的XML語言包文件,,將數(shù)據(jù)記錄到內(nèi)存,,窗體加載時進行數(shù)據(jù)填充,替換默認的界面文字,。導(dǎo)入的過程中也使用了反射技術(shù),其方法如下:
?。?)程序啟動時,,打開要讀取的外部XML語言包文件。
?。?)按深度遍歷方法讀取XML文件,。提取所有Form節(jié)點的名稱和標題欄文本屬性值,存入內(nèi)存,。每個Form創(chuàng)建一個窗體信息對象,,存放Framework、TextControl以及UIText組件的文本信息,,多個窗體信息對象之間以標題欄文本為區(qū)分標識,。
(3)所有窗體處理完畢后,,替換全局提示信息文本:創(chuàng)建Globalpromptmsg類的一個實例,,獲取它的類型信息,搜索該實例中與globalpromptmsg節(jié)點下提示信息節(jié)點同名的公開字段,,利用反射機制將對應(yīng)字段的值替換為對應(yīng)節(jié)點的text屬性值,。其程序如下:
Globalpromptmsg gmp=new Globalpromptmsg ();
Type type=gmp.GetType(),;
FieldInfo currfieldinfo = null,;
foreach(XmlNode msgnode in formnode.ChildNodes)
{
currfieldinfo=type.GetField(msgnode.Attributes["name"].Value);
if (currfieldinfo != null)
currfieldinfo.SetValue(currfieldinfo,, msgnode.
Attributes["text"].Value),;
}
通過調(diào)用Type對象的GetField方法來搜索具有指定名稱的公開字段,并將其存入FieldInfo對象,;然后調(diào)用FieldInfo對象的SetValue方法對給定字段值進行修改,。
(4)窗體加載時,,從第2步獲取的數(shù)據(jù)中查找對應(yīng)控件的各項文本屬性信息,,替換掉組件默認的文本,從而實現(xiàn)界面語言的導(dǎo)入,。
2.4 實際界面顯示
以登錄界面為例,,提取出一個簡單的語言為英文的xml文件如圖6所示,。
圖中,Solution節(jié)點代表解決方案,,Native-lan節(jié)點代表顯示的語言種類,,F(xiàn)orm節(jié)點代表窗體,F(xiàn)orm的子節(jié)點textcontrol和uitext分別對應(yīng)窗體需顯示文本的控件和隱含在程序中的文字信息,。提示信息存放在globalpromptmsg節(jié)點下,。每個item節(jié)點都指明了組件的名稱和顯示文本,擴展支持語言時只需修改節(jié)點的Text值,。
本設(shè)計中默認語言是中文簡體,,默認的登錄界面如圖7所示。選擇英文語言包文件時,,程序運行得到的登錄界面如圖8所示,。
本文采用擴展外部XML語言包的方法,在對源程序修改代價最小的情況下實現(xiàn)了對軟件的多語言支持,,語言增加或界面變化時無需重新編譯源程序,,動態(tài)增加或修改語言包文件即可,實現(xiàn)簡單,、擴展性強,、維護成本小,是一個設(shè)計良好的多語言資源實現(xiàn)模型,。在界面語言導(dǎo)入導(dǎo)出時使用了.NET反射技術(shù),、動態(tài)調(diào)用需要的方法和屬性信息,其程序靈活直觀,。本文方法在飛行員飛行品質(zhì)評估系統(tǒng)中得到了成功應(yīng)用,。
參考文獻
[1] 陳傳波,洪慧芳.基于XML的本地化技術(shù)研究[J].計算機工程與科學(xué),,2006,,28(10):95-97.
[2] 司國東. .NET環(huán)境下的一種多語言界面解決方案[J].農(nóng)業(yè)網(wǎng)絡(luò)信息,2007(2):35-36.
[3] 唐勇,,李秀龍.多語言用戶界面的研究與實現(xiàn)[J].計算機應(yīng)用研究,,2002(4):112-113.
[4] 王鋒,魏曉麗,,江開耀,,等.基于XML的C#多語言界面實現(xiàn)[J].計算機工程與設(shè)計,2008,,29(15):4073-4078.