banner.gif adie's blog
主页 博客 胭脂泪,相留醉,几时重,自是人生长恨水长东
统计
日志总数: 127
评论总数: 123
日志分类
日志归档
最近日志
最近评论
订阅
rss2.gif

atom.gif

google_rss
yc.gif 【技术资料】 阅读 6542 次

C++(VC环境) 轻量级国际化解决方案

2011-06-02 16:02:05

1. 概述

    只适用于非常小的程序当中, 翻译的字符串很少, 而且只能用于非 Unicode 的程序. 

    支持不退出程序动态切换语言, 资源文件中的字符自动翻译等等.

2. 实现过程

    首先我们定义出用于进行翻译的接口,  将一个字符串 ID 翻译为选中语言的字符串. 另外, 由于还需要动态切换语言, 所以还需要一个将语言字符串替换回对应 ID 的方法. 所以接口定义为下面的方式:
  1. class IStrSrc  
  2. {  
  3. public:  
  4.     IStrSrc(void){}  
  5.     virtual ~IStrSrc(void){}  
  6.   
  7. public:  
  8.     virtual const std::string& GetString(const std::string& sid) = 0;  
  9.     virtual const std::string& GetKey(const std::string& value) = 0;  
  10. };  
    现在我们来实现这个接口,  让 CMapString 从 IStrSrc  继承, 并添加一个 std::map<std::string, std::string> 来存储字符串的 ID 和内容.  利用 map 容器提供的方法, 上面的接口很容易实现:

  1. const std::string& CMapString::GetString(const std::string& sid)  
  2. {  
  3.     static const std::string nullstr = "";  
  4.     std::map<std::string, std::string>::iterator iter = m_StrMap.find(sid);  
  5.     return iter != m_StrMap.end() ? iter->second : nullstr;  
  6. }  
  7.   
  8. const std::string& CMapString::GetKey(const std::string& value)  
  9. {  
  10.     static const std::string nullstr = "";  
  11.     std::map<std::string, std::string>::iterator iter = m_StrMap.begin();  
  12.     for(; iter != m_StrMap.end(); ++iter)  
  13.         if(iter->second == value)  
  14.             return iter->first;  
  15.   
  16.     return nullstr;  
  17. }  


   另外, 在这个类中我们还需要初始化 m_StrMap 成员, 设置语言等等操作. 在语言改变时这里提供了一个注册回调的方法, 当其他某个部分使用了另外的国际化方法时, 可以通过回调通知其他模块语言设置被改变. 初始化成员很简单, 只需要将字符串的 ID 和内容放到 map 表中即可. 为了初始化方便,  CMapString 通过重载 () 号操作符让你可以这样进行初始化:

  1. void CMapString::LoadGb2312()  
  2. {  
  3.     (*this)  
  4.     ("OK""确定")  
  5.     ("Cancel""取消")  
  6.     ;  
  7. }  
   有了以上两个类, 我们就可以在程序中使用 GetString 把字符串翻译后再使用了, 但是资源中的字符串翻译还没有完成, 为此我们使用另外一个类 CStrManger 来处理. 它构造的时候需要一个 IStrSrc 指针来完成字符串装换. 它提供了两个方法来为资源中的字符串进行翻译: UpdateControl, UpdateMenus. 通过遍历子窗口转换他们的标题来处理大部分的字符, 另外还对 ComboBox, SysTabControl32 等控件做了处理, 让他们里面的内容可以被翻译. 另外 UnUpdateControl, UnUpdateMenus 提供上述转换的逆转换, 以便在切换语言时能够先恢复再加载其它语言的字符串. 具体实现见源代码.

   最后, 在 StrMagHelp.h 中定义了一个 CStrManger 类的单件, 并提供了一系列的宏来简化使用.

3. 使用方法

   1. 在初始化的时候使用 SETSRCTYPE(CMapString) 来设置 CStrManger 需要的 IStrSrc 指针. 这种设置方法会 new 一个 CMapString 对象给 CStrManger, 并在 CStrManger 销毁的时候销毁这个 new 的对象.
       如果你需要使用 CMapString 的方法, 你可以自己先定义好这个对象, 然后使用 SETSRCOBJ(g_Language) 这种方式来初始化. 这样初始化的对象在 CStrManger  销毁时不会自动销毁.
   2. 在程序中需要用到 const char* 类型的字符串时使用 CSTR(ID) 来转换; 需要 char* 类型时使用 VSTR(ID); 需要 std::string 类型时使用 STDSTR(ID). 如果需要反复使用一个字符串 , 可以通过 DEFSTR(var, ID) 来定义一个 const char* var 变量. 这样可以避免每次使用都进行转换, 提高效率.
   3. 在对话框初始化话的时候使用 UPDATECTRL(hWnd) 和 UPDATEMENU(hMenu) 来翻译资源中的字符处串. 如果是 MFC 的程序, 可以使用更简化的 UPDATECTRLWND 和 UPDATEMENUWND, 他从 this 指针中获取当前窗口和当前窗口的菜单.
   4. 在切换语言时, 首先调用 RENEWCTRL, RENEWMENU, 并将主窗口的句柄作为参数. 然后调用 CMapString 的方法来改变语言, 新语言的字符串加载完成后调用 UPDATECTRL 和 UPDATEMENU 即可.

 

4. 下载源代码

    

▲评论

X 正在回复:
姓 名: 留下更多信息
性 别:
邮 件:
主 页:
Q Q:
来 自:
职 业:
评 论:
验 证:


Valid HTML 4.01 Strict Valid CSS!
Copyleft.A!die Software Studio.ADSS
Power by webmaster@adintr.com