Translations / i18n / localizations for programs/zh CN

From Free Pascal wiki
Jump to navigationJump to search

Deutsch (de) English (en) español (es) français (fr) 日本語 (ja) 한국어 (ko) polski (pl) português (pt) русский (ru) 中文(中国大陆) (zh_CN)

本文讲解程序如何为不同语言(如英语、中文、德语、芬兰语、意大利语等)选用不同的字符串。

  • i18n国际化的缩写(单词 internationalization 的 i 和 n 中间有18个字符)
  • l10n本地化的缩写(单词 localization 的 l 和 n 中间有10个字符)

i18n 快速入门

本快速指南将带领大家开始翻译历程,并快速完成任务。并请参阅语言代码页双向文本模式

敬请了解,世界上使用最多的语言是:

  • 1 - 汉语:超过14亿人的母语。
  • 2 - 西班牙语:西班牙语位居第二,大约在30个国家使用。
  • 3 - 英语:全球有3.35亿人使用,约占世界人口的5%。(以英语为第二语言的不计入)
  • 4 - 印地语:超过2.6亿人使用。
  • 5 - 阿拉伯语:在全球近60个国家使用。
  • 6 - 葡萄牙语:巴西人口超过2亿,葡萄牙人口略超过1000万。
  • 7 - 孟加拉语:孟加拉国(人口1.55亿)的主要语言,也是印度的官方语言之一。
  • 8 - 俄语和日语。

poedit

最著名的翻译工具是名为 poedit 的程序。Poedit 供翻译人员使用,可输出 PO 和 MO 两种格式的文件。

窗体的翻译

如果保存窗体时启用了 i18n 选项,就会生成一个.lrj文件,用于创建最终的 .po 文件。因此非常重要的一点就是,版本管理系统要将 .po 文件与源代码一起纳入,不要加入忽略列表(如 .gitignore)中,否则翻译将无法继续。

资源字符串的翻译

以下方式可在单元文件中存放资源字符串:

resourcestring
  Caption1 = 'Some text';
  HelloWorld1 = 'Hello World';

资源字符串类似于普通字符串常量,也就是可以赋值给任何字符串:

Label1.Caption := HelloWorld1;

编译为 .po 文件

在 Lazarus IDE 中启用 i18n 后,资源字符串会编译成 .po 文件。可在菜单“项目>项目选项>i18n”中启用。重新编译时,.po 文件会被更新。存储 .po 文件的目录可以自行选择,建议使用“po_files”目录。

建议将默认翻译文件设为英语或应用的默认语言,因为在找不到其他翻译文件时会加载默认翻译文件。

有了“project1.po”文件之后,复制粘贴并重命名为“project1.es.po”或某个语言代码。现在就有了两个语言文件:英语和西班牙语。然后就得将文件发给翻译人员进行翻译。

现在的目录结构将如下所示:

project1\po_files\
project1\po_files\project1.po
project1\po_files\project1.es.po

将 .po 文件转换为 .mo 文件

.po 文件翻译完成后,为了加快加载速度,需要编译为 .mo 文件,因为 .mo 是二进制格式。用 Poedit 即可完成,在“文件>编译为.mo”菜单中。

请注意,在关于翻译的其他事项中,介绍了 Lazarus 应用程序如何定位语言文件。

自动转换语言

将转换好的 .mo 文件放入可执行文件所在的“locale”或“languages”目录中,引用单元“DefaultTranslator”即可完成翻译过程。语言将自动进行转换。

uses
  DefaultTranslator;

仅需在“locale”或“languages”目录中发布 .mo 文件即可,因为 .po 文件仅用于翻译和编译为 .mo 文件。

现在项目的目录结构将如下所示:

project1\project1.exe
project1\locale\
project1\locale\project1.mo
project1\locale\project1.es.mo

语言转换测试

一切就绪后,需要测试每种语言的翻译能否在应用中正常显示。自动转换功能有助于对每种语言进行快速测试。

运行应用的命令行参数中必须带上“--lang”参数,后跟所需的语言代码。

若要测试西班牙语的翻译文件,则运行如下:

project1.exe --lang es

然后就会出现翻译后的应用程序了。

用 IDE 也可以实现。打开运行>运行参数菜单,在命令行参数(没有应用程序名称)框中输入:

--lang it

然后点击运行(F9),将会出现翻译后的应用程序。

最后的步骤

以下步骤有助于获得更好的整体翻译结果:

LCL 的翻译

要获得完整的翻译结果,必须将 LCL 的翻译文件放入应用程序的“locale”文件夹中。

请将“C:\lazarus\lcl\languages”中的所有内容复制到“locale”文件夹中。这样应用程序就会包含 LCL 的翻译了。

格式设置

为了确保 Windows 系统中的格式设置正确,必须阅读格式设置

在 Linux、BSD 和 macOS 系统中,有多个区域设置定义了时间、日期格式或千位分隔符等内容。为了 RTL 能够正常初始化,需要在程序(.lpr文件)的 uses 部分加入 clocale 单元。

双向文本模式

双向文本模式 适用于阿拉伯语之类的从右到左读写的语言。另请参阅 脚本方向和语言,以了解 LTR(从左到右)和 RTL(从右到左)语言的清单和最常用的语言。

以下单元可以确定该采用什么 BidiMode。代码已在 Lazarus 主分支版本中测试通过,在当前发布版本中可能有效也可能无效(请参阅本页的改动以获取旧版源代码)。

首先将以下单元保存为 ubidimodetools.pas:

unit ubidimodetools;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils;

function GetLang: string;
function GetBiDiMode: TBiDiMode;

implementation

uses
  FileUtil, LCLProc, LazUTF8;

function GetLang: string;
var
  T: string; // unused FallBackLang
  i: integer;
begin
  Result := '';
  { 解决方案与 LCLTranslator 单元相同 }

  for i := 1 to Paramcount - 1 do
    if (ParamStrUTF8(i) = '--LANG') or (ParamStrUTF8(i) = '-l') or
      (ParamStrUTF8(i) = '--lang') then
      Result := ParamStrUTF8(i + 1);

  //Win32 用户可以用 LANG 变量覆盖
  if Result = '' then
    Result := GetEnvironmentVariableUTF8('LANG');

  if Result = '' then
    LazGetLanguageIDs(Result, {%H-}T);
end;

function GetBiDiMode: TBiDiMode;
begin
  case GetLang of
    // 阿拉伯语
    'ar': Result := bdRightToLeft;
    else
      Result := bdLeftToRight;
  end;
end;

end.

创建窗体时可执行以下操作:

BiDiMode := GetBiDiMode;

注意:必须确保具备正确的翻译文件,才能正常工作。

注意2:或许根本就没必要使用,因为 Windows 可以自动修改 BidiMode。

技术细节

gettext

语言转换过程涉及的主要技术是 GNU gettext。FPC 自带了 gettext 单元。

uses
  gettext;

PO

PO – 可移植对象。从翻译人员收到的文件。包含了原文和译文的文本文件。

MO

MO – 机器对象。MO 文件的内容与 PO 文件完全相同。两种文件只是格式不同。PO 文件是便于人类阅读的文本文件,而 MO 文件则是便于机器读取的编译后的文件。gettext 单元实现了 TMOFile,并提供了几个函数由多个 .mo 文件转换语言,必要时可以使用。

unit gettext;

...

TMOFile = class

...

  procedure GetLanguageIDs(var Lang, FallbackLang: string);
  procedure TranslateResourceStrings(AFile: TMOFile);
  procedure TranslateUnitResourceStrings(const AUnitName:string; AFile: TMOFile);
  procedure TranslateResourceStrings(const AFilename: String);
  procedure TranslateUnitResourceStrings(const AUnitName:string; const AFilename: String);

关于翻译的其他事项

以下是之前本文有关翻译的全部资料。有很多文章可能会给新手带来困扰。为了简化起见,其他资料已移至:关于翻译的其他事项。请尽量保持本文的简洁明了。

参见