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