張 鵬,陳景光,胡選仲,于文學(xué)
(中機(jī)試驗(yàn)裝備股份有限公司,吉林 長(zhǎng)春 130103)
工業(yè)自動(dòng)化控制系統(tǒng)具有提高效率、節(jié)能降耗、節(jié)省人力成本、促進(jìn)產(chǎn)業(yè)升級(jí)的明顯效果,其發(fā)展?jié)摿薮蟆9I(yè)自動(dòng)化控制系統(tǒng)可大致劃分為硬件系統(tǒng)與軟件系統(tǒng),其中,硬件系統(tǒng)負(fù)責(zé)動(dòng)作命令實(shí)際執(zhí)行,軟件系統(tǒng)主要負(fù)責(zé)數(shù)據(jù)計(jì)算分析及與使用者之間的人機(jī)交互。智能化的人機(jī)交互是自動(dòng)化設(shè)備被市場(chǎng)認(rèn)可的關(guān)鍵。
隨著我國自主研發(fā)的自動(dòng)化控制設(shè)備越來越多地出口到不同的國家,測(cè)控系統(tǒng)軟件人機(jī)交互語言轉(zhuǎn)化工作日益繁重,且擁有龐大多元化的國際市場(chǎng)需求。打破出口設(shè)備的不同國家語言交互障礙,提高軟件開發(fā)效率,縮小我國工業(yè)自動(dòng)化控制與歐美等發(fā)達(dá)國家的差距,對(duì)提升我國工業(yè)自動(dòng)化技術(shù)水平及國際市場(chǎng)競(jìng)爭(zhēng)力意義重大[1]。
開發(fā)軟件所需的計(jì)算機(jī)硬件和操作系統(tǒng)要求如下:
(1)計(jì)算機(jī)硬件:微型計(jì)算機(jī);
(2)操作系統(tǒng):Windows 7及以上版本;
(3)開發(fā)工具:Microsoft Visual Studio 2017、WPF;
(4)開發(fā)語言:.NET/C#;
(5)使用控件:DevExpress最新版本;
(6)語言工具:GNU Gettext+Poedit。
WPF是微軟新一代圖形系統(tǒng),運(yùn)行在.NET Framework 3.0及以上版本,為用戶界面、2D/3D圖形、文檔和媒體提供了統(tǒng)一的描述和操作方法。
DevExpress全稱Developer Express,DevExpress控件以界面美觀和功能強(qiáng)大著稱,此控件中有大量的示例和幫助開發(fā)的文檔,能夠讓開發(fā)人員快速入手。DevExpress控件已廣泛應(yīng)用于項(xiàng)目進(jìn)程監(jiān)督、企業(yè)管理、成本管控、生產(chǎn)控制等軟件中。
開發(fā)框架采用GNU Gettext+Poedit的方式實(shí)現(xiàn)多語言管理。
i18n源自英文單詞internationalization,其首末字符為i和n,18為中間的字符數(shù),是國際化的簡(jiǎn)稱。L10N為資源本地化,全稱為L(zhǎng)ocalization,因首字母L與末字母N之間共10個(gè)字母。資源本地化就是讓軟件產(chǎn)品使用當(dāng)?shù)氐沫h(huán)境,如語言、文化、使用習(xí)慣等,一般涉及到具體國家的語言文件,以L10N表示,而多國語言相關(guān)的解決方案以i18n表示[4]。
GNU Gettext是軟件國際化的解決方案之一,類似的還有IBM的ICU4C,但I(xiàn)CU4C比較龐大。GNU Gettext最早使用在Linux上,現(xiàn)已支持全面Windows平臺(tái)[5]。
Poedit依賴GNU Gettext,實(shí)現(xiàn)了圖形化的操作。和普通翻譯相比,不需要再手動(dòng)輸入Key,Poedit可自動(dòng)進(jìn)入源文件,根據(jù)一定的規(guī)則提取key。Poedit工具界面如圖1所示。
圖1 Poedit工具界面
例如,可以將_(“”)中包含的內(nèi)容搜索出來形成Key,并可通過Poedit界面工具進(jìn)行翻譯。同時(shí),Poedit還提供輔助翻譯功能。Poedit工具翻譯搜索界面如圖2所示。
圖2 Poedit工具翻譯搜索界面列表
GNU Gettext+Poedit的解決方案真正意義上實(shí)現(xiàn)了編碼與翻譯分離,翻譯過程中不需要修改源代碼,只需要將MO結(jié)果文件修改到程序指定位置,程序啟動(dòng)時(shí)將自動(dòng)獲取新的翻譯信息。開發(fā)人員通過VS代碼編寫工具編寫代碼,提供給Poedit工具進(jìn)行代碼查詢,并生成執(zhí)行程序。Poedit對(duì)代碼進(jìn)行遍歷查詢,按照一定的規(guī)則搜索需要翻譯的代碼,形成PO文件。PO文件以Key-Value的形式展示給翻譯人員,翻譯人員只需要使用Poedit對(duì)指定的PO文件進(jìn)行翻譯,將Key對(duì)應(yīng)的Value填寫正確的翻譯。最后通過Poedit翻譯生成MO文件,再將MO文件提供給執(zhí)行程序使用[4,5]。翻譯轉(zhuǎn)化架構(gòu)如圖3所示。
圖3 編碼與翻譯轉(zhuǎn)化架構(gòu)
多語言幫助工具存放在EVAF.Framework.Core中,包括LNG類和GettextExtension類。LNG類聲明:
public static class LNG //類聲明
{
private static Catalog _currentCatalog;
public static string _(string key)
{
try
保時(shí)捷是最后登場(chǎng)的一員。單從紐博格林北環(huán)的圈速排名來看,它必將在本場(chǎng)測(cè)試中創(chuàng)造紀(jì)錄。但常規(guī)道路不同于賽道,我們對(duì)911 GT2 RS車主能否在日常生活中觸及這輛保時(shí)捷的極限心存疑慮。但本次測(cè)試打消了我們的顧慮—保時(shí)捷車主完全可以將這輛跑車推向極限,但前提是改變自己的駕駛風(fēng)格并能適應(yīng)后置后驅(qū)的車輛布局。如何在強(qiáng)大的制動(dòng)力和牽引力的幫助下保持自若與從容,同樣是駕駛者必須掌握的能力。
{
if (_currentCatalog == null)
{
return key;
}
return _currentCatalog.GetString(key);
}
catch (Exception e)
{
Console.WriteLine(e);
}
return key;
}
}
LNG類重寫了下劃線“_”操作,用于在CS類中代碼翻譯的幫助,GettextExtension類用于對(duì)xaml中代碼翻譯的幫助。GettextExtension類聲明中的關(guān)鍵變量與函數(shù):
public string Value //實(shí)現(xiàn)方法,通過上面的Key就能成功地找到對(duì)應(yīng)內(nèi)容
{
get
{
if (!string.IsNullOrEmpty(Key))
{
return LNG._(Key);
}
return _value;
}
set
{
_value = value;
}
}
每處標(biāo)記是通過調(diào)用ProvideValue方法來實(shí)現(xiàn)在運(yùn)行時(shí)使用IServiceProvider,然后再通過查詢此IserviceProvider服務(wù)內(nèi)容來獲取傳遞信息。
XAML處理器在處理具有標(biāo)記的類型節(jié)點(diǎn)和成員值時(shí),會(huì)直接調(diào)用ProvideValue方法,從而實(shí)現(xiàn)語言的互相轉(zhuǎn)化。
public override object ProvideValue(IServiceProvider supplier)
{
var TempSupplier = supplier.GetService(typeof(IProvideValueTarget)) as IProvideValueTarget;
if (TempSupplier!= null) //判讀是否為空,如果不為空
{
var temp1 = TempSupplier.TargetObject as Setter;
if (temp1!= null) //判讀是否為空
{
return new Binding("Value") { Source = this, Mode = BindingMode.OneWay };
}
}
Else //判讀是否為空,如果為空
{
return new Binding("Value") { Source = this, Mode = BindingMode.OneWay };
}
var temp2 = new Binding("Value") { Source = this, Mode = BindingMode.OneWay };
return temp2.ProvideValue(supplier);
}
語言改變進(jìn)入觸發(fā)事件,每次打開軟件初始化的時(shí)候,都會(huì)自動(dòng)綁定到已經(jīng)定義好全局的GlobalClass.LanguageChangeEvent事件。
private void Language_Event(object sender, EventArgs e)
{
NotifyValueChanged();
}
確定翻譯位置。如圖4所示,需要翻譯的位置為窗口標(biāo)題“測(cè)試窗口”,測(cè)試按鈕“發(fā)送”。
圖4 軟件前端WPF界面
增加引用:
xmlns:multiLanguage="clr-namespace:EVAF.Framework.Core.MultiLanguage;assembly=EVAF.Framework.Core"
修改Title為Title="{multiLanguage:Gettext 測(cè)試窗口}",修改Button的Content為Content="{multiLanguage:Gettext 發(fā)送}"。
其中,multiLanguage:Gettext為翻譯標(biāo)識(shí),其后內(nèi)容為需要翻譯的內(nèi)容。
代碼修改前后對(duì)比如圖5所示。
圖5 代碼修改前后對(duì)比
multiLanguage:Gettext中multiLanguage為引用的縮寫,在本例中為multiLanguage。該縮寫智能修改為L(zhǎng)NG和multiLanguage,為方便后面的工具使用。
如果需要修改為L(zhǎng)NG,則需將引用修改為:
xmlns:LNG="clr-namespace:EVAF.Framework.Core.MultiLanguage;assembly=EVAF.Framework.Core"
確定翻譯位置,需要對(duì)圖6中彈出消息進(jìn)行翻譯。修改CS類中代碼,需引用EVAF.Framework.Core.MultiLanguage,同時(shí),將MessageBox中需要彈出的代碼加上LNG._(" ")即可。
圖6 彈出對(duì)話框消息翻譯
打開POEdit程序,按步驟提示生成PO文件,將PO文件生成在工程目錄的Languages目錄下(主要方便管理),也可以放在其他自定義位置。點(diǎn)擊保存后,在Languages文件夾中包含一個(gè)en_US.po文件(可雙擊打開)。源關(guān)鍵字用于匹配需要翻譯的字符串,采用下劃線、括號(hào)與雙引號(hào)的方式_(“”),因此輸入額外關(guān)鍵字為下劃線“_”。上面只有CS里面下劃線括號(hào)_(“”)包含的字符,但是XAML中不能出現(xiàn)這樣的描述,需要運(yùn)行SearchXMAL.exe工具。翻譯結(jié)果視圖界面如圖7所示。
圖7 Poedit翻譯結(jié)果
在Debug目錄下創(chuàng)建一個(gè)Languages文件夾,并在Languages文件夾中創(chuàng)建一個(gè)“en-US”文件夾,將生成的MO文件拷貝到該文件夾中。en-US中可以有多個(gè)MO文件,支持框架、模塊為獨(dú)立的MO文件,以實(shí)現(xiàn)多種語言的互相切換。
void App_Startup(object sender, StartupEventArgs e) //程序啟動(dòng)入口
{
LNG.ChangeLanguage("en-us");//導(dǎo)入多語言開發(fā)包
Process proc = Process.GetCurrentProcess();
if (Process.GetProcessesByName(proc.ProcessName).Length > 1)
{
MessageBox.Show(LNG._("應(yīng)用程序?qū)嵗褑?dòng)!"), LNG._("提示");
Application.Current.Shutdown();
return;
}
}
程序運(yùn)行效果示意圖界面如圖8所示。
圖8 多語言切換運(yùn)行效果
本文利用GNU Gettext+Poedit框架結(jié)構(gòu),在無需修改原始代碼的基礎(chǔ)上,可自由切換多國語言,實(shí)現(xiàn)編碼與翻譯分離,提高了二次開發(fā)的效率,使自動(dòng)化人才更好地投入到高精尖領(lǐng)域,打破自動(dòng)測(cè)控系統(tǒng)國際化語言交流障礙,提高了產(chǎn)品的國際市場(chǎng)競(jìng)爭(zhēng)力。