PO4A(1p)

名称
po4a - 一次性更新 PO 文件和翻译文档

简介
po4a [options] config_file

描述
po4a (PO 代表任何东西)使用经典的 gettext 工具简化了文档翻译的维护。po4a 的主要特点是将内容的翻译与文档结构分离。请参阅 po4a(7) 页了解本项目的详细介绍。

Upon execution, po4a parses all documentation files specified in its configuration file. It updates the PO files (containing the translation) to reflect any change to the documentation, and produce a translated documentation by injecting the content's translation (found in the PO files) into the structure of the original master document.

At first, the PO files only contain the strings to translate from the original documentation. This file format allows the translators to manually provide a translation for each paragraph extracted by po4a. If the documentation is modified after translation, po4a marks the corresponding translations as "fuzzy" in the PO file to request a manual review by the translators. The translators can also provide so-called "addendum", that are extra content stating for example who did the translation and how to report bugs.

 master documents ---+---->-------->---------+
  (doc authoring)    |                       |
                     V   (po4a executions)   >-----+--> translated
                     |                       |     |     documents
 existing PO files -->--> updated PO files >-+     |
      ^                            |               |
      |                            V               |
      +----------<---------<-------+               ^
       (manual translation process)                |
                                                   |
 addendum -->--------------------------------------+

The workflow of po4a is asynchronous, as suited to open-source projects. The documentation writers author the master documents at their own pace. The translators review and update the translations in the PO files. The maintainers rerun po4a on need, to reflect any change to the original documentation to the PO files, and to produce updated documentation translations, by injecting the latest translation into the latest document structure.

By default, a given translated document is produced when at least 80% of its content is translated. The untranslated text is kept in the original language. The produced documentation thus mixes languages if the translation is not complete. You can change the 80% threshold with the --keep option described below. Note however that discarding translations as soon as they are not 100% may be discouraging for the translators whose work will almost never be shown to the users, while showing "translations" that are too incomplete may be troubling for the end users.

Storing the translated documentation files in the version control system is probably a bad idea, since they are automatically generated. The precious files are the PO files, that contain the hard work of your fellow translators. Also, some people find it easier to interact with the translators through an online platform such as weblate, but this is naturally fully optional.

  Quick start tutorial
Let's assume you maintain a program named foo which has a man page man/foo.1 written in English (the bridge language in most open-source projects, but po4a can be used from or to any language). Some times ago, someone provided a German translation named man/foo.de.1 and disappeared. This is a problem because you just got a bug report saying that your documentation contains a gravely misleading information that must be fixed in all languages, but you don't speak German so you can only modify the original, not the translation. Now, another contributor wants to contribute a translation to Japanese, a language that you don't master either.

It is time to convert your documentation to po4a to solve your documentation maintenance nightmares. You want to update the doc when needed, you want to ease the work of your fellow translators, and you want to ensure that your users never see any outdated and thus misleading documentation.

The conversion includes two steps: setup the po4a infrastructure, and convert the previous German translation to salvage the previous work. This latter part is done using po4a-gettextize, as follows. As detailed in the documentation of po4a-gettextize(1), this process rarely fully automatic, but once it's done, the de.po file containing the German translation can be integrated in your po4a workflow.

  po4a-gettextize --format man --master foo.1 --localized foo.de.1 --po de.po

Let's now configure po4a. With the appropriate file layout, your configuration file could be as simple as this:

 [po_directory] man/po4a/

 [type: man] man/foo.1 $lang:man/translated/foo.$lang.1

It specifies that all PO files (containing the work of the translators) are in the man/po4a/ directory, and that you have only one master file, man/foo.1. If you had several master files, you would have several lines similar to the second one. Each such line also specify where to write the corresponding translation files. Here, the German translation of man/foo.1 is in man/translated/foo.de.1.

The last thing we need to complete the configuration of po4a is a POT file containing the template material that should be used to start a new translation. Simply create an empty file with the .pot extension in the specified po_directory (e.g. man/po4a/foo.pot), and po4a will fill it with the expected content.

Here is a recap of the files in this setup:

  ├── man/
  │   ├── foo.1        <- The original man page, in English
  │   ├── po4a/
  │   │   ├── de.po    <- The German PO translation, from gettextization
  │   │   └── foo.pot  <- The POT template of future translations (empty at first)
  │   └── translated/  <- Directory where the translations will be created
  └── po4a.cfg         <- The configuration file

Once setup, executing po4a will parse your documentation, update the POT template file, use it to update the PO translation files, and use them to update the documentation translation files. All in one command:

        po4a --verbose po4a.cfg

This is it. po4a is now fully configured. Once you've fixed your error in man/foo.1, the offending paragraph in the German translation will be replaced by the fixed text in English. Mixing languages is not optimal, but it's the only way to remove errors in translations that you don't even understand, and ensure that the content presented to the users is never misleading. Updating the German translation is also much easier in the corresponding PO file, so the language mix-up may not last long. Finally, when a Japanese translator wants to contribute a new translation, she should rename the foo.pot into ja.po and complete the translation. Once you have this file, just drop it in man/po4a/po/. A translated page will appear as man/translated/foo.ja.1 (provided that enough content is translated) when you run po4a again.

选项

-k, --keep
    保留(即写入)结果文件的转换百分比的最小阈值(默认值：80)。即，默认情况下，文件必须至少翻译 80% 才能写入磁盘。

-h, --help
    显示简短的帮助消息。

-M, --master-charset
    包含要翻译的文档的文件字符集。请注意，所有主文档必须使用相同的字符集。

-L, --localized-charset
    包含本地化文档的文件字符集。请注意，所有翻译的文档将使用相同的字符集。

-A, --addendum-charset
    附录的字符集。请注意，所有附录应使用相同的字符集。

-V, --version
    显示脚本的版本并退出。

-v, --verbose
    增加程序的冗长程度。

-q, --quiet
    减少程序的冗长。

-d, --debug
    输出一些调试信息。

-o, --option
    要传递给格式插件的额外选项。有关有效选项及其含义的更多信息，请参阅每个插件的文档。例如，您可以将 '-o tablecells' 传递给 AsciiDoc 解析器，而文本解析器将接受 '-o tabs=split'。

-f, --force
    始终生成 POT 和 PO 文件，即使 po4a 认为没有必要。

    默认行为(未指定 --force 时)如下：

        如果 POT 文件已经存在，则如果主文档或配置文件较新(除非提供了 --no-update)，则会重新生成该文件。POT 文件也写入临时文档中，po4a 验证是否确实需要更改。

        此外，只有当翻译的主文档、PO 文件、其中一个附录或配置文件更新时，才会重新生成翻译。要避免尝试重新生成未通过阈值测试的翻译(请参见 --KEEP)，可以创建扩展名为 .po4a-stamp 的文件(请参见 --STAMP)。

    如果主文档包含文件，则应使用 --force 标志，因为不会考虑这些包含文件的修改时间。

    PO 文件总是基于带有 msgmerge-U 的 POT 重新生成。

--stamp
    告诉 po4a 在由于未达到阈值而未生成翻译时创建标记文件。这些戳记文件根据预期的翻译文档命名，扩展名为 .po4a stamp。

    注意：这只会激活 .po4a stamp 文件的创建。如果存在戳记文件，则始终使用它们，并使用 --rm translations 或在最终翻译文件时删除它们。

--no-translations
    不生成翻译的文档，只更新 POT 和 PO 文件。

--no-update
    不要更改 POT 和 PO 文件，只能更新翻译。

--keep-translations
    即使翻译不符合 --keep 指定的阈值，也保留现有翻译文件。此选项不会创建内容很少的新翻译文件，但会保存由于主文件更改而衰减的现有翻译。

    警告：此标志以一种相当剧烈的方式更改 po4a 行为：在翻译改进之前，您的翻译文件根本不会更新。仅当您希望传送过时的翻译文档而不是只传送准确的未翻译文档时，才使用此标志。

--rm-translations
    删除翻译的文件（意味着 --no translations）。

--no-backups
    此标志自 0.41 起不起作用，可能会在以后的版本中删除。

--rm-backups
    此标志自 0.41 起不起作用，可能会在以后的版本中删除。

--translate-only translated-file
    只翻译指定的文件。如果配置文件包含大量文件，则加快处理速度可能会很有用。请注意，此选项不更新 PO 和 POT 文件。此选项可以多次使用。

--variable var=value
    定义将在 po4a 配置文件中展开的变量。每次出现 $(var) 都将被 value 替换。此选项可以多次使用。

--srcdir SRCDIR
    为 po4a 配置文件中指定的所有输入文档设置基本目录。

    如果同时指定了 destdir 和 srcdir，则按顺序在以下目录中搜索输入文件：destdir、当前目录和 srcdir。如果指定，输出文件将写入 destdir 或当前目录。

--destdir DESTDIR
    为 po4a 配置文件中指定的所有输出文档设置基本目录（请参见上面的 --srcdir）。

  选项修改 POT 头

--porefs type
    指定引用格式。参数 type 可以是以下值之一：never 不生成任何引用；file 只指定不带行号的文件；counter 用递增的计数器替换行号；full 包含完整引用（默认值：full）。

--wrap-po no|newlines|number (default: 76)
    指定应如何封装 po 文件。这使我们可以选择封装良好但可能导致 git 冲突的文件，或者更容易自动处理但对人类来说更难读取的文件。

    从历史上看，gettext 套件已经重新格式化了第 77 列化妆品的 po 文件。此选项指定 po4a 的行为。如果设置为数值，po4a 将在内容中的此列和换行之后封装 po 文件。如果设置为 newlines，po4a 将只在内容中的新行之后拆分 msgid 和 msgstr。如果设置为 no，则 po4a 根本不会封装 po 文件。引用注释总是由我们在内部使用的 gettext 工具封装。

    请注意，此选项对 msgid 和 msgstr 的封装方式（即，将换行符添加到这些字符串的内容中）没有影响。

--master-language
    包含要翻译的文档的源文件的语言。 请注意，所有主文档必须使用相同的语言。

--msgid-bugs-address email@address
    设置 msgid 错误的报告地址。 默认情况下，创建的 POT 文件没有 Report-Msgid-Bugs-To 字段。

--copyright-holder string
    在 POT 标头中设置版权所有者。 默认值为“自由软件基金会有限公司。”

--package-name string
    设置 POT 标头的程序包名称。 默认值为“封装”。

--package-version string
    设置 POT 标头的软件包版本。 默认值为“版本”。

  修改 PO 文件的选项

--msgmerge-opt options
    msgmerge(1) 的其他选项。

    注意： $lang 将扩展为当前语言。

--no-previous
    此选项从传递给 msgmerge 的选项中删除 -previous。这是支持 0.16 之前的 gettext 版本所必需的。

--previous
    此选项 --previous 添加到传递给 msgmerge 的选项中。它需要 gettext 0.16 或更高版本，并在默认情况下激活。

配置文件
po4a 需要一个配置文件作为参数。此文件必须包含以下元素：

•   PO 文件的路径和项目中存在的语言列表;

•   可选地，一些全局选项和所谓的配置别名，用作配置单个主文件的模板;

•   要转换的每个主文件的列表以及特定参数。

所有行在方括号之间都包含一个命令，后跟其参数。注释以字符 '#' 开头，并一直运行到行的末尾。您可以转义行尾，将命令分散到几行。

本页提供了一些完整的示例，而其他示例可以在源代码分发的 "t/cfg" 目录中找到。

  查找 PO 和 POT 文件
最简单的解决方案是显式指定 POT 和 PO 文件的路径，如下所示：

 [po4a_paths] man/po/project.pot de:man/po/de.po fr:man/po/fr.po

首先指定 POT 文件的路径，然后指定德语和法语 PO 文件的路径。

可以按如下方式写入相同的信息，以降低复制/粘贴错误的风险：

 [po4a_langs] fr de
 [po4a_paths] man/po/project.pot $lang:man/po/$lang.po

$lang 组件使用提供的语言列表自动展开，减少了添加新语言时出现复制/粘贴错误的风险。

通过只提供包含翻译项目的目录的路径，您可以进一步压缩相同的信息，如下所示。

 [po_directory] man/po/

提供的目录必须包含一组 PO 文件，每个文件名为 XX.po，"XX" 为此文件中使用的语言的 ISO 639-1。该目录还必须包含单个 POT 文件，文件扩展名为 ".pot"。在第一次运行时，该文件可以是空的，但必须存在(po4a 无法猜测要在扩展名之前使用的名称)。

请注意，您只能在 "po_文件夹" 和 "po4a_路径" 之间选择一个。第一个 ("po_文件夹") 更紧凑，进一步降低了复制/粘贴错误的风险，但强制您使用预期的项目结构和文件名。第二个 ("po4a_路径") 更明确，可能更具可读性，建议您在使用 po4a 设置第一个项目时使用。

集中或拆分 PO 文件？

默认情况下，po4a 为每种目标语言生成一个 PO 文件，其中包含翻译项目的全部内容。随着项目的增长，这些文件的大小可能会出现问题。使用 weblate 时，可以为每个翻译段（即 msgid）指定优先级，以便首先翻译重要的部分。尽管如此，一些翻译团队还是喜欢将内容分成几个文件。

要在每个主文件中有一个 PO 文件，只需在 "[po4a_paths]" 行上的 PO 文件名中使用字符串 $master，如下所示。

 [po4a_paths] doc/$master/$master.pot $lang:doc/$master/$lang.po

With this line, po4a will produce separate POT and PO files for each document to translate. For example, if you have 3 documents and 5 languages, this will result in 3 POT files and 15 PO files. These files are named as specified on the "po4a_paths" template, with $master substituted to the basename of each document to translate. In case of name conflict, you can specify the POT file to use as follows, with the "pot=" parameter.

This feature can also be used to group several translated files into the same POT file. The following example only produces 2 POT files: l10n/po/foo.pot (containing the material from foo/gui.xml) and l10n/po/bar.pot (containing the material from both bar/gui.xml and bar/cli.xml).

 [po4a_langs] de fr ja
 [po4a_paths] l10n/po/$master.pot $lang:l10n/po/$master.$lang.po
 [type: xml] foo/gui.xml $lang:foo/gui.$lang.xml pot=foo
 [type: xml] bar/gui.xml $lang:bar/gui.$lang.xml pot=bar
 [type: xml] bar/cli.xml $lang:bar/cli.$lang.xml pot=bar

在 split 模式下，po4a 在 PO 更新期间构建一个临时概要，以便在所有 PO 文件之间共享翻译。如果两个 PO 文件对同一字符串有不同的翻译，po4a 将此字符串标记为 fuzzy，并将在包含此字符串的所有 PO 文件中提交两个翻译。当翻译人员解除困惑时，翻译将自动用于每个 PO 文件中。

  指定要翻译的文档
You must also list the documents that should be translated. For each master file, you must specify the format parser to use, the location of the translated document to produce, and optionally some configuration. File names should be quoted or escaped if they contain spaces. Here is an example:

 [type: sgml] "doc/my stuff.sgml"  "fr:doc/fr/mon truc.sgml"  de:doc/de/mein\ kram.sgml
 [type: man] script fr:doc/fr/script.1 de:doc/de/script.1
 [type: docbook] doc/script.xml fr:doc/fr/script.xml \
             de:doc/de/script.xml

但同样，这些复杂的行很难阅读和修改，例如在添加新语言时。使用 $lang 模板重新组织内容要简单得多，如下所示：

 [type: sgml]    doc/my_stuff.sgml $lang:doc/$lang/my_stuff.sgml
 [type: man]     script.1          $lang:po/$lang/script.1
 [type: docbook] doc/script.xml    $lang:doc/$lang/script.xml

  指定选项
有两种类型的选项：po4a options 是 po4a 命令行选项的默认值，而 format options 用于更改格式分析器的行为。作为 po4a options，您可以在配置文件中指定 --keep 命令行参数的默认值是 50%，而不是 80%。Format options 记录在每个解析模块的特定页面上，例如 Locale::Po4a::Xml(3pm)。例如，您可以将 nostrip 传递给 XML 解析器，以不除去提取的字符串周围的空格。

您可以为特定主文件传递这些选项，甚至为该文件的特定翻译传递这些选项，使用 "opt:" 和 "opt_XX:" 作为 "XX" 语言。在下面的示例中， nostrip 选项被传递给 XML 解析器（对于所有语言），而对于法语翻译，阈值将降低到 0%（因此始终保持）。

 [type:xml] toto.xml $lang:toto.$lang.xml opt:"-o nostrip" opt_fr:"--keep 0"

无论如何，这些配置块必须位于行的末尾。必须先声明文件，然后才是附录（如有）（见下文），然后才是选项。配置块的分组不是很重要，因为元素在内部连接为字符串。以下示例都是等效的：

  [type:xml] toto.xml $lang:toto.$lang.xml opt:"--keep 20" opt:"-o nostrip" opt_fr:"--keep 0"
  [type:xml] toto.xml $lang:toto.$lang.xml opt:"--keep 20 -o nostrip" opt_fr:"--keep 0"
  [type:xml] toto.xml $lang:toto.$lang.xml opt:--keep opt:20 opt:-o opt:nostrip opt_fr:--keep opt_fr:0

请注意，生成 POT 文件时不使用特定于语言的选项。例如，仅在构建法语翻译时，不可能将 nostrip 传递给解析器，因为同一 POT 文件用于更新每种语言。因此，唯一可以特定于语言的选项是生成翻译时使用的选项，如 "--keep" 选项。

配置别名

要将相同的选项传递给多个文件，最好的方法是按如下所示定义类型别名。在下一个示例中，使用此 "test" 类型（即 "man" 类型的扩展）将 "--keep 0" 传递给每个意大利语翻译。

  [po4a_alias:test] man opt_it:"--keep 0"
  [type: test] man/page.1 $lang:man/$lang/page.1

还可以对现有类型进行扩展，对别名使用相同的名称，如下所示。这不是一个错误的递归定义。

  [po4a_alias:man] man opt_it:"--keep 0"
  [type: man] man/page.1 $lang:man/$lang/page.1

全局默认选项

您还可以使用 "[options]" 行定义必须用于所有文件的选项，无论其类型如何。

  [options] --keep 20 --option nostrip

与命令行选项一样，您可以缩写配置文件中传递的参数：

  [options] -k 20 -o nostrip

选项优先权

每个源的选项都是串联的，确保默认值可以很容易地被更具体的选项覆盖。顺序如下：

•   "[options]" 行提供可由任何其他源重写的默认值。

•   然后使用类型别名。特定于语言的设置将覆盖适用于所有语言的设置。

•   特定于给定主文件的设置将同时覆盖默认设置和来自类型别名的设置。在这种情况下，特定于语言的设置也会覆盖全局设置。

•   最后，po4a 命令行上提供的参数会覆盖配置文件中的任何设置。

示例

下面是一个示例，演示如何引用空格和引号：

 [po_directory] man/po/

 [options] --master-charset UTF-8

 [po4a_alias:man] man opt:"-o \"mdoc=NAME,SEE ALSO\""
 [type:man] t-05-config/test02_man.1 $lang:tmp/test02_man.$lang.1 \
            opt:"-k 75" opt_it:"-L UTF-8" opt_fr:--verbose

  附录：在译文中增加额外内容
如果您想在翻译中添加一个额外的部分，例如给翻译人员加学分，那么您需要在定义主文件的行中定义一个附录。有关附录文件语法的更多详细信息，请参阅第 po4a(7) 页。

 [type: pod] script fr:doc/fr/script.1 \
             add_fr:doc/l10n/script.fr.add

您还可以使用语言模板，如下所示：

 [type: pod] script $lang:doc/$lang/script.1 \
             add_$lang:doc/l10n/script.$lang.add

如果补遗不适用，翻译将被丢弃。

附录声明的修饰符

在并非所有语言都提供附录的情况下，或者当附录列表从一种语言更改为另一种语言时，附录修饰符可以简化配置文件。修饰符是位于文件名之前的单个字符。

?   如果此文件确实存在，请包括 appendment_path，否则不执行任何操作。

@   addendment_path 不是常规的附录，而是一个逐行包含附录列表的文件。每个附录前面都可以加上修饰符。

!   appendment_path 被丢弃，它不会被加载，也不会被任何进一步的附录规范加载。

以下内容包括任何语言的附录，但前提是该附录存在。如果附录不存在，则不会报告任何错误。

 [type: pod] script $lang:doc/$lang/script.1  add_$lang:?doc/l10n/script.$lang.add

以下为每种语言的附录清单：

 [type: pod] script $lang:doc/$lang/script.1  add_$lang:@doc/l10n/script.$lang.add

  过滤翻译的字符串
有时候，你想在翻译过程中隐藏一些字符串。为此，可以为主文件指定一个 "pot_in" 参数，以指定在生成 pot 文件时要使用的文件名，而不是实际的主文件名。下面是一个例子：

  [type:docbook] book.xml          \
          pot_in:book-filtered.xml \
          $lang:book.$lang.xml

使用此设置，将从 book-filtered.xml （必须在调用 po4a 之前生成），而转换后的文件将从生成 book.xml 文件. 因此，任何属于F的字符串 book.xml 文件但不在 book-filtered.xml 不会包含在 PO 文件中，从而阻止翻译人员为其提供翻译。因此，在生成翻译的文档时，这些字符串将保持不变。这自然会降低翻译的级别，因此您可能需要使用 "--keep" 选项来确保无论如何都会生成文档。

参见
po4a-gettextize(1), po4a(7).

作者
 Denis Barbier <barbier@linuxfr.org>
 Nicolas François <nicolas.francois@centraliens.net>
 Martin Quinson (mquinson#debian.org)

翻译
taotieren <admin@taotieren.com>

版权和许可
Copyright 2002-2023 by SPI, inc.

This program is free software; you may redistribute it and/or modify it under the terms of GPL v2.0 or later (see the COPYING file).