CnPack Forum » CnVCL 组件包 » 试用GNU Gettext 开源多语组件包


2008-9-28 11:00 softyes
试用GNU Gettext 开源多语组件包

尝试过CnPack中的CnMultiLang组件和国外的GNU Gettext组件后,感觉GNU Gettext做多语言要方便些。

这两者都是开源免费的多语言组件,而且都采用语言文件保存的字符串替换的方式,不同的是CnMultiLang采用的是[元件.属性]=[字串]的方式,而GNU Gettext采用的是[旧字串]=[新字串]的方式。

CnMultiLang虽然比较成熟对中文化的支持比较好,而且是以控件的方式出现在组件面板中,可以可视化编辑属性,但是其多语化的方式为[元件.属性]=[字串]的方式,不方便的地方有两点:1、会有很多重复的地方 2、静态字符串,例如对话框、输入框的字符串的多语化非常不方便。

GNU Gettext采用的是字典方式,按照词汇对应。而且,各个细节都非常贴心。安装后,在工程目录文件夹上点右键即可生成字典模板,然后在某个特定语言文件上右键合并,即可智能合并刚生成的模板,字典文件采用通用的PO格式,可以采用通用编辑器编辑(推荐Poedit,很好用)。另外,最贴心的地方就是,对于混杂在代码中的字符串,只要使用一个函数_()将字符串扩起来,再重新生成字典模板即可将其加入翻译字典;对于一些动态生成的按钮、对话框标题等,只要将其加入resourcestring即可。当然,缺点也是有的:1、没有图形化方式编辑,需要自行添加代码(其实没几行)2、对中文化支持不好,需要自行添加代码解决(设置一下全局默认字体大小即可) 3、一词多义的情况不好处理(加空格或者放到新的domain里)

下面说一下GNU Gettext使用中需要注意的个别地方:

下载地址http://dybdahl.dk/dxgettext/

1、 在FormCreate中添加初始化代码
这些代码一般比较固定:
[img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockStart.gif[/img][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedBlock.gif[/img][color=#000]    [/color]...[color=#0800]{Initialazation for locales}[/color][color=#0800][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img]     [/color][color=#0800]//[/color][color=#0800] 设置忽略列表[/color][color=#0800]
[img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/color][color=#000]    TP_GlobalIgnoreClassProperty(TAction,[/color][color=#000]'[/color][color=#000]Category[/color][color=#000]'[/color][color=#000]);
[img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img]    TP_GlobalIgnoreClassProperty(TControl,[/color][color=#000]'[/color][color=#000]HelpKeyword[/color][color=#000]'[/color][color=#000]);
[img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img]    TP_GlobalIgnoreClassProperty(TNotebook,[/color][color=#000]'[/color][color=#000]Pages[/color][color=#000]'[/color][color=#000]);
[img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img]    TP_GlobalIgnoreClassProperty(TControl,[/color][color=#000]'[/color][color=#000]ImeName[/color][color=#000]'[/color][color=#000]);
[img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img]    TP_GlobalIgnoreClass(TFont);
[img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img]     [/color][color=#0800]//[/color][color=#0800] 开始翻译组件[/color][color=#0800]
[img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/color][color=#000]    TranslateComponent(self);[/color]



2、主菜单要加"&"
因为Delphi会自动给主菜单文字前面加一个"&"字符,如果你没有手动加的话,这样会造成主菜单这些单词无法被翻译。
例如:主菜单"File"最好写成"&File",否则生成的字典为“File”,但Delphi会编译时自动将菜单名替换为"&File",这样就无法匹配了。

3、resourcestring
常用的resourcestring举例:
[img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][color=#000]resourcestring
[img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img]    yes[/color][color=#000]=[/color][color=#000]'[/color][color=#000]&Yes[/color][color=#000]'[/color][color=#000];no[/color][color=#000]=[/color][color=#000]'[/color][color=#000]&No[/color][color=#000]'[/color][color=#000];ok[/color][color=#000]=[/color][color=#000]'[/color][color=#000]OK[/color][color=#000]'[/color][color=#000]; [/color][color=#0800]//[/color][color=#0800] 对话框按钮[/color][color=#0800]
[img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/color][color=#000]    warning[/color][color=#000]=[/color][color=#000]'[/color][color=#000]Warning[/color][color=#000]'[/color][color=#000];error[/color][color=#000]=[/color][color=#000]'[/color][color=#000]Error[/color][color=#000]'[/color][color=#000]; [/color][color=#0800]//[/color][color=#0800] 对话框标题[/color]


MessageDlg示例:
[img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][color=#000]    MessageDlg(_([/color][color=#000]'[/color][color=#000]Exit without saving ?[/color][color=#000]'[/color][color=#000]), mtWarning, mbOKCancel,[/color][color=#000]0[/color][color=#000])
[/color]


4、切换语言的方法
[img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][color=#000]procedure TMainForm.mniLangCnClick(Sender: TObject);
[img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img]begin
[img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img]    UseLanguage([/color][color=#000]'[/color][color=#000]zh_CN[/color][color=#000]'[/color][color=#000]);
[img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img]    RetranslateComponent(Self);
[img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img]end;[/color]


对话框文字被截断问题补充上文中介绍的方法,即在FormCreate方法中设置DefFontData.Height属性,经过证实无效。
经考证,其实字符被截断的关键是设置了错误的Charset。例如,简体中文字符应该设置为GB2312_CHARSET,如果设置为ANSI_CHARSET则会计算字符宽度不准确,造成字符被截断的问题。

那么,介绍我现在使用的解决办法,就是当改变语言时自动读取并设置po文件中的字体信息,这种方法需要自己用文本编辑器添加一个自定义Property,例如"Default-Font: Size=9; Charset=GB2312_CHARSET\n"。

具体改写方法如下:

1、在gnugettext.pas文件中找到TGnuGettextInstance.WhenNewLanguage函数,并改写为
[img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][color=#000]procedure TGnuGettextInstance.WhenNewLanguage([/color][color=#00ff]const[/color][color=#000] LanguageID: [/color][color=#00ff]string[/color][color=#000]);
[img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img]var
[img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img]    s:[/color][color=#00ff]string[/color][color=#000];
[img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img]    font:TStrings;
[img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img]    i,code:Integer;
[img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img]begin
[img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img]    [/color][color=#0800]//[/color][color=#0800] This is meant to be empty.[/color][color=#0800]
[img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockStart.gif[/img][img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedBlock.gif[/img][/color][color=#000]    [/color]...[color=#0800]{Read font info from po file, by Zero File}[/color][color=#000]
[img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img]    [/color][color=#0800]//[/color][color=#0800] reset charset first[/color][color=#0800]
[img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/color][color=#000]    DefFontData.Charset:[/color][color=#000]=[/color][color=#000]DEFAULT_CHARSET;
[img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img]    [/color][color=#0800]//[/color][color=#0800]read properties[/color][color=#0800]
[img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img][/color][color=#000]    s :[/color][color=#000]=[/color][color=#000] GetTranslationProperty([/color][color=#000]'[/color][color=#000]Default-Font[/color][color=#000]'[/color][color=#000]);
[img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img]    [/color][color=#00ff]if[/color][color=#000] s [/color][color=#000]=[/color][color=#000] [/color][color=#000]''[/color][color=#000] then Exit;
[img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img]    font:[/color][color=#000]=[/color][color=#000]TStringList.Create;
[img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img]    font.Delimiter:[/color][color=#000]=[/color][color=#000]'[/color][color=#000];[/color][color=#000]'[/color][color=#000];
[img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img]    font.DelimitedText:[/color][color=#000]=[/color][color=#000] s;
[img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img]    [/color][color=#00ff]for[/color][color=#000] i:[/color][color=#000]=[/color][color=#000]0[/color][color=#000] to font.Count[/color][color=#000]-[/color][color=#000]1[/color][color=#000] [/color][color=#00ff]do[/color][color=#000]
[img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img]    begin
[img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img]        s:[/color][color=#000]=[/color][color=#000]LowerCase(font.Names[i]);
[img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img]        [/color][color=#00ff]if[/color][color=#000] [/color][color=#000]'[/color][color=#000]name[/color][color=#000]'[/color][color=#000] [/color][color=#000]=[/color][color=#000] s then
[img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img]            DefFontData.Name:[/color][color=#000]=[/color][color=#000]font.ValueFromIndex[i]
[img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img]        [/color][color=#00ff]else[/color][color=#000] [/color][color=#00ff]if[/color][color=#000] [/color][color=#000]'[/color][color=#000]size[/color][color=#000]'[/color][color=#000] [/color][color=#000]=[/color][color=#000] s then
[img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img]            DefFontData.Height:[/color][color=#000]=[/color][color=#000] [/color][color=#000]-[/color][color=#000]MulDiv(StrToInt(font.ValueFromIndex[i]),
[img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img]                    GetDeviceCaps(GetDC([/color][color=#000]0[/color][color=#000]), LOGPIXELSY), [/color][color=#000]72[/color][color=#000])
[img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img]        [/color][color=#00ff]else[/color][color=#000] [/color][color=#00ff]if[/color][color=#000] [/color][color=#000]'[/color][color=#000]charset[/color][color=#000]'[/color][color=#000] [/color][color=#000]=[/color][color=#000] s then begin
[img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img]            [/color][color=#00ff]if[/color][color=#000] IdentToCharset(font.ValueFromIndex[i],code) then
[img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img]                DefFontData.Charset:[/color][color=#000]=[/color][color=#000] code;
[img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img]        end;
[img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img]    end;
[img]http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif[/img]end;[/color]


2、在每个语言包的po文件中添加一条Property
例如:
简体中文:"Default-Font: Size=9; Charset=GB2312_CHARSET\n"
繁体中文:"Default-Font: Size=9; Charset=CHINESEBIG5_CHARSET\n"

2008-9-28 13:18 Passion
没有字典也就是没有二次替换功能,确实是CnMuiltiLang没有做到的,也是怕把结构弄的太麻烦。

代码中的静态字符串需要手工处理,自行定义成var然后自行书写TranslateString,这部分也没自动代码替换生成功能,主要是代码分析等太复杂了,不容易做,就得依靠开发者自己写了。:L

页: [1]


Powered by Discuz! Archiver 5.0.0  © 2001-2006 Comsenz Inc.