在SOUI中使用动态多语言切换

动态语言切换是很多国际化产品的需求,SOUI之前的版本支持静态多语言翻译,通过在程序启动时设置好语言翻译模块,在程序中打开的UI都会自动调用该翻译模块进行文字翻译,但是不支持运行进语言切换。

最近几个网友都提到这个需求,还是决定在SOUI实现一套动态多语言切换机制。

先看看运行效果:

多语言切换首先需要在语言翻译模块管理对象,SOUI中使用一个扩展接口ITranslatorMgr处理。

下面是新版本的语言翻译接口:

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 }

参见上面红色代码。

需要切换语言时,如下加载新的翻译模块即可:

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+版本支持。

原文地址:https://www.cnblogs.com/setoutsoft/p/6743006.html