delphi中国际化的几种方案及比较(转)

来源:互联网 发布:开了淘宝店怎么经营 编辑:程序博客网 时间:2024/04/20 11:16

======================================================
注:本文源代码点此下载
======================================================

delphi中国际化的几种方案及比较(转)

随着全球化程度加深,软件越来越像蒲公英,到处飘散、扎根。这其中要解决的是不同语言的显示问题。我们当然希望一套程序,可以不修改代码就可以支持不同的语言,不要去维护很多的版本。

首先要谈到的一个问题是乱码问题,因为delphi

win32到11.x版还是不支持unicode,所以一般使用ansi码,有这样几种情况会显示乱码:

使用的语言文字与系统当前设定的语言不一样;比如简体版qq在繁体操作系统(或简体操作系统的区域设置中“非unicode程序的语言”设定为繁体)就是乱码。即使改变font.charset,某些元件仍然会出现乱码,如statusbar。因此,在越南文版的windows显示越南文,在伊朗文版的windows显示伊朗文,不要在越南文版windows显示伊朗文,在伊朗文版windows显示越南文,这样就能确保没有乱码问题。好在一般这样的错位用法也不多见。

系统没有安装你要显示的语言的语言包;

如果你要保证完全无乱码,必须考虑使用unicode码,使用成套的支持unicode的元件,如tnt,但它在ui变现上比较单一,你不可能不使用别的元件。

言归正传,首先,看看哪些地方的字串需要实现多语言,并来看看各种实现方法的优劣。

1、界面上的元件,如tbutton的caption;

2、主动弹出的消息,如showmessage('are you sure?'),raise

exception.create('error!');

3、例外错误举发的报告信息,如f/0引起的exception;

4、第3方元件包内部的上述字串;

实现多语言的方法很多,列举一二:

1、delphi自带的resource生成工具

此工具把专案的dfm文件里的所有字串以及pas中定义为resourcestring的字串列举出来,按不同的语言编译成不同的resource,专案编译前先选语言,每种语言编译成一个exe。

这个工具使用很不方便,不是一个完整的解决方案,跟borland的midas的demo一样(tclientdataset通过providername连接到remotedatamodule的tdatasetprovider,实际开发erp系统时,谁会放100个tdatasetprovider连接到100个tdataset?),只是一个原理尚通的示范。

首先,由于dfm本身也是资源文件的一部分,因此每次修改都要“update resource

dlls...”,如修改button1为button2,如果你忘了,运行时就会报“找不到资源button1的错误”;提供的字典编辑画面中,出了字串,还有left/top等资料;字典不能重用,在一个模组翻译了,在第2个模组还要再翻译相同的词。

其次,每种语言一个exe/bpl,如果你的系统是package切割,bpl也是每种语言一个,还要小心别把不同语言的bpl组合在了一起,到时候一个画面显示中文,一个显示德文(有一个可能是乱码)就惨了。

再次,在作bpl组装的系统时,第3方元件如果没有提供多语言的方案,你就需要修改第3方元件,但一般我们不这样干,因为第3方元件会随时更新,难道每次人家更新你也再更新人家。

因此,一般都没有人使用delphi本身提供的这个方案(除了作demo)。

2、resource

dll方式

用单独的resourcedll,用loadresstring等函数获得翻译字串,但你要到处写这个函数来一一替换,特别是form上的字串,噢,会累死人。字典可以重用。

3、网上讨论很多的ini文件方式

此方法是写个替换的引擎,在运行时从ini文件读取语言字串来替换画面元件的显示文字。这个方法比第一种进步很多,不需要每种语言编译一个exe了,只要提供不同的ini文件就好;画面修改时如果ini没有同步更新也不会出现致命错误,最多就是某个文字没有转换;引擎也提供了字串转换函数,因此也可以处理主动弹出的消息。这个方法在文件格式上有三种不同的实现:

(1)、[编号]=[字串]

每个字串从1开始编号,1,2,3,4......,很麻烦,代码要修改,当然运行时切换语言没问题。

(2)、[元件.属性]=[字串]

这种实现把元件instance一一对应,用rtti来判断属性,替换很精确,也可以运行时切换语言。不足之处是,略显呆板,多个元件相同的字串会多次列出;没有扩展性,表现tlistview的columns等复杂元件时比较吃力。

(3)、[旧字串]=[新字串]

不管元件的instance,ini是纯粹的语言对照表,或者叫字典,扩展性、运行时切换语言可能在引擎里。不足之处是不能处理一词多义。

总的说来,这种方式有很大进步,但为了用ini文件,大家还要费力的破解64k的限制,更专业的方式是使用自定义的文件格式。

在简单性方面,无疑是这种自定义的转换引擎,[旧字串]=[新字串]的文件格式来得方便,借助字典管理工具,字典文件可以重复使用,也可以提供给专业翻译公司翻译。那么剩下的问题在引擎上,如何方便,最好用户不写一行代码;如何扩展性强,支持任意的第三方元件;如何有弹性,同一个画面有多种语言的文字,同一个词可以转换成不同的意思......

4、给每个元件类继承一个子类,在子类的loaded方法里转换文字。由于要处理的都是叶级元件(虽然tlabel、tpanel都是从tcustomcontrol来,但不能只处理tcustomcontrol),工作量比较大;对旧有程序除了换元件无能为力。

5、为每个元件类注册一个转换函数,引擎遍历container,为每个元件找到血源最近的转换函数,调用这个函数转换这个元件的文字。这样可以不必处理叶结点,只需在恰当的元件层上注册函数;不必改动旧有程序。設計時form上只需要放一個轉換元件,這個元件在loaded后開始掃描form上的元件,從for

i:=0 to componentcount-1或從for i:=0 to

controlcount-1遞歸,找到一個元件就去查找其血緣最近的註冊函數,然後調用這個函數替換其文字。因爲註冊函數是額外加上去的,所以不會動到舊的代碼,對任意第方元件都可以擴展支持,且也不用去修改人家第3方元件的代碼。

我认为第5种方法很优雅,看起来比较干净。用gof的设计模式来套,这属于mediator

pattern(中介者模式)。多年前,我们使用一个叫txpmenu的元件来获得xp风格的界面,也是感觉到它很干净,一个元件就搞定一切,不用tlabel换成tflatlabel,tbutton换成tflatbutton......我记得《程序员》上还有文章专门称赞这个元件。但那个元件没有使用中介者模式,不能很好的扩展对第3方元件的支持。

最后,我们畅想一下,如果我是borland,如何在delphi里完整支援多语言。delphi提供了一个区块定义的关键字“resourcestring”,在这个区块定义的字串常量,编译器会把它编译在exe文件的资源区,运行时用loadstringa这个windows

api来读取,因此有些外部转换工具可以直接从exe文件读取这些资源字串,再写入转换后的字串;内嵌的转换引擎也可以拦截这个api函数来转换文字。但是如果exe里的字串资源化不彻底,就无能为力,这个不彻底恰恰来自delphi的dfm文件,delphi把dfm文件整个作为一项资源放在exe里,其上的字串就没法决定是否要don`t

resource(delphi源码里很多常量字串都有这个提示)了。

如果除了string,widestring,ansistring等等这些数据类型,delphi增加一种数据类型multistring,然后修改vcl元件定义(拜托borland连同unicode一起解决了吧),像tlabel.caption定义成multistring,对multistring类型,有一种专门的处理方法,如类似resourcestring用loadstring

api来处理,每次读取就转换一次,但应该比这个内容更多,比如要传出instance,然后提供一个全局的applicationmulti元件,类似applicationevent,让外面能捕捉到。至于字典,只能外部用户提供(当然可以制定一个标准格式让delphi人都可以共享交换)。

此法看起来可行,但还有个效率问题要考虑,(1)每次读取都转换,对频繁draw的东西效率低;(2)比如一个toolbar有好多的toolbutton,批次更新时一般都会用beginupdate/endupdate,vcl如何告知后代来提高这种效率。(补记:效率看起来不是问题,对多次字串更改导致频繁draw,其实元件自己已经会用beginupdate/endupdate处理,外部不会涉及)

---

本文章使用“国华软件”出品的博客内容离线管理软件multiblogwriter撰写并发布


======================================================
在最后,我邀请大家参加新浪APP,就是新浪免费送大家的一个空间,支持PHP+MySql,免费二级域名,免费域名绑定 这个是我邀请的地址,您通过这个链接注册即为我的好友,并获赠云豆500个,价值5元哦!短网址是http://t.cn/SXOiLh我创建的小站每天访客已经达到2000+了,每天挂广告赚50+元哦,呵呵,饭钱不愁了,\(^o^)/
原创粉丝点击