关于DELPHI程序多语言支持的问题.docx
- 文档编号:30714151
- 上传时间:2023-08-19
- 格式:DOCX
- 页数:18
- 大小:25.08KB
关于DELPHI程序多语言支持的问题.docx
《关于DELPHI程序多语言支持的问题.docx》由会员分享,可在线阅读,更多相关《关于DELPHI程序多语言支持的问题.docx(18页珍藏版)》请在冰豆网上搜索。
关于DELPHI程序多语言支持的问题
----------------仅供学习参考----------------
关于DELPHI程序多语言支持的问题
写DELPHI程序,是如何实现繁体化的?
是如何开发英文版的?
是通过外挂语言包吗?
我完整地说一下我的问题:
我写一个DELPHI程序,开发环境是是简体中文版本winxp系统+Delphi7的。
现在想做一个繁体版本以及其他非简体中文版本的出来。
此时遇到这几个问题:
1、在非简体中文系统中均出现乱码或界面文字错位。
2、而且语言包速度太慢了,每次启动要预读一下语言文件进行界面翻译,工程量大的时候明显感到启动速度下降了
3、因为工程量比较大,逐一设置“提示内容”及“界面内容”的语言包比较麻烦,所以不想用ini文件或dll资源库的语言包形式
请问各位DELPHI高手你们是怎么做的?
有没有一劳永逸的方法?
听说DELPHI内置的多国语言功能,有没有用法帮助?
还有没有其他一些好用简单强大的Unicode语言包控件?
---------------------------------------------------------------------
Delphi的多语言是这么用的,但是添加多语言后编译连接速度很慢,有时候10来分钟。
可以把你的Delphi的窗体文件分给翻译来翻译,如果是Delphi7,需要先用Conver.exe来转换为文本格式。
1、Project-NewApplication创建你的中文版软件。
2、Project-Language-Add添加你的语言,比如美国英语(ENU)。
或者File-New-Others-DllWizard
3、保存后生成多个文件夹。
4、Project-BuildAll
5、程序目录下生成和工程文件同名的语言文件:
MyExe.ENU;MyExe.CHN,软件发布需要带这些文件。
6、把软件里面所有字符串定义为资源字符串。
resourcestring
C_AppTitle='xx管理系统';
C_Error='错误';
C_Warning='警告';
7、在软件中用如下代码切换语言:
const
//定义你得多语言:
ENGLISH=(SUBLANG_ENGLISH_USshl10)orLANG_ENGLISH;
CHINESE=(SUBLANG_CHINESE_SIMPLIFIEDshl10)orLANG_CHINESE;
uses
ReInit;
...
ifLoadNewResourceModule(ENGLISH)<>0then
begin
ReInitializeForms();
end;
更多请参考Delphi帮助,里面写得更清楚。
我以前也用INI文件做多语言,感觉挺好用,Delphi带得这个多语言感觉编译起来太慢,而且总需要Build半天。
利用INI文件实现界面无闪烁多语言切换
程序运行时,我们查找当前目录下所有的语言配置文件(*.ini),为了达到这个目的,我编写了如下的函数搜索目录下所有的语言配置文件的文件名,然后将文件名去掉ini扩展名保存返回:
functionTForm1.SearchLanguagePack:
TStrings;
var
ResultStrings:
TStrings;
DosError:
integer;
SearchRec:
TsearchRec;
begin
ResultStrings:
=TStringList.Create;
DosError:
=FindFirst(ExtractFilePath(ParamStr(0))+'*.ini',faAnyFile,SearchRec);
whileDosError=0do
begin
{返回的文件名并去掉末尾的.ini字符}
ResultStrings.Add(ChangeFileExt(SearchRec.Name,''));
DosError:
=FindNext(SearchRec);
end;
FindClose(SearchRec);
Result:
=ResultStrings;
end;
在Form建立的事件中添加代码,将目录下所有的语言文件名加入选择列表框中。
procedureTForm1.FormCreate(Sender:
TObject);
begin
ComboBox1.Items.AddStrings(SearchLanguagePack);
end;
程序的重点在如何切换语言,在ComboBox1的OnChange事件中进行切换操作。
这里我写了SetActiveLanguage过程用于实现这一操作。
procedureTForm1.ComboBox1Change(Sender:
TObject);
begin
SetActiveLanguage(ComboBox1.Text);
end;
其中SetActiveLanguage代码如下:
procedureTForm1.SetActiveLanguage(LanguageName:
string);
const
Translations='Translations';
Messages='Messages';
var
frmComponent:
TComponent;
i:
Integer;
begin
withTInifile.Create(ExtractFilePath(ParamStr(0))+LanguageName+'.ini')do
begin
fori:
=0toComponentCount-1do{遍历Form组件}
begin
frmComponent:
=Components[i];
iffrmComponentisTLabelthen{如果组件为TLabel型则当作TLabel处理,以下同}
begin
(frmComponentasTLabel).Caption:
=
ReadString(Translations,frmComponent.Name
+'.Caption',(frmComponentasTLabel).Caption);
end;
iffrmComponentisTCheckBoxthen
begin
(frmComponentasTCheckBox).Caption:
=
ReadString(Translations,frmComponent.Name
+'.Caption',(frmComponentasTCheckBox).Caption);
end;
iffrmComponentisTButtonthen
begin
(frmComponentasTButton).Caption:
=
ReadString(Translations,frmComponent.Name
+'.Caption',(frmComponentasTButton).Caption);
(frmComponentasTButton).Hint:
=
ReadString(Translations,frmComponent.Name
+'.Hint',(frmComponentasTButton).Hint);
end;
iffrmComponentisTMenuItemthen
begin
(frmComponentasTMenuItem).Caption:
=
ReadString(Translations,frmComponent.Name
+'.Caption',(frmComponentasTMenuItem).Caption);
end;
end;
M1:
=ReadString(Messages,'M1',M1);
end;
end;
在这个过程中,我们遍历了Form中的所有组件,根据他们的类别和组件名动态的从ini配置文件中读出应该显示的语言文字。
用遍历组件的方法比一个一个写出具体的组件维护起来要方便很多,代码的适应性也更强。
其中M1为一个字符串变量,这样提示消息也能切换,比如在Button1的Click事件中
procedureTForm1.Button1Click(Sender:
TObject);
begin
ShowMessage(M1);
end;
就可以根据不同的语言给出不同的提示文字。
好了,整个工程就做完了,你可以运行测试一下,是不是切换迅速而且无闪烁。
Delphi实现多语言界面
关键字:
多语言界面,Delphi,国际化,本地化。
随着Internet在全球的普及,一个软件开发者,开发出来的产品可以随意发布到全球各个角落,然而与此同时,开发出来的产品也面临着一个新的问题:
如何实现各种不同的语言界面,甚至根据最终用户的操作系统的语言版本,自动更改语言界面?
难道为每一个不同的语言编写一个不同的版本?
不,完全没有必要。
Delphi5.0作为一个优秀的快速RAD开发工具,可以很容易地实现国际化支持,因为Delphi5.0内置了对多语言界面的支持。
一个程序,如果需要不同的语言版本,那么应该有一下几点需要注意的地方[]:
1.必须允许你的程序代码能够处理好各种语言字符串,例如如果要中文化,必须能够处理双字节。
2.你必须设计好你的程序界面,以便能够使你的程序界面元素有足够的空间显示语言文字信息。
一般说来,在50个字节以内的英文单词所表达的意思,用其他的语言来描述的话,长度要超过50字节,但中文是一个例外。
特别对于几个字节的英文单词,其他的语言的长度几乎百分之百要超过英文的长度!
因此,必须在控件中留出足够的长度以便在更改语言之后,还能显示全部的语言文字信息。
3.你必须翻译所有的资源。
本文将着重讨论如何用Delphi5.0实现多语言的支持和切换,界面设计和上述要求不在本文讨论范围之内。
要为程序添加语言支持,只要在Delphi主菜单项Project下面选择LanguagesàAdd…即可。
点击之后出现语言向导,读者按照向导进行操作即可。
向导结束之后,会生成一个工程组文件(BPG),最后出现TranslationManager,软件开发者可以在这里翻译所有语言的所有资源,包括字体、位置、文字等等。
说明一下:
你可以随时随地用Project下面的Languages子菜单的功能来添加、删除、修改各种界面元素。
做完上述工作之后,我们现在就差切换语言的代码了。
为了切换语言,大家可以使用下面的一个单元[],单元中提供了两个函数,用来更换语言界面元素,其中LoadNewResourceModule是用来修改文字信息等等,ReinitializeForms用来重新刷新窗体和控件以保证同步。
///文件名:
MaltiLan.pas
unitMaltiLan;
interface
uses
Windows,Messages,SysUtils,Classes,Graphics,Controls,Forms;
procedureReinitializeForms;
functionLoadNewResourceModule(Locale:
LCID):
Longint;
implementation
type
TAsInheritedReader=class(TReader)
Public
procedureReadPrefix(varFlags:
TFilerFlags;varAChildPos:
Integer);Override;
end;
procedureTAsInheritedReader.ReadPrefix(varFlags:
TFilerFlags;varAChildPos:
Integer);
begin
inheritedReadPrefix(Flags,AChildPos);
Include(Flags,ffInherited);
end;
functionSetResourceHInstance(NewInstance:
Longint):
Longint;
var
CurModule:
PLibModule;
begin
CurModule:
=LibModuleList;
Result:
=0;
whileCurModule<>nildo
begin
ifCurModule.Instance=HInstancethen
begin
ifCurModule.ResInstance<>CurModule.Instancethen
FreeLibrary(CurModule.ResInstance);
CurModule.ResInstance:
=NewInstance;
Result:
=NewInstance;
Exit;
end;
CurModule:
=CurModule.Next;
end;
end;
functionLoadNewResourceModule(Locale:
LCID):
Longint;
var
FileName:
array[0..260]ofchar;
P:
PChar;
LocaleName:
array[0..4]ofChar;
NewInst:
Longint;
begin
GetModuleFileName(HInstance,FileName,SizeOf(FileName));
GetLocaleInfo(Locale,LOCALE_SABBREVLANGNAME,LocaleName,SizeOf(LocaleName));
P:
=PChar(@FileName)+lstrlen(FileName);
while(P^<>'.')and(P<>@FileName)doDec(P);
NewInst:
=0;
Result:
=0;
ifP<>@FileNamethen
begin
Inc(P);
ifLocaleName[0]<>#0then
begin
//Thenlookforapotentiallanguage/countrytranslation
lstrcpy(P,LocaleName);
NewInst:
=LoadLibraryEx(FileName,0,LOAD_LIBRARY_AS_DATAFILE);
ifNewInst=0then
begin
//Finallylookforalanguageonlytranslation
LocaleName[2]:
=#0;
lstrcpy(P,LocaleName);
NewInst:
=LoadLibraryEx(FileName,0,LOAD_LIBRARY_AS_DATAFILE);
end;
end;
end;
ifNewInst<>0then
Result:
=SetResourceHInstance(NewInst)
end;
functionInternalReloadComponentRes(constResName:
string;HInst:
THandle;varInstance:
TComponent):
Boolean;
var
HRsrc:
THandle;
ResStream:
TResourceStream;
AsInheritedReader:
TAsInheritedReader;
begin{avoidpossibleEResNotFoundexception}
ifHInst=0thenHInst:
=HInstance;
HRsrc:
=FindResource(HInst,PChar(ResName),RT_RCDATA);
Result:
=HRsrc<>0;
ifnotResultthenExit;
ResStream:
=TResourceStream.Create(HInst,ResName,RT_RCDATA);
try
AsInheritedReader:
=TAsInheritedReader.Create(ResStream,4096);
try
Instance:
=AsInheritedReader.ReadRootComponent(Instance);
finally
AsInheritedReader.Free;
end;
finally
ResStream.Free;
end;
Result:
=True;
end;
functionReloadInheritedComponent(Instance:
TComponent;RootAncestor:
TClass):
Boolean; functionInitComponent(ClassType:
TClass):
Boolean;
begin
Result:
=False;
if(ClassType=TComponent)or(ClassType=RootAncestor)thenExit;
Result:
=InitComponent(ClassType.ClassParent);
Result:
=InternalReloadComponentRes(ClassType.ClassName,FindResourceHInstance(
FindClassHInstance(ClassType)),Instance)orResult;
end;
begin
Result:
=InitComponent(Instance.ClassType);
end;
procedureReinitializeForms;
var
Count:
Integer;
I:
Integer;
Form:
TForm;
begin
Count:
=Screen.FormCount;
forI:
=0toCount-1do
begin
Form:
=Screen.Forms[I];
ReloadInheritedComponent(Form,TForm);
end;
end;
end.
测试程序窗体单元文件如下:
///单元文件名:
unit1.pas
unitUnit1;
interface
uses
Windows,Messages,SysUtils,Classes,Graphics,Controls,Forms,Dialogs,
Menus,MLanTool,ExtCtrls,StdCtrls;
type
TForm1=class(TForm)
MainMenu1:
TMainMenu;
File1:
TMenuItem;
Exit1:
TMenuItem;
Language1:
TMenuItem;
Chese1:
TMenuItem;
English1:
TMenuItem; Button1:
TButton; Memo1:
TMemo; ListBox1:
TListBox;
GroupBox1:
TGroupBox; Panel1:
TPanel; procedureExit1Click(Sender:
TObject);
procedureChese1Click(Sender:
TObject); procedureEnglish1Click(Sender:
TObject);
Private
{Privatedeclarations}
Public
{Publicdeclarations}
end;
var
Form1:
TForm1;
implementation
{$R*.DFM}
const
ENGLISH=(SUBLANG_ENGLISH_USshl10)orLANG_ENGLISH;
CHINESE=(SUBLANG_CHINESE_SIMPLIFIEDshl10)orLANG_CHINESE;
procedureTForm1.Exit1Click(Sender:
TObject);
begin
Close;
end;
procedureTForm1.Chese1Click(Sender:
TObject);
begin
ifLoadNewResourceModule(CHINESE)<>0then
ReinitializeForms;
end;
procedureTForm1.English1Click(Sender:
TObject);
begin
ifLoadNewResourceModule(ENGLISH)<>0then
ReinitializeForms;
end;
end.
如果要自动切换语言,只要在FormCreate事件中添加如下代码即可:
ifLoadNewResourceModule(SysLocale.DefaultLCID)<>0then
ReinitializeForms;
说明一点:
在程序完成的时候,你应该用Luanguages子菜单的UpdateResourcesDLL功能更新所有的窗体和代码,然后用BuildAllProject编译所有的文件,这样才能保证你的程序正常运行。
所有的源代码可以到<
后记:
其实用INI文件也可以实现多语言界面的切换,好处是可以方便大家随时添加不同的语言文件,但是,对于一个大型的程序来说,用INI是不现实的。
用INI实现语言界面的程序,大家可以到<码和测试程序。
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 关于 DELPHI 程序 语言 支持 问题