GNU gettext国际化PO文件格式详解

文章目录

在软件国际化(i18n)和本地化(l10n)处理中,PO 文件是一个核心概念。对于参与过开源项目的翻译工作,或者作为开发者处理过多语言支持的人来说,很可能都接触过这种文件格式。本文将详细剖析 PO 文件的结构和内容。

什么是 PO 文件?

PO 代表 Portable Object(可移植对象)。它们是 文本文件,主要设计用于 供人类阅读和编辑。PO 文件的核心作用是将程序源代码中的原始、可翻译字符串与其在特定目标语言中的翻译关联起来。

每个 PO 文件通常只对应一种特定的目标语言。这意味着如果一个软件包支持多种语言,那么每种语言都会有一个对应的 PO 文件。

与 PO 文件密切相关的是 MO 文件(Machine Object)。MO 文件是 二进制文件,旨在 供程序在运行时读取 以快速检索翻译。它们由 msgfmt 工具从 PO 文件编译生成。PO 文件格式的设计灵感来源于 Uniforum 开发、Sun 在 Solaris 系统中首次实现的 NLS 标准。

PO 文件条目结构

一个 PO 文件由许多“条目”(entry)组成。每个条目都包含一个原始的未翻译字符串及其在目标语言中的翻译。虽然理解其整体结构很重要,但使用 PO 文件编辑器(如 Emacs 的 PO 模式)时,大多数格式细节都会由编辑器自动处理。

一个典型的 PO 文件条目 schematic 结构如下所示:

white-space
#  translator-comments
#. extracted-comments
#: reference...
#, flag...
#| msgid previous-untranslated-string
msgid untranslated-string
msgstr translated-string

让我们分解这个结构中的主要部分:

1. 空白和注释 (white-space and comments)

条目可以包含空白行和以 # 开头的注释行。注释提供了关于条目的附加信息。根据开头的不同字符,注释有不同类型:

# 翻译人员注释 (translator-comments)。这是翻译人员可以自由添加和编辑的注释,用于记录翻译过程中的思考或疑问。

#. 提取的注释 (extracted-comments)。通常包含从源代码中提取的、与字符串相关的上下文信息。

#: 引用 (reference)。这些行通常指示原始字符串在源代码中的位置,格式通常是 filename:line。这些引用由 xgettext 等工具自动生成。虽然可以使用 --no-location 选项禁止生成这些行, 但来源指出这样做会使熟悉技术的翻译人员难以理解消息的上下文。默认情况下会生成引用信息,并且可以通过 --add-location=type 选项控制详细程度 (full, file, never)。

#, 标志 (flag)。这些标志提供关于条目的元信息,通常也是由程序(如 xgettextmsgmerge)自动添加的。

#| :表示旧的、不再使用的原始字符串 (previous-untranslated-string)。这通常在 PO 文件更新时由 msgmerge 添加,以帮助翻译人员理解字符串是如何变化的。

2. msgid

这是原始的、未翻译的字符串,它直接取自程序源代码。

3. msgstr

这是 msgid 字符串在特定目标语言中的翻译

msgidmsgstr 字符串在 PO 文件中通常使用双引号 (") 括起来,特殊字符(如双引号本身或换行符)使用反斜杠 (\) 进行转义。同样,翻译人员通常无需手动处理这些引用和转义的细节,PO 文件编辑器会负责。

处理长字符串

如果 msgidmsgstr 字符串很长,可以将其分割成多行书写,并通过连接多个双引号括起来的字符串来实现。例如:

msgid "" "Here is an example of how one might continue a very long string\n" "for the common case the string represents multi-line output.\n"

这里的空字符串 "" 是为了格式兼容性,因为 msgidmsgstr 关键字后必须紧跟一个字符串(即使是空字符串)在同一行。

头部条目 (Header Entry)

每个 PO 文件的第一个条目是一个特殊的头部条目,其 msgid 是一个空字符串 (msgid "")。这个条目不包含程序中实际的字符串翻译,而是用于存放整个翻译文件的元信息

头部条目通常包含以下重要字段(这些字段的值很多由 msginit 程序在创建新 PO 文件时自动填充):

Project-Id-Version:软件包的名称和版本。

PO-Revision-Date:此 PO 文件的修订日期。

Last-Translator:最后修改此文件的翻译人员信息。

Language-Team:翻译团队的名称。

Language:目标语言标识。语言命名约定通常是 ll_CC(语言代码_国家/地区代码)或简单的 ll(语言代码)。例如,在德国使用的德语标识可以是 de_DE 或更常用的 de。此字段不包含 .encoding@variant 后缀。所以,如果您的区域设置名称是 de_DE.UTF-8,在 PO 文件中通常只写 de

MIME-Version, Content-Type, Content-Transfer-Encoding:与字符编码相关的字段。

  • Content-Type 字段通常包含 charset=ENCODING,指定文件的字符编码。如果输入 POT 文件(PO 模板文件)是 UTF-8 且包含非 ASCII 字符,msginit 会保留 UTF-8 编码。如果 POT 文件是纯 ASCII,则使用区域设置的编码。PO 文件支持的字符编码限于 GNU libc 和 GNU libiconv 支持的列表。来源列举了许多支持的编码,包括 ISO-8859-_ 系列、各种 CP 编码、GB2312、EUC-JP、UTF-8 等。对于某些语言,特别是需要使用特定的引号字符(如弯引号 U+201C, U+201D 等)时,即使区域设置是 ISO-8859-_,也推荐使用 UTF-8 编码创建 PO 文件,因为 UTF-8 能表示更丰富的字符。
  • Content-Transfer-Encoding 应设置为 8bit

Plural-Forms:这是一个可选字段,仅当 PO 文件包含复数形式时才需要。它定义了该语言的复数形式规则。格式为 nplurals=N; plural=EXPRESSION;nplurals 表示复数形式的数量,plural 后是一个 C 语言语法的表达式,用于根据数字 n 计算应使用的复数形式(索引从 0 开始)。翻译人员需要根据此信息为 msgid_plural 填写对应的 msgstr, msgstr, msgstr 等。msginit 包含了已知复数规则的数据库,可以帮助自动生成此字段。

Report-Msgid-Bugs-To:用于报告原始字符串 (msgid) 错误的电子邮件地址。

标志 (Flags)

标志出现在以 `#,’ 开头的行中。它们提供了关于条目属性的元信息。许多标志是程序自动生成的,不应由人工添加。一些重要的标志包括:

c-format / no-c-format:指示 msgidmsgstr 是否应被视为 C 格式字符串。msgfmt 会检查带有 c-formatpossible-c-format 标志的条目,验证其格式说明符(如 %d)是否匹配。这些标志通常由 xgettext 添加。还有针对其他语言的类似格式标志,如 kde-format, boost-format, tcl-format, perl-format, php-format, gcc-internal-format 等。

fuzzy:表示该翻译是“模糊的”,可能需要人工修订msgmerge 在更新 PO 文件时,如果发现原始字符串发生变化,可能会将旧的翻译标记为 fuzzy。请注意,只有未标记为 fuzzy 且已填充 msgstr 的条目(即已翻译条目)会被 msgfmt 编译成 MO 文件

obsolete:表示原始字符串在程序源代码中已不再使用。这样的条目通常会被注释掉。

range:可能表示源代码中的引用位置是一个范围。

上下文 (Contexts)

为了区分相同的原始字符串在不同上下文中的不同含义和翻译,PO 文件支持使用 msgctxt 字段。这允许同一个 msgid 字符串拥有不同的翻译。

文件有效性

为了使 PO 文件有效,必须遵循一定的规则。最重要的规则是,没有 msgctxt 的条目不能有重复的 msgid (或 msgid_plural)。同样,具有相同 msgctxt 的条目也不能有重复的 msgid (或 msgid_plural)。

使用编辑器

虽然理解 PO 文件格式的细节很有益处,但在实际翻译工作中,强烈推荐使用专门的 PO 文件编辑器。这些编辑器内置了对 PO 格式的支持,可以处理格式细节、引用、转义,并提供方便的功能,如导航、验证、模糊匹配处理等。常见的 PO 编辑器包括 Lokalize (KDE), Gtranslator (GNOME), Poedit, OmegaT, Virtaal Translation Editor, 以及 Emacs 的 PO 模式 和 vim 的支持。Emacs PO 模式还提供了诸如条目间移动、批量验证文件格式、查看源代码上下文 等高级功能。

总结

PO 文件作为 GNU gettext 国际化流程中的核心文件格式,通过结构化的文本格式,有效地存储了原始字符串及其在特定语言中的翻译,并辅以注释、引用、标志等信息。它设计为人可读和编辑,是连接程序员和翻译人员的重要桥梁。通过 GNU gettext 工具链中的 xgettext (提取字符串创建模板)、msginit (创建新翻译文件)、msgmerge (更新翻译文件) 和 msgfmt (编译为机器可读的 MO 文件) 等工具的配合,以及使用专门的 PO 文件编辑器,极大地简化了软件的国际化和本地化工作流程。


也可以看看