如安在措施中操作C++支持多国语言
本文以emule为例,探讨一下多国语言支持的实现。选择emule,因为它的多国语言支持实现的相当好,可以支持动态切换。并且最要害,它是开源的,可以直接通过源码来研究它的实现技能。
emule是操作动态加载资源DLL来实现多语言切换的,每一个资源DLL中包括了一份对应某一语言的字符串表。在源码的srchybridlang 路径上可以发明一个lang办理方案,个中包括了差不多40个项目,每个项目编译出来都是一个单独的DLL。这些DLL在措施安装时拷贝到指定的目次中。每个DLL内里都是一个大的string table。emule为每一个用到的字符串(约莫为1400多个)都指定了一个牢靠ID,在差异的DLL中这个ID对应了这个字符串的差异语言的翻译版本。这样每当需要这个字串时就通过ID去获取,在其时措施加载的某一特定语言的DLL,就可以取到相应语言的字串。
英文版本的string table编译在主EXE文件中,这样当某一语言不支持,或DLL文件加载失败时还可以利用英语版本。
下面我们就看看详细的实现。
主要实现代码在I18n.cpp文件中。进口函数是 void CPreferences::SetLanguage() ,这个函数在在 void CPreferences::LoadPreferences() 函数中被挪用,即载入了措施的各类选项后。当措施第一次运行时,在选项文件(即 preferences.ini)中没有内容,SetLanguage函数会按照系统的当地语言配置来加载对应的语言DLL资源,所以我们第一次安装后就是中文,无需配置。这一点我们后头会说到。
别的在 BOOL CPPgGeneral::OnApply() 中也挪用了该函数,即用户在“选项”窗口中改变了语言选择后。
在 void CPreferences::SetLanguage() 函数中,首先挪用了 static void InitLanguages(const CString& rstrLangDir, bool bReInit = false) 函数。这个函数主要是通过遍历“语言”目次(即我们前面说地的,专门用于存放各类语言版本DLL的目次),来初始化静态“语言表” (_aLanguages),这是个静态数组,个中的每一项对应一种支持的语言。凡能找到相应DLL文件的,就在表中标志该语言为支持。
然后挪用 static bool LoadLangLib(const CString& rstrLangDir, LANGID lid) 来载入相应的语言DLL。这个函数较量简朴,通过查“语言表”(_aLanguages),假如要载入的语言是支持的,就加载相应的DLL文件,并将DLL模块句柄存到_hLangDLL中,这也是一个静态变量。我们可以看到假如是英语,是不需要加载的,直接用EXE模块中的资源字符串表。
假如挪用LoadLangLib文件加载指定的语言失败,措施会实验判定当地系统的语言集,并加载对应的语言,假如加载也失败就利用英语。
语言文件加载乐成后,措施会实验从中加载一个字串,假如失败,说明大概DLL文件损坏,则再重设语言为英语。英语字串是内置在EXE文件中的,所以是最靠得住的。
至此,加载乐成,句柄生存在_hLangDLL静态变量中。
最后在需要字符串的处所措施通过 CString GetResString(UINT uStringID, WORD wLanguageID) 或 CString GetResString(UINT uStringID) 函数加载相应的字符串。这个函数的成果很简朴,就是从_hLangDLL指定的模块中加载字符串资源。假如_hLangDLL为 NULL就是从当前模块加载,我们前面已经看到了,假如利用英语这个变量的值就是NULL。
在emule的源码中,险些每个对话框都实现了一个Localize(void)函数,这个函数就是通过挪用GetResString来配置对话框上所有控件的文字。在 BOOL CPPgGeneral::OnApply() 函数中我们可以看到,在挪用CPreferences::SetLanguage函数切换了语言后,会依次挪用对话框和窗口的Localize(void)函数,从头配置UI的文字内容。
最后留意一点,假如你想让应用支持多语言,在设计对话框时要把对话框的Language属性设为“非特定语言”。在“资源”视图中选中相应的对话框节点,再切换到“属性”视图就可以看到这个选项了。假如不配置会呈现乱码。