使用VB6资源文件开发多国语言应用攻略

峻墅哥 2016-06-17 02:34:28
加精
VB6被很多程序员认为是一个过气的开发工具,但它实在是微软最经典的开发工具,没有之一!编译出的程序短小精悍,一般就几十K,而且从XP以后的操作系统,均携带其运行时库,只要程序只使用VB的标准控件,连安装都不需要,可以直接运行。所以,不太复杂的GUI程序我都使用VB6开发,速度那怎叫一个快字了得!
最近,我做了一个Mini流图软件,但需要支持多国语言。查了一下网上的资料,方案感觉都很山寨。基本上都是头疼医头,脚疼医脚,没有一个基于系统的全面调理方案。于是,仔细研究了VB6的资源文件体系,发现原来微软早就提供了完美的解决方案,只是中国的程序员大多不习惯这种贵族式的优雅。VC6也使用了这个机制,但GUI做得比VB差几条街,一点儿也不直观,智商低于120的程序员基本无缘此功能,但以后Visual Studio的VC一直继承下来这个机制(虽然表达方式依旧那么烂),不像VB从.net开始抛弃了这一机制,使用了简单粗暴的方法来解决。也许,简单粗暴是这个社会的潮流,但我依然追求优雅。所以以下内容仅适用于对完美有变态追求的同学们。
VB6的资源文件中一般包括字符串、图标、光标、位图和用户定义的字节流,共5种类型的资源,每种资源的实例都有2个属性,一个是资源ID,另一个就是语言ID。就是说,一个资源需要两个ID共同标识。例如:一个资源ID为101的字符串,其语言ID为1028的字符串内容是台湾中文,其语言ID为1033的字符串内容是美式英文,其语言ID为1049的字符串内容是俄文,其语言ID为2052的字符串内容是中国中文,其语言ID为2057的字符串内容是英式英文等等。如图所示是VB6的字符串资源编辑器,很直观吧!开发VC的项目经理太自大!

当程序请求资源时,只需要输入一个资源ID参数,运行时库会根据系统语言ID自动返回对应的资源。对于急功近利的同学们,这些基本就够用了。因为项目经理说做8国语言,大部分程序员不会考虑第9国人民的感受。后面将分享VB6资源文件体系的读取策略以便能优雅的解决第9国人民的问题。
在这之前,得先普及一下Windows内核的多国语言知识。微软从NT开始使用Unicode内核,其好处就是大大降低全球部署的成本,这是微软称霸全球的重要技术支持手段之一。对使用者而言,最直观的好处就是在输出的一个字符串里面可以同时包含多个国家的文字。虽然这种需求很少见,但切换语言这种事在Unicode技术的支持下,那就都不是事!
虽然Windows在发行时,都指明了语言版本,但实际上,任何一个语言的Windows都支持任意微软支持的语言。所以在语言上,Windows有两种级别的语言,一种是安装级(Installed),即系统(System)语言;另一种是支持级(Supported),即用户(User)语言。
一般情况下,系统语言和用户语言是一样的。那二般是个什么情况?举个例子,在一个国际学校,老师是美国人,他当然安装英文版Windows,但他的学生分别是法国人、德国人、中国人、韩国人,就是没有美国人!为了考虑学生的爱国情怀,老师给他们每个人分配一个登录账号,登录后,可以修改控制面板中的地区和语言,以便符合每个学生的习惯。这样,在每个学生的登录会话环境中,系统语言都是英语,用户语言是用户在控制面板中设置的语言。
OK,现在来看看VB6的运行时库对资源请求是如何动作的。当程序请求资源时,只需要输入一个资源ID参数,运行时库首先使用用户语言ID与请求的资源ID所拥有的所有语言ID进行匹配,如果成功,就把请求的资源ID和匹配成功的语言ID对应的资源返回;如果不成功,再使用系统语言ID与请求的资源ID所拥有的所有语言ID进行匹配,如果成功,就把请求的资源ID和匹配成功的语言ID对应的资源返回;如果还不成功,则把请求的资源ID所拥有的所有语言ID中ID值最小的那个对应的资源返回。
看那个例子,为了方便讲解,我加了一个资源ID是99的字符串,里面的内容是语言ID值。如果登录会话环境的用户语言和系统语言都没有匹配上,则返回中文(台湾)的字符串资源,因为1028是所有提供的语言ID中最小的!
说到这里,大家可能很快想到,ID值最小的一定是0,那0是怎么定义的呢?那我们得先看看微软是如何定义语言ID的:
#define MAKELANGID(PrimaryLanguage, SubLanguage) ((((WORD) (SubLanguage)) << 10) | (WORD) (PrimaryLanguage))
意思是语言ID由1个16位的字表示(最多支持65536种语言),其中低10位为主语言ID(最多支持1024种主语言),高6位为子语言ID(每个主语言最多有64种子语言)。
主语言和子语言策略是表达以下情况:如西班牙语,世界上母语是西班牙语的国家有20多个,比英语还多,这个要问那位15世纪才华横溢、精力充沛的伊莎贝拉女王,是她指使哥伦布同学全球殖民而导致我们现在的问题。这20多个国家的西班牙文叫子语言,但他们都属于西班牙语区,这个区称之为主语言。
主语言ID为0被微软称之为中性语言(Neutral),它居然也有子语言,分别是SUBLANG_NEUTRAL(0)、SUBLANG_DEFAULT(1)和SUBLANG_SYS_DEFAULT(2),分别对应3种中性语言Neutral、Neutral Default和Neutral System Default。
所以,前面讲的是个家庭版,现在看看微软的运行时库对资源请求动作的专业版。当程序请求资源时,只需要输入一个资源ID参数,运行时库首先使用用户语言ID与请求的资源ID所拥有的所有语言ID进行匹配,如果成功,就把请求的资源ID和匹配成功的语言ID对应的资源返回;如果不成功,则返回主语言ID为0且子语言ID也为0的资源;如果没找到,再使用系统语言ID与请求的资源ID所拥有的所有语言ID进行匹配,如果成功,就把请求的资源ID和匹配成功的语言ID对应的资源返回;如果还不成功,则把请求的资源ID所拥有的所有语言ID中ID值最小的那个对应的资源返回。
所以,使用VB6多国语言资源文件的最佳实践是:根据软件主要投放语言区域,把那个语言设置为Neutral Default或Neutral System Default(这两个效果一样,如果设置为Neutral,则系统语言将失去一次匹配的机会)。例如:软件准备投放欧洲市场,项目只准备了英、法、德、意4国语言,你可以把英语设置为Neutral Default。当用户语言和系统语言都不是法、德、意时,均使用英语;如果不这么配置,就会使用语言ID最小的那个语言(德语)。显然,在欧洲,认识英文的人应该比认识德文的人多,这样的用户体验更好。
当然,最好的方案还是提供所有语言!其实,也不是很难!关键是工欲善其事,必先利其器!
2001年,有个叫Phil Jollans(http://www.jollans.com)的德国小伙子做了一个叫做World Resource String Editor的VB6插件,可以直接从excel中导入字符串资源!有图有真相:

我就是用这个工具,只需要填写中国(中文)那一列的内容,把文件分发给各个翻译组,再汇总导入,工作之轻松令人发指!什么?西班牙语有20个国家?来吧,我把西班牙(西班牙)那一列复制20列,再把子语言ID一换,轻松支持所有西班牙地区的国家。羽扇纶巾,樯橹灰飞烟灭的感觉!满足需求都弱爆了,预测需求才能立于不败之地。
但预测需求也只是个中级水平,只有引领需求才是最高境界!那什么才是最高境界呢?说到这里,上面已经解决了80%的问题,但只花费了20%的功力,下面的内容解决剩下20%的问题,但需要80%的功力。
其实,微软的整个策略还是对需求了解得不够充分,略显简单粗暴。例如:比利时、瑞士等几个欧洲小国也说法语,它对法国的标准法语进行了一些扩展,就像方言一样,懂比利时法语的人肯定也懂法国的标准法语,这是个非常自然的需求。所以,资源提取的完整最佳策略应该是这样的:
当程序请求资源时,只需要输入一个资源ID参数,运行时库首先使用用户语言ID与请求的资源ID所拥有的所有语言ID进行匹配,如果成功,就把请求的资源ID和匹配成功的语言ID对应的资源返回;如果不成功,就把用户语言ID的主语言ID与请求的资源ID所拥有的所有语言ID的主语言ID进行匹配,如果成功,就把请求的资源ID和匹配成功的主语言ID里面子语言ID最小的那个语言ID对应的资源返回;如果不成功,则返回主语言ID为0且子语言ID也为0的资源;如果没找到,再使用系统语言ID与请求的资源ID所拥有的所有语言ID进行匹配,如果成功,就把请求的资源ID和匹配成功的语言ID对应的资源返回;如果不成功,就把系统语言ID的主语言ID与请求的资源ID所拥有的所有语言ID的主语言ID进行匹配,如果成功,就把请求的资源ID和匹配成功的主语言ID里面子语言ID最小的那个语言ID对应的资源返回;如果还不成功,则把请求的资源ID所拥有的所有语言ID中ID值最小的那个对应的资源返回。我已经竭尽毕生才华企图让阿甘都能看懂了,如果还看不懂,就洗洗睡吧,不求甚解才是真正的幸福。
好吧,终极对决如期而至。这么屌暴天的需求怎么优雅地实现呢?翻阅MSDN上所有关于多国语言资源方面的资料,发现一套修改资源的API:BeginUpdateResource, UpdateResource和EndUpdateResource,可以修改资源的语言ID,但还是太复杂,严重损坏VB6的简单美形象。换一个思路,既然改资源那么累,能不能改用户语言呢?又发现了这么一个函数SetLocaleInfo,可以设置用户语言。哈哈,这样的话,大体思路就出来了:程序启动后,首先调用一个调整函数:这个函数首先获取用户语言,与已有的资源语言比对,如果有完全匹配的,就可以退出了;如果没有完全匹配的,再使用用户语言的主语言与已有的资源语言的主语言比对,如果有匹配的,就用SetLocaleInfo把用户语言设置为匹配了主语言的那个语言ID。这样,资源里只需提供一种主语言的标准语言即可支持使用这个主语言的所有国家。系统语言的修改非常麻烦,要调用一系列API,最致命的是需要重启操作系统,这个基本上就放弃了。但也无大碍,因为用户语言才是最重要的依据,匹配到系统语言上多少有点掩耳盗铃的感觉。
但是,SetLocaleInfo可是真真切切地修改了用户语言,即使你退出前再把原来的用户语言改回去,也会影响到其它在你之后启动的应用,更何况你的程序有可能崩溃,连改回去的机会都没有。
再经过仔细搜索,又发现这么一个函数SetThreadLocale,参数更简单,最重要的是其修改的语言信息只在本线程内起作用,并不真正地修改用户语言。这下大家满足了吧!
有意见,发邮件45672463@qq.com,标题注明图乃大。
...全文
4349 14 打赏 收藏 转发到动态 举报
写回复
用AI写文章
14 条回复
切换为时间正序
请发表友善的回复…
发表回复
大苏打0917 2016-07-08
  • 打赏
  • 举报
回复
厉害厉害厉害
6742 2016-07-07
  • 打赏
  • 举报
回复
留个脚印,学习
a1006695177 2016-07-04
  • 打赏
  • 举报
回复
厉害厉害厉害
duity 2016-07-04
  • 打赏
  • 举报
回复
look look
笨狗先飞 2016-07-01
  • 打赏
  • 举报
回复
百度翻译API调用一下,连打字都省了
gj_zs 2016-07-01
  • 打赏
  • 举报
回复
mark!mark!
ClarkLinus 2016-07-01
  • 打赏
  • 举报
回复
包子混起,哈哈
qq_35479812 2016-07-01
  • 打赏
  • 举报
回复
LOOK LOOK
threenewbee 2016-06-30
  • 打赏
  • 举报
回复
看了下,是用资源实现的。其实默认的vb应用程序向导就支持这个方式,只要勾选其中的多国语言就可以生成这么个框架。
litaoa 2016-06-30
  • 打赏
  • 举报
回复
真的没用过。也没看到过这个功能,楼主用心了。顶一下楼主。
vansoft 2016-06-29
  • 打赏
  • 举报
回复
牛!向楼主学习这种学习的精神。
舉杯邀明月 2016-06-29
  • 打赏
  • 举报
回复
Mark ....... 学习一下。
赵4老师 2016-06-17
  • 打赏
  • 举报
回复
Sisulizer 4 企业版方便地为你的软件提供多种语言支持,三个步骤进行本地化:扫描应用程序和定位文本;使用Sisulizer可视化编辑工具翻译文本;创建本地化软件版本。Sisulizer 能提供对绝大多数应用程序的良好支持,还支持对各种源代码文件、网页的本地化。 Sisulizer 4 中文版 Sisulizer Enterprise Edition 是一款软件本地化(也就是中文汉化)以增加收入的工具。Sisulizer方便地为你的软件提供多种语言支持,三个步骤进行本地化:扫描应用程序和定位文本;使用Sisulizer可视化编辑工具翻译文本;创建本地化软件版本。这个是企业多国语言版本,适用Windows 2000、XP、2003作业平台. Sisulizer Enterprise Edition 方便地为你的软件提供多种语言支持,三个步骤进行本地化:扫描应用程序和定位文本;使用Sisulizer可视化编辑工具翻译文本;创建本地化软件版本。 Sisulizer 能提供对绝大多数应用程序的良好支持,还支持对各种源代码文件、网页的本地化。 Sisulizer Enterprise Edition 的第3版支持新的平台,如Android, FireMonkey, Delphi XE2 64位和改进。 NET支持。它配备了许多新的功能,如翻译记忆编辑器,真正的HTML预览,和几十个内置的更多有用的改进。建议所有的Sisulizer客户更新. Sisulizer Enterprise Edition 是为大企业以及日益全球化的软件公司提供的最佳软件本地化工具。其可广泛的应用于服务器数据库的本地化,Web应用程序的本地化以及使用共享的译码存储系统。通过使用我们提供的命令行工具,用户可以在其软件开发过程中集成Sisulizer的功能。其翻译网格中支持的实时拼写检查能帮助用户的翻译程序创建质量更优的翻译,此外,其提供了许多报表以及验证功能,以帮助用户对其软件进行更佳的本地化工作。Sisulizer Enterprise有着良好的机器翻译服务的用户接口。 Sisulizer Enterprise Edition 功能亮点 -用户只需简单的三步即可完成本地化工作:扫描,翻译以及创建 -瞬间完成本地化更新。用户只需点击”Scan for Changes”按钮,Sisulizer即可显示所有的新的,改变的,或者移除掉的字符串,并且能自动的对既有翻译内容进行重用。能极大的节省日常开支以及翻译成本。 -能对诸如可执行文件或者DLL文件之类的二进制文件进行本地化。无需提供源代码。 -安全性保障。Sisulizer为二进制文件生成本地化版本,而无需对您的原始工程文件作任何修改。 -能翻译为任何人类语言,包括阿拉伯语,中文,希腊语,希伯来语,日语,韩语以及任何用户自定义语言。 -可翻译为可视化文本(所见即所得)。所以所有用户都可对之进行翻译,包括您,您的翻译,或者身在其他国家的合作者,您再也无需被他们带着无尽的问题轰炸了。 -再也无需再次翻译了。Sisulizer能自动记住您曾做过的所有翻译,这极大的节省了时间与金钱。 -能本地化所有的Windows的APP,包括一些当下流行的语言诸如,C/C++, Delphi, Java, 和 VB6, plus Qt, gnuGetText,以及一些Ini文件,比如Pocket PC等。 -用户可以在工程文件处于任何状态(alpha, beta,发布, 较小升级或重大更新)时即对之进行本地化。减少了您用于市场推广的时间以及能更快的使得金回流。 Sisulizer Enterprise Edition 专业化功能 -完全支持.NET应用程序。可本地化C#,VB.NET Winforms, Silverlight以及WPF应用程序。其还支持ResX以及二进制源库进行本地化。 -在原工程中翻译帮助文件。对翻译记录的共享加快了工作进度,减少了该过程中与翻译软件的通讯,时间与经济上均能大幅节省。 -支持本地化的主要格式:本地数据库,HTML,XML文件。 -除了内置的翻译内存以外,其还能与您的翻译软件进行翻译记录交换。 -适用于多种语言的实时的拼写检测器能帮助找出翻译文本以及原始文本中的错误。 -其有着强大用于翻译验证的QA功能,能帮助解决一些翻译过程中的一般性错误,诸如忘记的菜单快捷方式,错误的占位符数目,甚至一些在翻译过程中尚未发生的错误。 -其报表与统计功能使得用户能实时掌握本地化的状态与进度。 Sisulizer 中文企业注册版 Sisulizer Enterprise Edition 企业级功能 -拥有帮助将Sisulizer集成入创建过程的命令行工具。 -拥有用ASP,JAP和PHP语言编写的We

1,066

社区成员

发帖
与我相关
我的任务
社区描述
VB 资源
社区管理员
  • 资源
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧