為UI在不同地區顯示不同的語言是產品國際化的一個重要要求。
在SOUI中實現了一套類似QT的多語言翻譯機制:布局XML不需要調整,程序代碼也不需要調整,只需要為不同地區的用戶提供不同的語言翻譯文件即可。
在SOUI中,我們實現了一個使用明文XML的語言翻譯模塊:translator.dll
為了使用多語言翻譯,首先需要准備一個語言翻譯的XML文件。demo中使用的翻譯文件如下:
<?xml version="1.0" encoding="utf-8"?> <language name="ch" guid="{0DAEDE3C-6B94-4a81-9A55-C304FDD69D98}"> <context> <!--沒有上下文的翻譯--> </context> <context name="editmenu"> <message> <source>copy</source> <translation>復制</translation> </message> <message> <source>cut</source> <translation>剪切</translation> </message> <message> <source>paste</source> <translation>粘貼</translation> </message> </context> <context name="messagebox"> <message> <source>ok</source> <translation>確定</translation> </message> <message> <source>cancel</source> <translation>取消</translation> </message> <message> <source>retry</source> <translation>重試</translation> </message> </context> <context name="dlg_main"> <message> <source>close</source> <translation>關閉窗口</translation> </message> </context> </language>
可以看到該XML中有一個language的根節點,該節點有兩個屬性:name和guid,這兩個屬性都是用來標識該翻譯文件的。
在language節點下,有多個context節點,每個context節點有一個name屬性(可以為空),對應一個翻譯上下文。
每一個context下有不同數量的message結點,每個message又有兩個子節點:source 和 translation。
source對應需要翻譯的文字,而translation則對應翻譯后的文字。
要使用這個語言翻譯文件,首先需要從translator.dll中創建一個SOUI::ITranslatorMgr對象,並將該對象交給SOUI::SApplication管理。
再從ItranslatorMgr對象創建SOUI::ITranslator對象,並將Itranslator對象添加到ItranslatorMgr管理的翻譯列表中。
最后還要為ITranslator對象加載翻譯數據源(也就是前面提供的XML文件)。
下面是demo中使用和語言翻譯相關的代碼(見_tWinMain函數)
SApplication *theApp=new SApplication(pRenderFactory,hInstance);//SOUI APP CAutoRefPtr<ITranslatorMgr> transMgr; //多語言翻譯模塊,由translator.dll提供 transLoader.CreateInstance("translator.dll",(IObjRef**)&transMgr);// if(trans) {//加載語言翻譯包 theApp->SetTranslator(transMgr); pugi::xml_document xmlLang; if(theApp->LoadXmlDocment(xmlLang,_T("lang_cn"),_T("translator"))) { CAutoRefPtr<ITranslator> langCN; transMgr->CreateTranslator(&langCN); langCN->Load(&xmlLang.child(L"language"),1);//1=LD_XML transMgr->InstallTranslator(langCN); } }
我們先看一下editmemu的XML:
<editmenu trCtx="editmenu" iconSkin="_skin.sys.icons" itemHeight="26" iconMargin="4" textMargin="8" > <item id="1" icon="3">cut</item> <item id="2" icon="4">copy</item> <item id="3" icon="5">paste</item> <item id="4" >delete</item> <sep/> <item id="5">select all</item> </editmenu>
在這個XML中,根節點有一個屬性trCtx,代表翻譯上下文,對應語言翻譯文件中的context中的name屬性。
在這個menu定義中,所有的菜單項的文字全是英文。其中前面3項:cut, copy and paste在語言翻譯文件中有對應的翻譯項。
下圖為程序運行時edit的右鍵菜單顯示結果:
上面演示的是菜單資源的語言翻譯,布局XML中的文字的翻譯基本一樣,只需要為布局的根結點定義一個翻譯上下文(trCtx)(沒有定義時則從沒有指定name屬性的context里查找翻譯結果)。
可以參見demo的"close”按照的tooltip的翻譯。
不管是菜單XML還是布局XML,它們都是靜態的,經過設計需要使用代碼往UI添加新的文字,同樣也需要翻譯,這個時候如何處理?
其實看一下靜態資源翻譯的代碼就知道,要實現語言翻譯,需要為每一句待翻譯的文字調用一個函數:
SApplication::getSingleton().GetTranslator()->tr(const SStringW & strSrc,const SStringW & strCtx)
第一個參數是等翻譯字符串,第二個參數是翻譯上下文。
考慮到語句太長,系統提供了一個宏:
#define TR(p1,p2) SApplication::getSingleton().GetTranslator()->tr(p1,p2)
這樣用TR就可以實現文字翻譯了。