動態語言切換是不少國際化產品的需求,SOUI以前的版本支持靜態多語言翻譯,經過在程序啓動時設置好語言翻譯模塊,在程序中打開的UI都會自動調用該翻譯模塊進行文字翻譯,可是不支持運行進語言切換。app
最近幾個網友都提到這個需求,仍是決定在SOUI實現一套動態多語言切換機制。ide
先看看運行效果:ui
多語言切換首先須要在語言翻譯模塊管理對象,SOUI中使用一個擴展接口ITranslatorMgr處理。spa
下面是新版本的語言翻譯接口:翻譯
namespace SOUI { /** * @struct ITranslator * @brief 語言翻譯接口 * * Describe */ struct ITranslator : public IObjRef { /** * Load * @brief 從資源中加載語言翻譯數據 * @param LPVOID pData -- 資源指針,具體含義由接口的實現來解釋 * @param UINT uType -- 資源類型,具體含義由接口的實現來解釋 * @return BOOL true-加載成功, false-加載失敗 * * Describe */ virtual BOOL Load(LPVOID pData,UINT uType)=0; /** * name * @brief 獲取翻譯資源的name * @return SOUI::SStringW 翻譯資源的name * * Describe */ virtual SStringW name()=0; /** * guid * @brief 獲取翻譯資源的ID * @return GUID 翻譯資源的ID * * Describe */ virtual GUID guid()=0; /** * tr * @brief 執行翻譯的接口 * @param const SStringW & strSrc -- 原字符串 * @param const SStringW & strCtx -- 翻譯上下文 * @param SStringW & strRet -- 翻譯後的字符串 * @return BOOL true-翻譯成功,false-翻譯失敗 * * Describe */ virtual BOOL tr(const SStringW & strSrc,const SStringW & strCtx,SStringW & strRet)=0; }; /** * @struct ITranslatorMgr * @brief 語言翻譯接口管理器 * * Describe */ struct ITranslatorMgr : public IObjRef { /** * SetLanguage * @brief 設置翻譯模塊當前接受的語言 * @param [in] const SStringW & strLang -- 翻譯語言 * * Describe 自動清除語言和目標語言不一樣的模塊 */ virtual void SetLanguage(const SStringW & strLang) = 0; /** * GetLanguage * @brief 獲取翻譯模塊當前接受的語言 * @return SStringW -- 翻譯語言 * * Describe */ virtual SStringW GetLanguage() const = 0; /** * CreateTranslator * @brief 建立一個語言翻譯對象 * @param [out] ITranslator * * ppTranslator -- 接收語言翻譯對象的指針 * @return BOOL true-成功,false-失敗 * * Describe */ virtual BOOL CreateTranslator(ITranslator ** ppTranslator)=0; /** * InstallTranslator * @brief 向管理器中安裝一個語言翻譯對象 * @param ITranslator * ppTranslator -- 語言翻譯對象 * @return BOOL true-成功,false-失敗 * * Describe */ virtual BOOL InstallTranslator(ITranslator * ppTranslator) =0; /** * UninstallTranslator * @brief 從管理器中卸載一個語言翻譯對象 * @param REFGUID id -- 語言翻譯對象的ID * @return BOOL true-成功,false-失敗 * * Describe */ virtual BOOL UninstallTranslator(REFGUID id) =0; /** * tr * @brief 翻譯字符串 * @param const SStringW & strSrc -- 原字符串 * @param const SStringW & strCtx -- 翻譯上下文 * @return SOUI::SStringW 翻譯後的字符串 * * Describe 調用ITranslator的tr接口執行具體翻譯過程 */ virtual SStringW tr(const SStringW & strSrc,const SStringW & strCtx)=0; }; }
用戶切換UI語言後,使用SDispatchMessage方法向全部SWindow發送UM_SETLANGUAGE消息。
SWindow收到該消息後對窗口中須要作語言翻譯的對象從新翻譯語言後更新顯示。
要在SOUI中使用多語言切換,首先須要在winmain裏設置翻譯模塊: 1 int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE /*hPrevInstance*/, LPTSTR lpstrCmdLine, int /*nCmdShow*/) 2 {
3 HRESULT hRes = OleInitialize(NULL); 4 SASSERT(SUCCEEDED(hRes)); 5 6 int nRet = 0; 7 8 SComMgr *pComMgr = new SComMgr; 9 10 //將程序的運行路徑修改到項目所在目錄所在的目錄 11 TCHAR szCurrentDir[MAX_PATH] = { 0 }; 12 GetModuleFileName(NULL, szCurrentDir, sizeof(szCurrentDir)); 13 LPTSTR lpInsertPos = _tcsrchr(szCurrentDir, _T('\\')); 14 _tcscpy(lpInsertPos + 1, _T("..\\SouiWizard1")); 15 SetCurrentDirectory(szCurrentDir); 16 { 17 BOOL bLoaded=FALSE; 18 CAutoRefPtr<SOUI::IImgDecoderFactory> pImgDecoderFactory; 19 CAutoRefPtr<SOUI::IRenderFactory> pRenderFactory; 20 CAutoRefPtr<ITranslatorMgr> trans; //多語言翻譯模塊,由translator.dll提供 21 22 bLoaded = pComMgr->CreateRender_GDI((IObjRef**)&pRenderFactory); 23 SASSERT_FMT(bLoaded,_T("load interface [render] failed!")); 24 bLoaded=pComMgr->CreateImgDecoder((IObjRef**)&pImgDecoderFactory); 25 SASSERT_FMT(bLoaded,_T("load interface [%s] failed!"),_T("imgdecoder")); 26 bLoaded = pComMgr->CreateTranslator((IObjRef**)&trans); 27 SASSERT_FMT(bLoaded, _T("load interface [%s] failed!"), _T("translator")); 28 29 pRenderFactory->SetImgDecoderFactory(pImgDecoderFactory); 30 SApplication *theApp = new SApplication(pRenderFactory, hInstance); 31 //從DLL加載系統資源 32 HMODULE hModSysResource = LoadLibrary(SYS_NAMED_RESOURCE); 33 if (hModSysResource) 34 { 35 CAutoRefPtr<IResProvider> sysResProvider; 36 CreateResProvider(RES_PE, (IObjRef**)&sysResProvider); 37 sysResProvider->Init((WPARAM)hModSysResource, 0); 38 theApp->LoadSystemNamedResource(sysResProvider); 39 FreeLibrary(hModSysResource); 40 }else 41 { 42 SASSERT(0); 43 } 44 45 CAutoRefPtr<IResProvider> pResProvider; 46 #if (RES_TYPE == 0) 47 CreateResProvider(RES_FILE, (IObjRef**)&pResProvider); 48 if (!pResProvider->Init((LPARAM)_T("uires"), 0)) 49 { 50 SASSERT(0); 51 return 1; 52 } 53 #else 54 CreateResProvider(RES_PE, (IObjRef**)&pResProvider); 55 pResProvider->Init((WPARAM)hInstance, 0); 56 #endif 57 58 theApp->InitXmlNamedID(namedXmlID,ARRAYSIZE(namedXmlID),TRUE); 59 theApp->AddResProvider(pResProvider); 60 61 if (trans) 62 {//加載中文語言翻譯包 63 theApp->SetTranslator(trans); 64 pugi::xml_document xmlLang; 65 if (theApp->LoadXmlDocment(xmlLang, _T("cn"), _T("lang"))) 66 { 67 CAutoRefPtr<ITranslator> langCN; 68 trans->CreateTranslator(&langCN); 69 langCN->Load(&xmlLang.child(L"language"), 1);//1=LD_XML 70 trans->InstallTranslator(langCN);
71 } 72 } 73 // BLOCK: Run application 74 { 75 CMainDlg dlgMain; 76 dlgMain.Create(GetActiveWindow()); 77 dlgMain.SendMessage(WM_INITDIALOG); 78 dlgMain.CenterWindow(dlgMain.m_hWnd); 79 dlgMain.ShowWindow(SW_SHOWNORMAL); 80 nRet = theApp->Run(dlgMain.m_hWnd); 81 } 82 83 delete theApp; 84 } 85 86 delete pComMgr; 87 88 OleUninitialize(); 89 return nRet; 90 }
參見上面紅色代碼。3d
須要切換語言時,以下加載新的翻譯模塊便可:指針
void CMainDlg::OnLanguage(int nID)
{
ITranslatorMgr *pTransMgr = SApplication::getSingletonPtr()->GetTranslator(); bool bCnLang = nID == R.id.lang_cn; pugi::xml_document xmlLang; if (SApplication::getSingletonPtr()->LoadXmlDocment(xmlLang, bCnLang?_T("cn"):_T("en"), _T("lang"))) { CAutoRefPtr<ITranslator> lang; pTransMgr->CreateTranslator(&lang); lang->Load(&xmlLang.child(L"language"), 1);//1=LD_XML pTransMgr->SetLanguage(lang->name()); pTransMgr->InstallTranslator(lang);
SDispatchMessage(UM_SETLANGUAGE,0,0); //soui2.6 新增長的方法。 } }
注: 該功能只在SOUI 2.6+版本支持。code