PO4A(7) | Po4a 工具 | PO4A(7) |
po4a - 翻译文档和其他资料的框架
po4a(PO For Anything) 使用经典的 gettext 工具简化了文档翻译的维护。po4a 的主要特征是它将内容翻译与文档结构分离。
本文档是对 po4a 项目的介绍,重点关注考虑是否使用此工具的潜在用户,以及想要了解事物为什么是这样的好奇用户。
自由软件的理念是让技术真正为每个人所用。但许可并不是唯一的考虑因素:未翻译的自由软件对非英语国家的人来说毫无用处。因此,要让每个人都可以使用软件,我们还有一些工作要做。
大多数项目都很好地理解了这种情况,现在每个人都相信有必要翻译所有的东西。然而,实际的翻译代表了许多个人的巨大努力,他们因小小的技术困难而步履蹒跚。
值得庆幸的是,使用 gettext 工具套件实际上可以很好地翻译开放源码软件。这些工具用于从程序中提取要翻译的字符串,并以标准化格式(称为 PO 文件或翻译目录)显示要翻译的字符串。一个完整的工具生态系统已经出现,可以帮助翻译人员实际翻译这些 PO 文件。然后,gettext 在运行时使用结果向最终用户显示翻译后的消息。
然而,关于文件,情况仍然有些令人失望。起初,翻译文档似乎比翻译程序更容易,因为您似乎只需复制文档源文件并开始翻译内容。然而,当原始文档被修改时,跟踪修改很快就变成了翻译人员的噩梦。如果手动完成,此任务会令人不快且容易出错。
过时的翻译往往比根本没有翻译更糟糕。最终用户可能会被描述程序旧行为的文档所欺骗。此外,他们不能直接与维护人员互动,因为他们不会说英语。此外,维护员无法修复该问题,因为他们并不了解文档翻译所用的每种语言。这些困难通常是由糟糕的工具造成的,可能会削弱志愿翻译人员的积极性,进一步加剧问题。
po4a 项目的目标是简化文档翻译人员的工作。具体地说,它使文档翻译 Maintenance 变得可维护。
我们的想法是重用 gettext 方法并使其适用于该领域。与 gettext 一样,文本从其原始位置提取,并作为 PO 翻译目录呈现给翻译人员。翻译人员可以利用经典的 gettext 工具来监控要进行的工作,并以团队形式进行协作和组织。然后,po4a 将翻译直接注入到文档结构中,以生成翻译后的源文件,可以像处理和分发英语文件一样处理和分发这些源文件。任何未翻译的段落都将以英语保留在生成的文档中,从而确保最终用户在文档中永远不会看到过时的翻译。
这使翻译维护的大部分繁琐工作自动化。发现需要更新的段落变得非常容易,当元素重新排序而不需要进一步修改时,这个过程是完全自动的。还可以使用特定验证来减少导致文档损坏的格式化错误的机会。
有关此方法的优点和缺点的更完整列表,另请参阅本文档下面的 FAQ。
目前,该方法已成功应用于多种文本格式:
Locale::Po4a::Man(3pm) 模块还支持 BSD 手册页使用的 MDOC 格式(它们在 Linux 上也很常见)。
有关详细信息,请参阅 Locale::Po4a::AsciiDoc。
有关详细信息,请参阅 Locale::Po4a::Pod。
目前只支持 DebianDoc 和 DocBook DTD,但是添加对新 DTD 的支持非常简单。通过在命令行上提供所需的信息,甚至可以在未知的 SGML DTD 上使用 po4a,而无需更改代码。有关详细信息,请参见 Locale::Po4a::Sgml(3pm)。
使用 Python 文档、一本书和一些演示文稿测试了 Locale::Po4a::LaTeX(3pm) 模块。
这支持静态站点生成器、自述文件和其他文档系统中使用的通用格式。有关详细信息,请参阅 Locale::Po4a::Text(3pm) 。
目前,po4a 支持 DocBook DTD (有关详细信息,请参阅 Locale::Po4a::Docbook(3pm) )和 XHTML。
有关详细信息,请参阅 Locale::Po4a::BibTex。
有关更多详细信息,请参阅 Locale::Po4a:Docbook 。
有关更多详细信息,请参阅 Locale::Po4a:Guide。
有关更多详细信息,请参阅 Locale::Po4a::Wml。
有关更多详细信息,请参阅 Locale::Po4a::Yaml 。
有关更多详细信息,请参阅 Locale::Po4a::RubyDoc。
有关更多详细信息,请参见 Locale::Po4a:Halibut。
有关更多详细信息,请参阅 Locale::Po4a::Ini 。
从历史上看,po4a 是围绕四个脚本构建的,每个脚本都完成特定的任务。po4a-gettexalize(1) 帮助引导翻译,并可选择将现有翻译项目转换为 po4a。po4a-updatepo(1) 将对原始文档的更改反映到相应的 po 文件中。po4a-late(1) 从原始文件和相应的 PO 文件构建翻译后的源文件。此外,po4a-Normalize(1) 对于调试 po4a 解析器非常有用,因为它从原始文档生成一个未翻译的文档。它使发现解析过程引入的故障变得更容易。
Most projects only require the features of po4a-updatepo(1) and po4a-translate(1), but these scripts proved to be cumbersome and error prone to use. If the documentation to translate is split over several source files, it is difficult to keep the PO files up to date and build the documentation files correctly. As an answer, a all-in-one tool was provided: po4a(1). This tool takes a configuration file describing the structure of the translation project: the location of the PO files, the list of files to translate, and the options to use, and it fully automates the process. When you invoke po4a(1), it both updates the PO files and regenerate the translation files that need to. If everything is already up to date, po4a(1) does not change any file.
本节的其余部分将概述如何使用 po4a 的脚本界面。大多数用户可能更喜欢使用 po4a(1) 文档中描述的多合一工具。
下面的模式概述了如何使用每个 po4a 脚本。这里,master.doc 是要翻译的文档的示例名称;XX.doc 是以 XX 语言翻译的相同文档,而 doc.XX.po 是该文档以 XX 语言翻译的目录。文档作者主要关注 master.doc (可以是手册页、XML 文档、asciidoc 文件或类似文件);翻译人员主要关注 PO 文件,而最终用户只能看到 XX.doc 文件。
master.doc | V +<-----<----+<-----<-----<--------+------->-------->-------+ : | | : {翻译} | { 更新到 master.doc } : : | | : XX.doc | V V (可选) | master.doc ->-------->------>+ : | (新的) | V V | | [po4a-gettextize] doc.XX.po -->+ | | | (旧的) | | | | ^ V V | | | [po4a-updatepo] | V | | V translation.pot ^ V | | | doc.XX.po | | | (模糊) | { 翻译 } | | | | ^ V V | | {手动编辑} | | | | | V | V V doc.XX.po --->---->+<---<-- doc.XX.po addendum master.doc (初始) (最新) (可选) (最新) : | | | : V | | +----->----->----->------> + | | | | | V V V +------>-----+------<------+ | V [po4a-translate] | V XX.doc (最新)
此模式很复杂,但实际上,一旦设置和配置了项目,就只使用正确的部分(涉及 po4a-updatepo(1) 和 po4a-late(1) )。
左侧部分描述了如何使用 po4a-gettexalize(1) 将现有的翻译项目转换为 po4a 基础设施。此脚本获取原始文档及其翻译的副本,并尝试构建相应的 PO 文件。这种手动转换相当麻烦(有关更多详细信息,请参阅 po4a-gettexalize(1) 文档),但转换现有翻译只需要一次。如果您没有任何要转换的翻译,您可以忘掉这一点,专注于模式的正确部分。
在右上角,描述了原始作者的操作,更新了文档。右中部分描述了 po4a-updatepo(1) 的自动操作。提取新资料,并将其与现有翻译进行比较。先前的翻译用于未更改的部分,而部分修改的部分使用“模糊”标记连接到先前的翻译,指示翻译必须更新。新的或大量修改的资料未翻译。
然后,Manual editing 报告描述了翻译人员的操作,他们修改 PO 文件,为每个原始字符串和段落提供翻译。这可以使用特定的编辑器(如 GNOME Translation Editor、KDE's Lokalize 或 poedit )或使用在线本地化平台(如 weblate 或 pootle)来完成。翻译结果是一组 PO 文件,每种语言一个。有关更多详细信息,请参阅 gettext 文档。
图的下半部分显示了 po4a-translate(1) 如何从翻译人员更新的 master.doc 原始文档和 doc.XX.po 翻译目录创建翻译的源文档。文档的结构被重用,而原始内容被其翻译的对应内容替换。或者,可以使用附录向翻译中添加一些额外的文本。这通常用于将翻译人员的姓名添加到最终文档中。详情见下文。
如前所述,po4a(1) 程序结合了分离脚本的效果,在一次调用中更新 PO 文件和翻译后的文档。基本逻辑保持不变。
如果使用 po4a(1),则没有特定的步骤来开始转换。您只需在配置文件中列出语言,就会自动创建丢失的 PO 文件。自然,翻译人员必须为您的文档中使用的每个内容提供翻译。po4a(1)还创建 POT 文件,即 PO 模板文件。潜在的翻译人员可以通过重命名此文件并提供其语言的翻译,将您的项目翻译成一种新的语言。
如果您喜欢单独使用各个脚本,则应该使用 po4a-gettexalize(1) 创建 POT 文件,如下所示。然后可以将该文件复制到 XX.po 以启动新的翻译。
$ po4a-gettextize --format <format> --master <master.doc> --po <translation.pot>
Master 文档用于输入,而 POT 文件是此过程的输出。
为此使用的脚本是 po4a-updatepo(1) (有关详细信息,请参阅其文档):
$ po4a-updatepo --format <format> --master <new_master.doc> --po <old_doc.XX.po>
在输入中使用 master 文档,同时更新 PO 文件:它在输入和输出中都使用。
完成翻译后,您希望获得翻译后的文档,并将其与原始文档一起分发给用户。为此,请使用 po4a-late(1) 程序,如下所示:
$ po4a-translate --format <format> --master <master.doc> --po <doc.XX.po> --localized <XX.doc>
Master 文件和 PO 文件都用于输入,而本地化文件是此过程的输出。
从长远来看,在手动翻译文件时,向翻译中添加新文本可能是唯一更容易的事情 :)。当您想要向翻译后的文档添加额外的部分,而不是与原始文档中的任何内容相对应时,就会发生这种情况。典型的用例是给翻译团队加分,并指出如何报告特定于翻译的问题。
对于 po4a,您必须指定 addendum 文件,这些文件在概念上可以被视为在处理后应用于本地化文档的补丁。每个附录必须作为单独的文件提供,但其格式与经典补丁程序非常不同。第一行是 header,它定义了附录的插入点(不幸的是,使用了隐晦的语法--见下文),而文件的其余部分被逐字添加到确定的位置。
标题行必须以字符串 PO4A-HEADER: 开头,后跟分号分隔的 key=value 字段列表。
例如,下面的标题声明了一个附录,该附录必须放在翻译的最后。
PO4A-HEADER: mode=eof
当您想要在文档中间添加额外内容时,事情会更加复杂。下面的标题声明了一个附录,翻译时必须放在包含字符串 "About this document" 的 XML 部分之后。
PO4A-HEADER: position=关于本文档; mode=after; endboundary=</section>
实际上,当尝试应用附录时,po4a 会搜索与 "position" 参数匹配的第一行(这可以是 regexp(正则表达式))。不要忘记,po4a 在这里考虑 translated 文档。本文档是英文的,但如果您打算将附录应用于文档的法语翻译,则您的行可能应该如下所示。
PO4A-HEADER: position=关于本文档; mode=after; endboundary=</section>
一旦在目标文档中找到 "position",po4a 就会搜索 "position" 之后的下一行,它与所提供的 "endboundary" 匹配。附录被添加到该行的右侧 after (因为我们提供了 endboundary,即结束于当前部分的边界)。
使用下面的 Header 可以获得完全相同的效果,即等效:
PO4A-HEADER: position=关于本文档; mode=after; beginboundary=<section>
在这里,po4a 在翻译中的匹配 "About this document" 的行之后搜索与 "<section"> 匹配的第一行,并添加该行的附录 before ,因为我们提供了 beginboundary,即 边界标记下一节的开始。 因此,此标题行需要将附录放在包含 "about this document" 的部分之后,并指示 po4a 该部分以包含 "<section"> 标记的行开头。 这与前面的示例等效,因为您真正想要的是在"/section"> 之后或 "<section">之前添加此附录。
您还可以将插入mode 设置为值 "before",具有类似的语义:将 "mode=before" 与 "endboundary" 组合将把附录正好放在匹配边界 after,即 "position" 之前的最后一条潜在边界线。将 "mode=before" 与 "beginboundary" 组合将把附录放在匹配边界 before,也就是 "position" 之前的最后一条潜在边界线。
模式 | 边界种类 | 使用的边界 | 与边界比较的插入点 ========|===============|========================|========================================= 'before'(之前)| 'endboundary'(结束边界) | last before 'position'(‘位置’之前的最后一个) | Right after the selected boundary(就在所选边界之后) 'before'(之前)|'beginboundary'(开始边界)| last before 'position' (‘位置’之前的最后一个)| Right before the selected boundary(就在所选边界之前) 'after'(之后) | 'endboundary'(结束边界) | first after 'position'(‘位置’之后的第一个) | Right after the selected boundary(就在所选边界之后) 'after'(之后) |'beginboundary'(开始边界)| first after 'position'(‘位置’之后的第一个) | Right before the selected boundary(就在所选边界之前) 'eof'(EOF) | (none) (无) | n/a | End of file(文件结尾)
关于附录的提示和技巧
PO4A-HEADER: position=关于本文档; mode=after; beginboundary=<section> PO4A-HEADER: position=关于本文档; mode=after; beginboundary=<section>
附录示例
.SH "作者"
您应该通过设置 mode=After 选择两步方法。然后,您应该使用 position 参数 regex 将搜索范围缩小到 Authors 之后的行。然后,您应该将下一节的开头(即,^\.SH)与 BEGINBOLDER 参数 regex 相匹配。这就是说:
PO4A-HEADER:mode=after;position=作者;beginboundary=\.SH
PO4A-HEADER:mode=after;position=版权所有 Big Dude,2004 年;beginboundary=^
PO4A-HEADER:mode=after;position=关于本文档;beginboundary=FakePo4aBoundary
更详细的示例
原始文件(POD 格式):
|=head1 名称 | |dummy - 一个虚拟程序 | |=head1 作者 | |我
然后,以下附录将确保在文件的末尾添加有关翻译器的部分(简体中文)(简体中文, "翻译" 表示 "TRANSLATOR","我" 表示 "me")。
|PO4A-HEADER:mode=after;position=作者;beginboundary=^=head | |=head1 翻译 | |我 |
要将附录放在作者之前,请使用以下标题:
PO4A-HEADER:mode=after;position=名称;beginboundary=^=head1
这之所以可行,是因为“name”部分(在汉语中翻译为“名称”)之后与 beginboundary 匹配的下一行 /^=head1/ 是声明作者的那行。因此,附录将放在两个部分之间。请注意,如果稍后在名称和作者部分之间添加另一个部分,po4a 将错误地将附录放在新部分之前。
要避免出现这种情况,您可以使用 mode=BEFORE 来完成相同的操作:
PO4A-HEADER:mode=before;position=^=head1 AUTEUR
本章将向您简要介绍 po4a 的内部结构,以便您可以更有信心地帮助我们维护和改进它。它还可能帮助您理解为什么它没有达到您的预期,以及如何解决您的问题。
Po4a 体系结构面向对象。Locale::Po4a::TransTractor(3pm) 类是所有 po4a 解析器的共同祖先。这个奇怪的名称来自一个事实,即它同时负责翻译文档和提取字符串。
更正式地说,它需要一个要翻译的文档加上一个包含要用作输入的翻译的 PO 文件,同时生成两个单独的输出:另一个 PO 文件(从输入文档中提取可翻译字符串的结果)和一个翻译文档(结构与输入文档相同,但所有可翻译字符串都替换为输入 PO 的内容)。以下是这一点的图形表示:
输入文档 --\ /---> 输出文档 \ 翻译提取器:: / (翻译) +-->-- 解析() --------+ / \ 输入 PO --------/ \---> 输出PO (提取)
这个小骨头是所有 po4a 架构的核心。 如果省略输入 PO 和输出文档,则得到 po4a-gettextize。 如果同时提供输入而忽略输出 PO,则得到 po4a-translate。 po4a 调用翻译提取器两次,并在这些翻译提取器调用之间调用 msgmerge -U,以提供一个配置文件的一站式解决方案。 有关更多详细信息,请参见 Locale::Po4a::TransTractor(3pm)。
以下是在生产中使用 po4a 进行文档编制的项目的非常部分的列表。如果您想将您的项目添加到列表中,只需给我们发送电子邮件(或合并请求)即可。
该项目提供了将许多手册页翻译成不同语言的基础设施,可以集成到几个主要的发行版中(Arch Linux、Debian 和衍生品、Fedora)。
我个人把它念成 pouah <https://en.wiktionary.org/wiki/pouah>,这是一个法语拟声词,我们用它来代替 yuck(雅克 ) :) 我可能有一种奇怪的幽默感 :)
There are a few of them. Here is a possibly incomplete list, and more tools are coming at the horizon.
它只能处理 XML,并且只能处理特定的 DTD。我对列表的处理很不满意,列表以一个大的 msgid 结尾。当清单变得很大时,大块就变得更难处理了。
与它们相比,po4a 的主要优势是易于添加额外内容(这一点更糟糕),以及实现获取文本的能力。
- https://docs.kde.org/stable5/en/kdesdk/lokalize/project-view.html - http://www.debian.org/intl/l10n/
但是,并非所有事物都是绿色的,而且这种方法还存在一些必须解决的缺点。
我的梦想之一是以某种方式将 po4a 集成到 GTranslator 或 Lokalize 中。打开文档文件时,会自动提取字符串,并且可以将翻译后的文件 + po 文件写入磁盘。如果我们设法制作 MSWord(TM) 模块(或者至少是 RTF),专业翻译人员甚至可以使用它。
Denis Barbier <barbier,linuxfr.org> Martin Quinson (mquinson#debian.org)
2023-01-03 | Po4a 工具 |