龙空技术网

Delphi XE编程之多语言支持

IDudo 51

前言:

当前大家对“delphi远程播放控件”大约比较关怀,看官们都需要学习一些“delphi远程播放控件”的相关资讯。那么小编在网络上网罗了一些有关“delphi远程播放控件””的相关资讯,希望你们能喜欢,各位老铁们一起来学习一下吧!

在用Delphi开发软件的时候,会碰到需要支持多语言,这也是很多流行软件支持的特性。在网上搜了很多文章,没有一个能把整个过程讲清楚的,本文将结合实践,把Delphi的多语言支持的方法分享给大家。

多语言支持的第一步,就是收集需要翻译的文本,生成针对各种语言的文本模板。收集翻译文本大部人都会想到用TLang组件,实际上这个组件的功能实在有限,并不能完全的收集我们想要的所有文本,但是Delphi本身也提供了手动收集的方法。

在FMX.Types(Delphi 11.3)单元,存在以下几个函数(过程函数就不去分了,函数叫着顺口):

var  CollectLang, Lang: TStrings;procedure CollectLangStart;begin   ResetLang;    if CollectLang = nil then  begin     CollectLang := TStringList.Create;    // TStringList(CollectLang).Sorted := True;    TStringList(CollectLang).CaseSensitive := True;end;procedure CollectLangFinish;begin    FreeAndNil(CollectLang);end;function CollectLangStrings: TStrings;begin   Result := CollectLang;end;procedure CollectLangSave;begin   if CollectLang <> nil then     CollectLang.SaveToFile(ExtractFilePath(ParamStr(0)) + 'lang.lng');end;

CollectLangStart:启动收集;

CollectLangFinish:停止收集

CollectLangStrings: 返回收集数据

CollectLangSave: 保存收集结果

在进行数据收集之前,还需要一些事情需要我们知道:

所有的TStyledControl对象的继承者都会自动翻译自身的Text和Hint属性,但是也可以通过设置AutoTranslate=False来阻止自动翻译,这可以让我们来设置一些我们不需要翻译的控件不被自动翻译。所有翻译都会调用FMX.Types(Delphi 11.3)单元的Translate函数,函数原型如下:

function Translate(const AText: string): string;var  Idx: Integer;begin  if AText = '' then  begin    Result := '';    Exit;  end;  if Assigned(CustomTranslateProc) then  begin    if CustomTranslateProc(AText) <> '' then      Result := CustomTranslateProc(AText)    else      Result := AText;    Exit;  end;  if CollectLang <> nil then  begin    if CollectLang.IndexOf(AText) < 0 then      CollectLang.Add(AText)  end;  if Lang <> nil then  begin    if not NeedResetLang then    begin      Idx := Lang.IndexOfName(AText);      if Idx >= 0 then        Result := Lang.ValueFromIndex[Idx]      else        Result := AText;    end    else    begin      Idx := IndexOfValueStr(Lang, AText);      if Idx >= 0 then        Result := Lang.Names[Idx]      else        Result := '';      if Result.IsEmpty then        Result := AText;    end;  end  else    Result := AText;end;

通过Translate函数代码我们可以看出,该函数包含了文本收集的功能,所以我们需要进行文本收集,就需要在软件开始收集后,尽可能多的显示(实际上控件只要创建了就可以了)需要翻译的控件所在的界面,显示的越多,收集的信息就越全面。

有了前面的信息,对于不是控件Text和Hint属性的文本,比如一些错误信息等如果需要自动翻译,我们需要在显示消息的地方把错误信息用Translate函数括起来,这样就可以自动翻译我们输出的文本信息,也可以在信息收集的时候把这些信息自动加入收集模板。

收集代码我是这样写的:

procedure TMainForm.FormCreate(Sender: TObject);begin{$IFDEF DEBUG}     CollectLangStart;{$ENDIF}end;procedure TMainForm.FormDestroy(Sender: TObject);  {$IFDEF DEBUG}     CollectLangSave;    CollectLangFinish;  {$ENDIF}end;

生成的模板内容如下:

&ToolsConsoleSearchDebugBookMarkGeneralShortCut The file '%s'has been modified, do you want to save it?

生成的模板就只是一行行的文本,如果要进行翻译,需要每行后面加一个=后面跟翻译内容,比如:

&Tools=工具Console=控制台Search=搜索Debug=调试BookMark=书签General=通用ShortCut=快捷键 The file '%s'has been modified, do you want to save it?=文件'%s'已修改,是否保存?

在这里需要注意的是系统自动收集的文本中带字符引号的文本,比如前面模板中的

The file '%s'has been modified, do you want to save it?

会自动把Pascal字符串中的两个字符引号转换成一个字符引号即''%s''换成了'%s'。

The file '%s'has been modified, do you want to save it?文本在实际使用的时候是如下这样用的:

const   sCloseFileQuery = 'The file ''%s''has been modified, do you want to save it?';

程序中会如下调用:

TDialogService.MessageDialog(format(Translate(sCloseFileQuery),[ExtractFileName(EditorItem.FileName)]),TMsgDlgType.mtConfirmation,[TMsgDlgBtn.mbYes,TMsgDlgBtn.mbNo,TMsgDlgBtn.mbCancel],TMsgDlgBtn.mbYes,0,(procedure(const AResult: TModalResult)begin    ConfirmResult := AResult;end));case ConfirmResult of   mrYes: begin         Result := EditorItem.Save;    end;  mrNo: begin     //Result := True    end;   mrCancel: begin        Result := False;   end; end;end;

为什么要说这个,是因为如果手动添加需要翻译的文本,一定注意把文本中的两个字符引号换成一个字符引号,否则翻译不了.

翻译后的语言文件,还需要注意编码的问题,默认的ANSI编码使用会有问题,最好是保存为UTF8编码保存,在使用时同样用UTF8编码读取.

在为程序添加多语言支持功能之前,还需要知道,Delphi中每种语言都有一个两个字符的ID,比如英语是'en',中文是'zh'.

下面我们为程序添加多语言支持。本来Delphi提供了一个函数,直接从文件中加载语言文件

procedure LoadLangFromFile(const AFileName: string);

但是该函数只能使用默认编码,所以不能直接使用这个函数,不过Delphi还提供了另一个函数

procedure LoadLangFromStrings(const AStr: TStrings);

所以加载语言文件的函数如下:

procedure LoadLocal;var  Lang: String;  LocaleSvc: IFMXLocaleService;begin  Lang := 'en';  if TPlatformServices.Current.SupportsPlatformService(IFMXLocaleService, LocaleSvc) then  begin    Lang := LocaleSvc.GetCurrentLangID;    if Lang='zh' then    begin      if TEncoding.Default.CodePage=936 then        Lang := Lang+'_Simplified'      else        Lang := Lang+'_Traditional'    end;  end;  LoadLocal(Lang);end;procedure LoadLocal(const Lang: String);var  List: TStrings;  FileName: String;begin   if Lang='auto' then      LoadLocalelse if Lang='en' then    ResetLangelsebegin  FileName := TPath.Combine(TVPLUtils.LocalesDir,Lang+'.lng');  if TFile.Exists(FileName) then  begin     List := TStringList.Create;     try       List.LoadFromFile(FileName,TEncoding.UTF8);      LoadLangFromStrings(List);    finally      FreeAndNil(List);    end;   end;  end;end;

ResetLang函数是将所有控件的文本恢复到初始状态,这也是Delphi自身提供的函数。

if TEncoding.Default.CodePage=936 then

这句代码我用来判断是否是中文简体系统,不知道还有没有其他方法来判断。

到这里,Delphi多语言支持的整个过程就实现完了,希望能帮到你.

标签: #delphi远程播放控件