PO4A(7) | Po4a Tools | PO4A(7) |
po4a - ドキュメントやその他の素材の翻訳フレームワーク
po4a (PO for anything) は、従来の gettext ツールを使った文書翻訳の保守を容易にするものです。po4aの主な特徴は、内容の翻訳を文書構造から切り離すことです。
このドキュメントではpo4aプロジェクトの紹介を行いこのツールを使うかどうかを検討している潜在的な利用者と、このツールの仕組みのなりたちを理解したいという興味のある読者に焦点を当てます。
自由ソフトウェアの理念は、技術を真に誰もが利用できるようにすることです。しかし、ライセンスだけが考慮すべきことではありません。翻訳されていない自由ソフトウェアは、英語を母国語としない人々にとっては無用の長物なのです。ですから、ソフトウェアを誰もが利用できるようにするためにやるべきことはまだあります。
このような状況はほとんどのプロジェクトで知られており、誰もがあらゆるものを翻訳する必要性を確信しています。しかし、実際の翻訳は、多くの人の膨大な努力の結晶であり、ちょっとした技術的な問題で不自由なことになっているのが現状です。
ありがたいことに、オープンソースソフトウェアは、gettext tool suite を使って実際に非常によく翻訳されています。これらのツールは、プログラムから翻訳する文字列を抽出し、標準化された形式(POファイル、または翻訳カタログと呼ばれます)で翻訳する文字列を提示するために使用されます。翻訳者が実際にこのPOファイルを翻訳するのを助けるために、このツールのエコシステム全体が成立しました。そしてその結果を実行時にgettextが使用し、エンドユーザーに翻訳された文言を表示するのです。
しかし、ドキュメンテーションに関しては、まだ少し残念な状況です。一見して、文書のソースファイルを複製して翻訳を始めるだけなので、プログラムの翻訳よりも簡単そうに見えるかもしれません。しかし、元の文書が変更された場合、その変更点を把握しておくことは、すぐさま翻訳者にとって悪夢となります。手作業で行う場合、この作業は不快であり、誤りの温床となるのです。
古い翻訳は、全く翻訳がないことよりも悪いことがよくあります。エンドユーザは、プログラムの古い動作を説明した文書に騙される可能性があります。さらに、彼らは英語を話せないので、保守者と直接対話することができません。加えて、保守者は文書が翻訳されているすべての言語は知らないので、問題を修正することができません。このような困難はしばしば貧弱なツールによって引き起こされるもので、ボランティアの翻訳者のモチベーションを蝕み、問題をさらに悪化させる可能性があります。
po4aプロジェクトの目標は、文書を翻訳する人の仕事を楽にすることです。特に、文書の翻訳を保守可能なものにすることです。
アイディアとしてはgettextの手法を再利用し、この分野に適応させようというものです。gettextと同様、テキストは元の場所から抽出され、POの翻訳カタログとして翻訳者に提示されます。翻訳者はgettextの古典的なツールを活用して、取り組んでいる作業を監査し、チームとして協力・組織化することができます。それからpo4aは翻訳を文書構造に直接注入して、英語ファイルと同様に処理・配布できる翻訳済みソースファイルを生成します。翻訳されなかった段落は、翻訳後の文書に英語のまま残され、エンドユーザーが文書内の古い翻訳を目にすることがないようにします。
これにより、翻訳の保守におけるほとんどの荷の重い作業が自動化されます。更新が必要な段落を発見するのは非常に簡単であり、要素の順番が変わっただけでそれ以外の変更がなければ工程は完全に自動化されます。また何らかの検証を行うことで、文書が壊れてしまうような形式エラーの可能性を減らすことができます。
このアプローチの利点と欠点のより詳しい一覧は、このドキュメントの後ろの FAQ を参照してください。
現在、このアプローチで実装に成功しているのは、以下のテキスト整形フォーマットです:
Locale::Po4a::Man(3pm) モジュールは、BSD の man ページで使われている mdoc 形式にも対応しています(Linux でもかなり一般的になっています)。
詳しくはLocale::Po4a::AsciiDocをご覧ください。
詳細はLocale::Po4a::Podを見てください。
現在、DebianDoc と DocBook DTD のみに対応していますが、新しく対応するものを追加するのは、本当に簡単です。また、コマンドラインに必要な情報を与え、コードを変更せずに未知の SGML DTD を po4a で使用することもできます。詳細は Locale::Po4a::Sgml(3pm) を参照してください。
Locale::Po4a::LaTeX(3pm) モジュールは Python のドキュメントや書籍、プレゼンのスライドでの実績があります。
これは、静的サイトジェネレータ、README、その他のドキュメントシステムで使用される一般的な形式に対応しています。詳しくは Locale::Po4a::Text(3pm) をご覧ください。
現在、DocBook の DTD (詳細は Locale::Po4a::Docbook(3pm) を参照)とXHTMLがpo4aでは対応されています。
詳しくは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は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 スクリプトがどのように使用されるかの概要を示しています。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
補遺についてのヒントとコツ
PO4A-HEADER: position=About this document; mode=after; beginboundary=<section> PO4A-HEADER: position=About this document ; mode=after; beginboundary=<section>
補遺の例
.SH "AUTHORS"
mode=afterを設定して2工程の手法を選択します。それから position引数の正規表現でAUTHORSの後の行に検索を絞り込みます。次に、beginboundary引数の正規表現で、次の節の先頭(つまり^.SH)に照合させます。つまり次のようになります。
PO4A-HEADER:mode=after;position=AUTHORS;beginboundary=\.SH
PO4A-HEADER:mode=after;position=Copyright Big Dude, 2004;beginboundary=^
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を使っているプロジェクトのほんの一部の一覧です。もし一覧へのご自身のプロジェクトの追加をご希望でしたらEメール(またはマージリクエスト)をお寄せください。
このプロジェクトは多くのパッケージと別の言語に翻訳するインフラを提供しており、複数の主要なディストリビューション(Arch Linux、Debianとその派生、Fedora)への統合の準備が整っています。
個人的には<pouah|https://en.wiktionary.org/wiki/pouah>と発声しており、これは yuck の意味のフランス語の擬音語です :)。ヘンなユーモアのセンスかもしれません :)
いくつかあります。以下は恐らく不完全な一覧で、もっと多くのツールが現れてきています。
これは XML のみ、さらに特定の DTD のみを扱えます。リストが一つの大きな msgid になってしまうため、私はリストの扱いにかなり不満があります。リストが大きくなると、ひとかたまりの構造をつかみにくくなります。
以上に対する po4a の主な利点は、簡単に内容を追加できること (欠点かもしれませんが) と、gettext 化が簡単なことです。
- https://docs.kde.org/stable5/en/kdesdk/lokalize/project-view.html - http://www.debian.org/intl/l10n/
しかし、すべて問題ないわけではありません。このアプローチには対処するべき欠点もあります。
私の夢の一つは Gtranslator や Lokalize に何らかの形で統合することです。文書ファイルを開くと文字列を自動的に抽出し、翻訳されたファイルとPOファイルをディスクに書き込みます。MS Word (TM) モジュール (少なくとも RTF) でこれができれば、プロの翻訳家もこれを使ってくれるかも知れません。
Denis Barbier <barbier,linuxfr.org> Martin Quinson (mquinson#debian.org)
倉澤 望 <nabetaro@debian.or.jp> Debian JP Documentation ML <debian-doc@debian.or.jp>
Hey! The above document had some coding errors, which are explained below:
2023-01-03 | Po4a Tools |