国际化编程的注意点天气: 时间:2005-04-18 15:23:32 1.字符集(CharSet) 要支持国际化,最好的方案是支持Unicode;非Unicode也可以支持国际化,但是有小许的缺失。 Unicode的好处,同一Unicode编码下同一编码在不同区域和语言设置下都一致,且可同时显示或编辑多国语言文字[必须输入法支持,如微软拼音输入法支持Unicode,而智能ABC则不支持,个人认为拼音加加新版本使用.net做开发平台也有这个因素在]。 在大部分情况下,ANSI+CodePage就可以做到本地化,只有在涉及到Unicode定义到而Active CodePage(ACP)未定义的内容时才会有问题。 Win9x不能完整支持Unicode,只支持ANSI+CodePage;WinNT4以上同一内核系统支持Unicode(unicode16,UCS2),也支持ANSI+CodePage;LINUX支持Unicode(unicode32,UCS4-UCS2的超集),似乎需要通过加载相关模块支持。 代码页定义文件在%SYSTEM%下的c_*.nls中,如简体中文的代码页文件在2000/XP等OS下的文件是c_936.nls。 VCL几乎不支持Unicode;CLX支持Unicode,但DBExpress等支持不好;VCL.net支持。ADO与ADO.net支持Unicode。(VCL只是定义了WideString,WideChar等支持Unicode,且连最基本的SysUtils单元提供的WideUpper等函数在ANSI环境下运行都会崩溃。) VCL是基于ANSI+CodePage的,基于MBCS(SBCS混合DBCS)。 因为VCL对Unicode的支持不好,所以几乎所有的第三方组件也不支持Unicode;甚至很多第三方的组件都不支持MBCS。 Delphi的unicode库有: ELDOS的elpack,现已被LMD购买。 Delphi-JEDI的JCL,开源。 Delphi-Gems的unicode library,开源。 TNT组件tntcontrols,开源。 另外还有个别组件支持Unicode,如Delphi-Gems的VirtualTree等。 D9(Delphi 2005)等内部使用的是TWideControl,也是支持Unicode的,但是不随VCL发布。 使用MFC等开发程序时一般都采用编辑两套程序的方法来同时支持ANSI与Unicode;如果定义了编译器指示字UNICODE则开发出来的程序是Unicode版本,否则是ANSI版本的,Unicode版本在ANSI操作系统下可能会无法正常运行(基本的CSTRING类不支持ANSI的OS上兼容Unicode代码)。 基于VCL的程序惨得多,VCL根本没有提供这样的方式,所以VCL的程序过渡到Unicode比较复杂。 2.使用Unicode的资源 Delphi中无法直接正确使用unicode的资源。 有两种方法使用unicode资源: 1. 编写rc文件编译为res,再链接进exe或dll等等二进制文件中;然后代码中使用LoadStringW等API函数获取。(rc文件的格式:STRINGTABLE) 2. 引入tnt类库,在程序执行前运行tntsystem.InstallTntSystemUpdate([tsWideResourceStrings]);然后就可以使用resourcestring了。 3.国际化支持还需要注意的方面 1. 定义快捷键时使用标准美式键盘才有的按键。[只有这些按键才基本上是通用的,但是符号之类的也不是通用的,所以建议只有标准的字母和功能键作快捷键] 2. 大多数的语言翻译到其他语言时长度都比较英语要长,所以要注意界面布局留有足够的翻译空间(汉语是少数平均长度小于英语的语言)。 3. 最好能够使用区域设置显示,但在存储时最好不要带入区域设置格式化后的内容。 4. 图标等设计时需要注意尊重各国习惯,尽量少涉及到宗教等等内容(如猪牛,某些抽象的符号等等)。 5. 默认的CodePage和IME设定;最好不要在组件持久化中带入IME信息,除非必须这么做。 其他: 1.关于ANSI版本的程序本地化 一般情况下基于VCL的程序都应该支持本地化。如果不支持,我认为不是因为ANSI与Unicode的问题,而是因为控件不能正确处理MBCS的原因引起的。支持MBCS并不是象网上一些人所用的方法来判断,而要依据ANSI+CodePage来处理。虽然很多情况下似乎他们的方法是正确的,但那是因为大部分远东语言的代码页都使用了c1控制码+ASCII来表示DBCS的;但是还是会有一些细节差别的。 2.关于已有程序从ANSI转移到Unicode的困难 1.数据库的设定[Oracle:nvarchar2代替varchar2;MSSQL:nvarchar代替varchar(MSSQL还有一些其他的字段也分Unicode版本与ANSI版本)] 2.标准VCL组件(尤其是DB,类库等等:TDataSet,TField,string,TStrings…) 3.第三方组件(MemTable,dxGrid等等) 4.界面设置(如因为2,3两点原因而不完全过渡到Unicode时TCustomEdit.MaxLength;如果设置了数据库的双倍长度则英文出错,不然,则DBCS出错) 5.如果照顾到系统兼容性,还需要注意RTL库和Win32API的兼容性 6.IME的兼容性,在处理Windows消息时需要注意一些TextMessage和IME消息(WM_IME_CHAR,WM_GETTEXTLENGTH等等) 7.编写自定义组件时需要额外关注很多Unicode相关的琐节 8.即使代码支持了,但是Delphi的IDE也不能完全支持,还需要通过很多复杂的方法才有可能真正使IDE也支持(而且delphi7的编译器也只支持utf8,不支持unicode) 3.其他 XP中引入了theme(style),也就是新的ComCtrls,一旦程序支持了theme,就要小心一些向系统获取的信息,如TCustomEdit.SelLength,TCustomEdit.SelStart等等,这些信息的返回值与不支持theme时的返回值将会有差别[因为支持theme的window是comctrls6版本的组件,内部是使用Unicode方式工作的]。 设计窗体时注意字体的设置,如果不小心使用了中文字体等非英文环境下的字体,则可能程序的窗体在中文环境下与英文环境下的表现不一样(Windows无法评估未知窗体的TextHeigh,也无法找到匹配的字体)。 Windows选择最匹配字体的方法在不同版本中也有不一样,典型的是VCLForm用默认字体显示的中文在9x和2000/XP下显示的不一致[9x下字体很难看]。