PO4A.7(1)

名前
po4a - ドキュメントやその他の素材の翻訳フレームワーク

概要
po4a (PO for anything) は、従来の gettext ツールを使った文書翻訳の保守を容易にするものです。po4aの主な特徴は、内容の翻訳を文書構造から切り離すことです。

このドキュメントではpo4aプロジェクトの紹介を行いこのツールを使うかどうかを検討している潜在的な利用者と、このツールの仕組みのなりたちを理解したいという興味のある読者に焦点を当てます。

なぜpo4aなのか？
自由ソフトウェアの理念は、技術を真に誰もが利用できるようにすることです。しかし、ライセンスだけが考慮すべきことではありません。翻訳されていない自由ソフトウェアは、英語を母国語としない人々にとっては無用の長物なのです。ですから、ソフトウェアを誰もが利用できるようにするためにやるべきことはまだあります。

このような状況はほとんどのプロジェクトで知られており、誰もがあらゆるものを翻訳する必要性を確信しています。しかし、実際の翻訳は、多くの人の膨大な努力の結晶であり、ちょっとした技術的な問題で不自由なことになっているのが現状です。

ありがたいことに、オープンソースソフトウェアは、gettext tool suite を使って実際に非常によく翻訳されています。これらのツールは、プログラムから翻訳する文字列を抽出し、標準化された形式（POファイル、または翻訳カタログと呼ばれます）で翻訳する文字列を提示するために使用されます。翻訳者が実際にこのPOファイルを翻訳するのを助けるために、このツールのエコシステム全体が成立しました。そしてその結果を実行時にgettextが使用し、エンドユーザーに翻訳された文言を表示するのです。

しかし、ドキュメンテーションに関しては、まだ少し残念な状況です。一見して、文書のソースファイルを複製して翻訳を始めるだけなので、プログラムの翻訳よりも簡単そうに見えるかもしれません。しかし、元の文書が変更された場合、その変更点を把握しておくことは、すぐさま翻訳者にとって悪夢となります。手作業で行う場合、この作業は不快であり、誤りの温床となるのです。

古い翻訳は、全く翻訳がないことよりも悪いことがよくあります。エンドユーザは、プログラムの古い動作を説明した文書に騙される可能性があります。さらに、彼らは英語を話せないので、保守者と直接対話することができません。加えて、保守者は文書が翻訳されているすべての言語は知らないので、問題を修正することができません。このような困難はしばしば貧弱なツールによって引き起こされるもので、ボランティアの翻訳者のモチベーションを蝕み、問題をさらに悪化させる可能性があります。

po4aプロジェクトの目標は、文書を翻訳する人の仕事を楽にすることです。特に、文書の翻訳を保守可能なものにすることです。

アイディアとしてはgettextの手法を再利用し、この分野に適応させようというものです。gettextと同様、テキストは元の場所から抽出され、POの翻訳カタログとして翻訳者に提示されます。翻訳者はgettextの古典的なツールを活用して、取り組んでいる作業を監査し、チームとして協力・組織化することができます。それからpo4aは翻訳を文書構造に直接注入して、英語ファイルと同様に処理・配布できる翻訳済みソースファイルを生成します。翻訳されなかった段落は、翻訳後の文書に英語のまま残され、エンドユーザーが文書内の古い翻訳を目にすることがないようにします。

これにより、翻訳の保守におけるほとんどの荷の重い作業が自動化されます。更新が必要な段落を発見するのは非常に簡単であり、要素の順番が変わっただけでそれ以外の変更がなければ工程は完全に自動化されます。また何らかの検証を行うことで、文書が壊れてしまうような形式エラーの可能性を減らすことができます。

このアプローチの利点と欠点のより詳しい一覧は、このドキュメントの後ろの FAQ を参照してください。

  サポートするフォーマット
現在、このアプローチで実装に成功しているのは、以下のテキスト整形フォーマットです:

man（成熟した構文解析器）
    たくさんのプログラムで使われている、古き良きマニュアルページの形式です。この形式はいくらか難しく、初心者には本当に易しくありません。

    Locale::Po4a::Man(3pm) モジュールは、BSD の man ページで使われている mdoc 形式にも対応しています（Linux でもかなり一般的になっています）。

AsciiDoc（成熟した構文解析器）
    この形式は、文書の執筆を容易にすることを目的とした軽量のマークアップ形式です。例えば、git システムのドキュメントに使用されています。これらのmanページは po4a を使って翻訳されています。

    詳しくはLocale::Po4a::AsciiDocをご覧ください。

pod（成熟した構文解析器）
    Perl のオンラインドキュメントフォーマットです。既存のほとんどの Perl スクリプトに加え、言語や拡張機能自体がこの形式を使って記述されています。ドキュメントと実際のコードの両方を同じファイルに組み込んでおくことで両者の内容を近しいものに保ちやすくなっています。プログラマーの体験が良くなりますが、残念ながら翻訳者の生活は楽にはなりません。po4aを使うまではね。

    詳細はLocale::Po4a::Podを見てください。

sgml（成熟した構文解析器）
    現在ではXMLに取って代わられたとはいえ、数画面以上の文書にはこの形式が使われます。本全体に使われることもあります。これだけの長さの文書は、更新するのが非常に困難です。diffは、更新後に元のテキストの字下げが改められた場合、明らかに役に立たないとわかることがよくあります。幸いなことに、po4aはそのような変更処理の後でも助けになります。

    現在、DebianDoc と DocBook DTD のみに対応していますが、新しく対応するものを追加するのは、本当に簡単です。また、コマンドラインに必要な情報を与え、コードを変更せずに未知の SGML DTD を po4a で使用することもできます。詳細は Locale::Po4a::Sgml(3pm) を参照してください。

TeX / LaTeX （成熟した構文解析器）
    LaTeX 形式はフリーソフトウェア界や出版界で使われている主要な文書形式です。

    Locale::Po4a::LaTeX(3pm) モジュールは Python のドキュメントや書籍、プレゼンのスライドでの実績があります。

text（成熟した構文解析器）
    テキスト形式は、Markdown、fortunes、YAMLフロントマター節、debian/changelog、debian/control など、長いテキストブロックを含む多くの形式の基本形式となります。

    これは、静的サイトジェネレータ、README、その他のドキュメントシステムで使用される一般的な形式に対応しています。詳しくは Locale::Po4a::Text(3pm) をご覧ください。

xmlとXHTML（恐らく成熟した構文解析器）
    XML フォーマットは多くのドキュメントフォーマットの基礎になっています。

    現在、DocBook の DTD （詳細は Locale::Po4a::Docbook(3pm) を参照）とXHTMLがpo4aでは対応されています。

BibTeX（恐らく成熟した構文解析器）
    BibTeXは、LaTeXと共に出典リスト（参考文献一覧）を整えるために使用されています。

    詳しくはLocale::Po4a::BibTexをご覧ください。

DocBook（恐らく成熟した構文解析器）
    XMLを基にしたマークアップ言語で、文書を記述するのに意味的なタグを用います。

    詳しくはLocale::Po4a:Docbookをご覧ください。

Guide XML（恐らく成熟した構文解析器）
    XMLの文書形式の1つ。このモジュールは、少なくとも2016年3月（Wayback Machineに基づく）までは、Gentoo Linuxドキュメントの翻訳のサポートと保守を支援するために特別に開発されました。Gentooはその後、DevBook XML形式に移行しました。

    詳しくはLocale::Po4a:Guideをご覧ください。

Wml（恐らく成熟した構文解析器）
    Web Markup Languageの略であって、携帯電話で使われているWAPとしてのWMLを混同しないようにしてください。このモジュールはXHTMLモジュールに依存しており、XHTMLモジュール自体もXMLモジュールに依存しています。

    より詳しくは Locale::Po4a::Wmlを見てください。

Yaml（恐らく成熟した構文解析器）
    JSONの厳密なスーパーセットです。YAMLはシステムやプロジェクトの設定としてよく使われます。YAMLはRed HatのAnsibleの中核を成しています。

    より詳しくは Locale::Po4a::Yaml を見てください。

RubyDoc（恐らく成熟した構文解析器）
    Ruby Document (RD) 形式は、2002年にRDocに変換されるまでは、RubyおよびRubyプロジェクトの既定の文書形式でした。ただし、日本語版のRubyリファレンスマニュアルは今でもRDを使用しているようです。

    より詳しくは Locale::Po4a::RubyDocを見てください。

Halibut（恐らく実験的な構文解析器）
    PuTTYの開発者であるSimon Tathamが開発した、TeX、debiandoc-sgml、TeXinfoなどに似た要素を持つ文書作成システムです。

    詳しくはLocale::Po4a:Halibutをご覧ください。

Ini（恐らく実験的な構文解析器）
    MS-DOS によって普及した設定ファイル形式。

    詳しくはLocale::Po4a::Iniをご覧ください。

texinfo（極めて実験的な構文解析器）
    GNU のドキュメントはすべてこの形式で書かれています（公式 GNU プロジェクトになる必要条件の一つでさえあります）。po4a のLocale::Po4a::Texinfo(3pm) 対応は始まったばかりです。バグ報告や機能の要望をお願いします。

他に対応している形式
    po4a は、2.4以上のLinuxカーネル のコンパイルオプションのドキュメント (Locale::Po4a::KernelHelp) や、dia ツールで使用する図 (Locale::Po4a::Dia) といった、もっと稀だったり特殊な形式もサポートしています。新しい形式を追加するのは非常に簡単で、目標の形式の構文解析器を追加するのが主な作業内容となっています。この詳細情報は Locale::Po4a::TransTractor(3pm) を参照してください。

サポート外のフォーマット
    残念ながら、po4aはまだいくつかの文書形式に対応していません。それらの多くは po4a で簡単に対応できるはずです。例えば、パッケージの説明（debやrpm）、パッケージのインストールスクリプトの質問、パッケージの変更履歴、ゲームシナリオやwineのリソースファイルのようなプログラムで使用されるすべての特殊なファイル形式など、文書に使用されない形式が含まれます。

po4aを使う
歴史的に、po4aは4つのスクリプトを中心に構築されており、それぞれが特定の作業目的を果たしています。po4a-gettextize(1) は翻訳の初動に役立つもので、既存の翻訳プロジェクトをpo4aに変換する選択肢を提供します。po4a-updatepo(1) は、元の文書への変更を、対応する po ファイルに反映します。po4a-translate(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スクリプトの概要図
次のスキーマは、各 po4a スクリプトがどのように使用されるかの概要を示しています。master.doc は翻訳される文書の例です。XX.doc はXX言語で翻訳された同じ文書で、doc.XX.po はXX言語の文書の翻訳カタログを表します。文書の著者は主にmaster.doc（manpage、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                     |
          |              |         (fuzzy)                      |
       { 翻訳 }          |           |                          |
          |              ^           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-translate(1) を含む）右の部分だけが使用されます。

左の部分は、po4a-gettextize(1)を使って、既存の翻訳プロジェクトをpo4aのインフラへと変換する方法を示しています。このスクリプトは、元の文書と翻訳された対応する文書を受け取り、対応するPOファイルを構築しようとします。このような手動変換はかなり面倒ですが（詳しくは po4a-gettextize(1) のドキュメントを参照してください）、既存の翻訳を変換するために一度だけ必要になります。もし変換する翻訳がなければこのことは忘れてよく、スキーマの右の部分に集中することができます。

右上には原著作者が文書を更新する動作が図示されています。右中段にはpo4a-updatepo(1)の自動的な動作が示されています。新しい資料が抽出され、既存の翻訳と比較されます。変更されていない部分には以前の翻訳が使用され、部分的に変更された部分には、翻訳を更新する必要があることを示す "fuzzy" の印が以前の翻訳に付けられます。新しい部分や大きく変更された箇所は翻訳されないまま残されます。

次に、手動編集では、翻訳者がPOファイルを修正して、すべての元の文字列と段落に翻訳を提供する動作が表されていることがわかります。これは、GNOME Translation Editor や KDE の Lokalize や poedit などの特定のエディタ、あるいは weblate や pootle などのオンライン現地語化プラットフォームを使用して行うことができます。翻訳結果は、1言語につき1つのPOファイルの集まりです。詳細は gettext のドキュメントを参照してください。

図の下部は、po4a-translate(1)が元の文書である master.docと翻訳者によって更新された翻訳カタログである doc.XX.poから翻訳された文書のソースを作成する様子を示しています。文書の構造は再利用され、元の内容は翻訳された対応部分に置き換えられます。オプションとして、addendumを使用して翻訳に追加でテキストを差し込むことができます。これは、最終的な文書に翻訳者の名前を追加するためによく使用されます。詳しくは以下をご覧ください。

先に述べたように、po4a(1)プログラムは、分離されたスクリプトの機能を統合し、1回の呼び出しでPOファイルと翻訳文書を更新するものです。通底する仕組みは同じです。

  新規翻訳を始めるには
po4a(1)を使用する場合、翻訳を開始するための特別な手順はありません。設定ファイルに言語を列挙するだけで、不足分のPOファイルは自動的に作成されます。当然ながら、翻訳者は文書で使用されているすべての内容の翻訳を提供する必要があります。po4a(1) は POT ファイル、つまり PO テンプレートファイルも作成します。このファイルの名前を変更し、何らかの言語で翻訳を提供することによって、プロジェクトを新しい言語に翻訳する翻訳者が現れるかもしれません。

もし、個々のスクリプトを別々に使いたい場合は、以下のように po4a-gettextize(1) を使って POT ファイルを作成するとよいでしょう。このファイルを XX.po に複製すれば新しい翻訳を開始することができます。

  $ po4a-gettextize --format <format> --master <master.doc> --po <translation.pot>

入力にはマスター文書が使われ、この処理による出力はPOTファイルになります。

  元の文書の変更の統合
そのためのスクリプトがpo4a-updatepo(1)です（詳しくはそのドキュメントを参照してください）：

  $ po4a-updatepo --format <format> --master <new_master.doc> --po <old_doc.XX.po>

マスター文書は入力で使用され、PO ファイルは更新されます。つまり入力と出力の両方で使用されます。

  翻訳済み文書を生成する
一度翻訳が完了したら、翻訳された文書を取得して元のものと一緒に利用者に配布したいでしょう。そのためには以下のように po4a-translate(1) プログラムを使用してください：

  $ po4a-translate --format <format> --master <master.doc> --po <doc.XX.po> --localized <XX.doc>

マスターファイルとPOファイルは両方とも入力で使われ、現地化されたファイルはこの過程の出力となります。

  補遺を使って翻訳に追加のテキストを入れる
ファイルを手動で翻訳する管理をしていれば、翻訳文に新しいテキストを追加することは、長い目で見れば恐らくどんな管理方法よりも簡単でしょう :)。こうしたことは翻訳された文書に、元の文書のどの内容にも対応しない追加部分を入れたい場合に起こります。古典的な使用例としては、翻訳チームに謝辞を述べたり、翻訳特有の問題を報告する方法を示したりすることがあります。

po4a では addendum ファイルを指定しなければなりませんが、これは概念的に処理後に現地化された文書に適用されるパッチと見なすことができます。各補遺は別々のファイルとして与えられていなければなりませんが、その形式は従来のパッチとは全く異なっています。最初の行は header line で、補遺の挿入位置を定義し（残念ながら不可解な構文で……。後述）、ファイルの残りの部分は決められた位置にそのまま追加されます。

ヘッダ行は、文字列 PO4A-HEADER:で始まり、key=valueフィールドのリストをセミコロンで区切ったものが続く必要があります。

例えば以下のヘッダは翻訳の一番最後に置かなければならない補遺を宣言しています。

 PO4A-HEADER: mode=eof

文書の途中に追加の内容を入れたい場合、話はより複雑になります。以下のヘッダは補遺を "About this document"という文字列を含むXMLのsectionの後に置かなければならないと宣言しています。

 PO4A-HEADER: position=About this document; mode=after; endboundary=</section>

実際には、補遺を適用しようとするとき、po4aは"position"引数（これは正規表現でも構いません）に照合する最初の行を探します。po4aはここで翻訳されたの文書を考慮することを忘れないでください。この文書は英語ですが、補遺がフランス語に翻訳された文書に適用されることを意図しているなら、行はおそらく次のようなものにするべきでしょう。

 PO4A-HEADER: position=À propos de ce document; mode=after; endboundary=</section>

"position"が対象の文書で見つかると、po4aは"position"以降で与えられた "endboundary"に照合する行を探します。その行のすぐ後ろに補遺が追加されます（なぜなら現在の節が終わる境界である endboundaryを与えたためです）。

ちょうど同じ効果が以下のヘッダでも付与でき、等価です。

 PO4A-HEADER: position=About this document; mode=after; beginboundary=<section>

ここでは、po4a は翻訳の中の "About this document" に照合する行の後にある "<section"> に照合する最初の行を探し、beginboundary、つまり次の節の始まりを示す境界を与えたのでその行の 前に 補遺を追加するのです。ですから、このヘッダ行は、"About this document"を含む節の後に補遺を置き、"<section">タグを含む行から節が始まるとpo4aに指示する必要があります。これは前の例と同じです。なぜなら本当にしたいことはこの補遺を "/section" の後か "<section" の前に追加することだからです。

挿入 l<mode>を値 "before"に設定することもでき、これは似た意味を持ちます。 "mode=before"と "endboundary"を組み合わせると、照合した境界のちょうど 後ろに補遺を置き、最後の潜在的な境界線が "position"の前に来ます。"mode=before"と "beginboundary"を組み合わせると照合した境界のちょうど 前に 補遺が置かれ、最後の潜在的な境界線が "position"の前に来ます。

  Mode   | Boundary kind |     Used boundary      | Insertion point compared to the boundary
 ========|===============|========================|=========================================
 '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'   |   (none)      |  n/a                   | End of file

補遺についてのヒントとコツ

•   これらが正規表現であることを覚えておいてください。例えば ".fi"で終わるnroffの節の終端に照合させたいときは、endboundary として ".fi" を使用しないでください。明らかに想定していない "the[ fi]le" にも照合してしまいます。この場合の正しい endboundary は "^\.fi$" です。

•   "position"と境界の内容の中ではまさに空白が要です。ですから、次の2つの行は異なります。2番目の行は、翻訳された文書に充分な後続の空白がある場合にのみ検出されます。

     PO4A-HEADER: position=About this document; mode=after; beginboundary=<section>
     PO4A-HEADER: position=About this document ; mode=after; beginboundary=<section>

•   この文脈検索は、翻訳文書の各行に対して大まかに操作しているように思われますが、実際には翻訳文書の内部データ文字列に対して操作しています。この内部データ文字列は、複数行を含む段落にまたがるテキストでやXMLタグそのものになりえます。補遺の正確な挿入点は、内部データ文字列の前か後でなければならず、内部データ文字列の中にあることはできません。

•   po4aに-vv引数を渡すと、どのように補遺が翻訳に追加されるかを理解することができます。また、補遺が適用されないときの実際の内部データ文字列を見るために、po4aをデバッグモードで実行することも役に立つかもしれません。

補遺の例

•   以下の nroff 節の後に何か追加したいとします:

      .SH "AUTHORS"

    mode=afterを設定して2工程の手法を選択します。それから position引数の正規表現でAUTHORSの後の行に検索を絞り込みます。次に、beginboundary引数の正規表現で、次の節の先頭（つまり^.SH）に照合させます。つまり次のようになります。

     PO4A-HEADER:mode=after;position=AUTHORS;beginboundary=\.SH

•   与えられた行の直後に何かを追加したければ、この行に照合するpositionとmode=afterを使い、任意の行に照合するbeginboundaryを与えてください。

     PO4A-HEADER:mode=after;position=Copyright Big Dude, 2004;beginboundary=^

•   ドキュメントの最後に何か追加したい場合、position はドキュメントの任意の行 (しかし 1 行のみ。ユニークでないと po4a は処理しません) にマッチするように与え、endboundary は何もマッチしないように与えます。"EOF" のような単純な文字列を使用せず、ドキュメントにたまたま含まれているものを使用してください。

     PO4A-HEADER:mode=after;position=About this document;beginboundary=FakePo4aBoundary

もっと詳細な例

オリジナルドキュメント (POD フォーマット):

 |=head1 NAME
 |
 |dummy - a dummy program
 |
 |=head1 AUTHOR
 |
 |me

そして、以下の補遺は確実に（フランス語で）翻訳者についての節をファイルの最後に追加されます（フランス語の "TRADUCTEUR" は "TRANSLATOR"、"moi" は "me" の意味です）。

 |PO4A-HEADER:mode=after;position=AUTEUR;beginboundary=^=head
 |
 |=head1 TRADUCTEUR
 |
 |moi
 |

AUTHOR の前に追加内容を追加するには、以下のヘッダを使用してください:

 PO4A-HEADER:mode=after;position=NOM;beginboundary=^=head1

これは、"NAME" 節（フランス語では "NOM"と翻訳される）の後にある beginboundary /^=head1/ に照合した次の行が作者を宣言しているからうまくいくのです。そのため、両方の節の間に追加内容が挿入されます。なお他の節がNAMEとAUTHORの節に後で追加される場合、po4aは補遺を新しい節の前に置くため間違ったことになります。

これを防ぐためにmode=l<before>を使って同じことを達成できます：

 PO4A-HEADER:mode=before;position=^=head1 AUTEUR

どのように動作しますか?
この章では、保守改良を自信を持って助けていただけるよう po4a 内部の概要を説明します。また、なぜ思ったように動作しないか、どのように問題を解決すればいいかを理解する助けになるかもしれません。

po4a のアーキテクチャはオブジェクト指向です。Locale::Po4a::TransTractor(3pm)クラスは全てのpo4a構文解析器に共通する先祖です。このヘンな名前は、文書の翻訳と文字列の抽出を同時に行うところから付けられています。

もっと形式張っていうと、入力として翻訳するドキュメントと翻訳が入っている PO ファイルを取り、結果を以下の二つに分けて出力します。別の PO ファイル (入力ドキュメントから翻訳可能な文字列を抽出した結果) と、翻訳済みドキュメント (入力したファイルと同じ構造ですが、翻訳可能な文字列は入力 PO ファイルの内容で置換されているファイル) です。以下に図示します:

   入力ドキュメント-\                             /---> 出力ドキュメント
                     \      TransTractor::       /         (翻訳済み)
                      +-->--   parse()  --------+
                     /                           \
   入力 PO ---------/                             \---> 出力 PO
                                                         (抽出済み)

この小さな骨子は、po4a アーキテクチャの中核全てを表しています。入力 のPO や出力文書を省略すると、po4a-gettextize になります。両方の入力を行い、出力のPO を無視すると、po4a-translate になります。po4aは2度TransTractorを呼び出し、そのTransTractorの呼び出しの間にmsgmerge -Uを呼び出すことで、1つの設定ファイルでワンストップの解決策を提供しているのです。詳しくはLocale::Po4a::TransTractor(3pm)を見てください。

po4aを使っているオープンソースプロジェクト
以下はプロダクション環境でドキュメント用にpo4aを使っているプロジェクトのほんの一部の一覧です。もし一覧へのご自身のプロジェクトの追加をご希望でしたらEメール（またはマージリクエスト）をお寄せください。

•   adduser (man): ユーザーとグループの管理ツール。

•   apt (man, docbook): Debianのパッケージ管理。

•   aptitude (docbook, svg): Debian用の端末ベースのパッケージ管理

•   F-DroidのWebサイト <https://gitlab.com/fdroid/fdroid-website> (markdown): Androidプラットフォーム用のインストール可能なFOSS（自由でオープンソースなソフトウェア）の目録。

•   git <https://github.com/jnavila/git-manpages-l10n> (asciidoc): ソースコードの変更を追跡するための分散バージョン管理システム。

•   Linux manページ <https://salsa.debian.org/manpages-l10n-team/manpages-l10n> (man)

    このプロジェクトは多くのパッケージと別の言語に翻訳するインフラを提供しており、複数の主要なディストリビューション（Arch Linux、Debianとその派生、Fedora）への統合の準備が整っています。

•   Stellarium <https://github.com/Stellarium/stellarium> (HTML): 手元のコンピュータ用の自由でオープンソースなプラネタリウム。po4aは空の文化の説明を翻訳するために使われています。

•   その他未整理の項目： <https://gitlab.com/fdroid/fdroid-website/> <https://github.com/fsfe/reuse-docs/pull/61>

FAQ

  po4aはどう発音するのですか？
個人的には<pouah|https://en.wiktionary.org/wiki/pouah>と発声しており、これは yuck の意味のフランス語の擬音語です :)。ヘンなユーモアのセンスかもしれません :)

  gettext を使ったドキュメント翻訳ツールは他に何がありますか?
いくつかあります。以下は恐らく不完全な一覧で、もっと多くのツールが現れてきています。

poxml
    KDE の人たちが DocBook XML を扱うために開発したツールです。知る限りでは、ドキュメントから PO ファイルへ翻訳する文字列を抽出し、翻訳後に注入する初めてのプログラムです。

    これは XML のみ、さらに特定の DTD のみを扱えます。リストが一つの大きな msgid になってしまうため、私はリストの扱いにかなり不満があります。リストが大きくなると、ひとかたまりの構造をつかみにくくなります。

po-debiandoc
    Denis Barbier によって作られたこのプログラムは、多少の異論があるとはいえ po4a SGML モジュールの先駆けといえます。名前の通り、少々非推奨の DTD である DebianDoc DTD のみを扱います。

xml2po.py
    2004年からGIMPドキュメントチームに使われています。名前から推測されるようにXMLファイルのみ対応であり、特有のMakefileの設定が必要ですが、かなり良く動作します。

Sphinx
    Sphinx文書プロジェクトも翻訳を管理するためにgettextをふんだんに使っています。翻訳過程の全体を管理する恐らく唯一のツールではありますが、不運にもreSTやMarkdownといったいくつかのテキスト形式でのみ動作します。

以上に対する po4a の主な利点は、簡単に内容を追加できること (欠点かもしれませんが) と、gettext 化が簡単なことです。

  gettext ベースアプローチの利点まとめ

•   翻訳はオリジナルと一緒に保存されません。その翻訳が古くなった場合、検出することが可能となります。

•   翻訳は互いに別々のファイルに格納され、異なる言語の翻訳者がパッチの提供やエンコードレベルの干渉を、互いに受けないようにします。

•   内部的には gettext をベースにしています (が、po4a は非常にシンプルなインターフェースを提供するので、内部で使用していることを理解する必要はありません)。そんなところで車輪の再発明をする必要はなく、これは広く用いられているので、バグに悩まされることはないと考えていいでしょう。

•   エンドユーザにとっては何も変化ありません (願わくば翻訳がよりよく保守されるようになる、という事実は置いておいて)。出来上がりの配布されるファイルはまったく同じです。

•   翻訳者は、新しいファイルの文法を学習する必要はなく、好みの PO ファイルエディタ (Emacs の PO mode や、Lokalize、Gtranslator など) でうまく動作します。

•   gettext は、完了しているもの (t)、レビューや更新が必要なもの (f)、そしてまだ翻訳作業が残っているもの (u) について、統計を取得する簡単な方法を提供しています。以下のアドレスでいくつか例を見つけることができます:

     - https://docs.kde.org/stable5/en/kdesdk/lokalize/project-view.html
     - http://www.debian.org/intl/l10n/

しかし、すべて問題ないわけではありません。このアプローチには対処するべき欠点もあります。

•   補遺は……一見して、変です。

•   翻訳したテキストを、段落をここで分割する、二つの段落を片方に結合するといった、あなたの好みに合わせることができません。しかし、オリジナルに問題があるのであれば、とりあえずバグとして報告すべきだ、という意見もあります。

•   簡単なインターフェースですが、学習が必要な新しいツールのままです。

    私の夢の一つは Gtranslator や Lokalize に何らかの形で統合することです。文書ファイルを開くと文字列を自動的に抽出し、翻訳されたファイルとPOファイルをディスクに書き込みます。MS Word (TM) モジュール (少なくとも RTF) でこれができれば、プロの翻訳家もこれを使ってくれるかも知れません。

関連項目

•   全てが1つに集まっている使うべきツールであるpo4a(1)のドキュメント。

•   個別のpo4aスクリプトのドキュメントは次の通り： po4a-gettextize(1)、 po4a-updatepo(1)、 po4a-translate(1)、 po4a-normalize(1)。

•   追加の補助スクリプト：msguntypot(1)、po4a-display-man(1)、po4a-display-pod(1)。

•   それぞれのフォーマットの構文解析器は次の通り。詳しくはそれぞれの解析器で受け付けるオプションを見てください：Locale::Po4a::AsciiDoc(3pm) Locale::Po4a::Dia(3pm), Locale::Po4a::Guide(3pm), Locale::Po4a::Ini(3pm), Locale::Po4a::KernelHelp(3pm), Locale::Po4a::Man(3pm), Locale::Po4a::RubyDoc(3pm), Locale::Po4a::Texinfo(3pm), Locale::Po4a::Text(3pm), Locale::Po4a::Xhtml(3pm), Locale::Po4a::Yaml(3pm), Locale::Po4a::BibTeX(3pm), Locale::Po4a::Docbook(3pm), Locale::Po4a::Halibut(3pm), Locale::Po4a::LaTeX(3pm), Locale::Po4a::Pod(3pm), Locale::Po4a::Sgml(3pm), Locale::Po4a::TeX(3pm), Locale::Po4a::Wml(3pm), Locale::Po4a::Xml(3pm)。

•   インフラの中核の実装は Locale::Po4a::TransTractor(3pm)（中核の組織立てを理解するのにとりわけ重要）、Locale::Po4a::Chooser(3pm)、Locale::Po4a::Po(3pm)、Locale::Po4a::Common(3pm)にあります。ソースツリー中のCONTRIBUTING.mdファイルもご確認ください。

著者
 Denis Barbier <barbier,linuxfr.org>
 Martin Quinson (mquinson#debian.org)

訳者
 倉澤 望 <nabetaro@debian.or.jp>
 Debian JP Documentation ML <debian-doc@debian.or.jp>

POD ERRORS
Hey! The above document had some coding errors, which are explained below:

Around line 37:
    Unterminated B<...> sequence