如何在程序中利用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属性设为“非特定语言”。在“资源”视图中选中相应的对话框节点,再切换到“属性”视图就可以看到这个选项了。如果不设置会出现乱码。

时间: 2024-09-20 22:37:44

如何在程序中利用C++支持多国语言的相关文章

java导出PDF文件,在程序中利用IE浏览器点击下载,是正确的后缀为PDF的文件;而在谷歌浏览器中,点击导出,导出的是后缀为.action的文件

问题描述 java导出PDF文件,在程序中利用IE浏览器点击下载,是正确的后缀为PDF的文件:而在谷歌浏览器中,点击导出,导出的是后缀为.action的文件,貌似是不支持谷歌浏览器啊?那位大哥遇到过啊?!case2:ServletOutputStreamouputStream=getResponse().getOutputStream();getResponse().setContentType("application/pdf");StringfileName2=newString(

WPF应用程序支持多国语言解决方案

原文:WPF应用程序支持多国语言解决方案 促使程序赢得更多客户的最好.最经济的方法是使之支持多国语言,而不是将潜在的客户群限制为全球近70亿人口中的一小部分.本文介绍四种实现WPF应用程序支持多国语言的解决方案. 效果如下图: Language - en-US (英文) Language - zh-CN (中文) 阅读目录 一.使用LocBaml工具 二.使用资源字典文件 三.使用.resx资源文件 四.实现动态切换程序显示语言 附:实现MessageBox支持多语言 一.使用LocBaml工具

ASP.NET中利用模板机制实现多语言

多语言实现方法有许多种, 1.利用VS2005自带的资源文件去实现 2.重写控件,给多语言赋值<myui:Lable key="language" runat=server />; 3.利用模板,内文格式如<input type="button" value="{search}" /> ... 以下利用模板机制实现多语言: 原理是用正则式把所有的{XXX}读取出来,然后替换,再写回到页面. 需要用到的命名空间: using

iOS版谷歌翻译2.0更新 支持49国语言手写识别

&http://www.aliyun.com/zixun/aggregation/37954.html">nbsp;   北京时间9月22日消息,据Dvice网站报道,提到翻译,我们总会想到这样的场景:拿着字典或电子翻译器,手忙脚乱地查着单词.对于非英语专业的朋友来说,翻译工作耗时又费力.在最近发布的谷歌翻译(Google Translate )2.0升级中,新增了手写翻译功能,为需要快速翻译的用户提供了强有力的帮助. 目前,谷歌翻译2.0只支持iOS设备:iPhone.iPad.

手机QQ国际版可即时翻译 支持19国语言互译

虽然从目前的情况来看,承载腾讯国际化的是微信而非手机 QQ,不过最近推出的手机QQ国际版,却在功能上向国际化迈出了一大步.新版的"QQ International"内置了 7 种语言,可以将聊天消息实时翻译成外语,支持包括繁体中文.英语.韩语.日语.法语.阿拉伯语在内的 19 种语言. "QQ International"和普通的手机 QQ 差别不大,但在功能上更加简洁.如不支持贴图表情.不支持游戏和阅读,也没有引入服务中心.不过 QQ International

手机QQ国际版推出即时翻译功能,支持19国语言相互翻译

摘要: 虽然从目前的情况来看,承载腾讯国际化的是微信而非手机QQ,不过最近推出的手机QQ国际版,却在功能上向国际化迈出了一大步.新版的QQ International内置了7种语言,可以将聊天消息实 虽然从目前的情况来看,承载腾讯国际化的是微信而非手机QQ,不过最近推出的手机QQ国际版,却在功能上向国际化迈出了一大步.新版的"QQ International"内置了7种语言,可以将聊天消息实时翻译成外语,支持包括繁体中文.英语.韩语.日语.法语.阿拉伯语在内的19种语言. "

Java Web程序中利用Spring框架返回JSON格式的日期_java

返回Json时格式化日期Date第一步:创建CustomObjectMapper类 /** * 解决SpringMVC使用@ResponseBody返回json时,日期格式默认显示为时间戳的问题.需配合<mvc:message-converters>使用 */ @Component("customObjectMapper") public class CustomObjectMapper extends ObjectMapper { public CustomObjectM

让你的VB程序支持多国语言的切换

程序 以前做过一个vb的小项目,客户需要软件同时能够支持中文和英文,为此写了一个自动语言切换的模块来用,不敢独享,拿来给大家参考一下,如果你有什么改进也可以写信给我..mailto:tonyki@citiz.net 模块 MdlLanMgr.bas :Attribute VB_Name = "ModuleLanMgr"Option Explicit Private Declare Function GetPrivateProfileString& Lib "kerne

C++程序中启动线程的方法_C 语言

 C++11 引入一个全新的线程库,包含启动和管理线程的工具,提供了同步(互斥.锁和原子变量)的方法,我将试图为你介绍这个全新的线程库. 如果你要编译本文中的代码,你至少需要一个支持 C++11 的编译器,我使用的是 GCC 4.6.1,需要使用 -c++0x 或者 -c++11 参数来启用 C++11 的支持. 启动线程 在 C++11 中启动一个线程是非常简单的,你可以使用 std:thread 来创建一个线程实例,创建完会自动启动,只需要给它传递一个要执行函数的指针即可,请看下面这个 He