Provided by: po4a_0.52-1_all 

名前
po4a - ドキュメントやその他の素材の翻訳フレームワーク
概要
po4a (PO for anything) プロジェクトは、gettext ツールが想定していないドキュメントのような領域で翻訳をしや
すくすること (またより興味深いのは、翻訳文の保守がしやすくなること) を目標にしています。
目次
このドキュメントは以下のような構成となっています:
1 なぜ po4a を使うべきなのでしょうか? 何の役に立つのですか?
この導入の章では、プロジェクトの動機とその哲学について説明します。翻訳を行うに当たって po4a を評価中
であるなら、まずこの章を読んでください。
2 po4a の使い方は?
この章は、処理全体を理解していただけるようにユーザの質問に答える形のリファレンスマニュアルの一種で
す。po4a をどのように使用するかを紹介し、特定のツールのドキュメントへの導入として役立ちます。
新規翻訳を始めるには?
翻訳をドキュメントファイルに適用するには?
po4a 翻訳を更新するには?
既存の訳を po4a にコンバートするには?
翻訳におまけのテキスト (翻訳者名など) を追加するには?
一度のプログラム実行でこのすべてを行うには?
po4a をカスタマイズするには?
3 どのように動作しますか?
この章では、保守改良を自信を持って助けていただけるよう po4a 内部の概要を説明します。また、なぜ思った
ように動作しないか、どのように問題を解決すればいいかを理解する助けになるかもしれません。
4 FAQ
本章ではよく訊かれる質問を分類します。実際、以下のような形でほとんどの質問を定型化できました。「なぜ
ああではなく、このような設計をしたのですか?」 po4a がドキュメントを翻訳する正しい方法ではないと感じた
ら、この節を読むようにするべきです。あなたの疑問への答えにならないな
ら、<po4a-devel@lists.alioth.debian.org> メーリングリストで私たちにお問い合わせください。私たちは
フィードバックが大好きです。
5 モジュール固有の記述
この章では、翻訳者とオリジナルの作者の視点で、それぞれのモジュールの仕様を示しています。翻訳生活をよ
り楽にするために、このモジュールで翻訳する際に遭遇する文法や、オリジナルのドキュメントが従わなければ
ならないルールについて学ぶには、これをお読みください。
この節は実際には本ドキュメント本来の部分ではなく、各モジュールのドキュメントにあります。これによ
り、ドキュメントとコードを共に保守し、確実に情報が最新となるのを助けます。
なぜ po4a を使うべきなのでしょうか? 何の役に立つのですか?
誰でもソフトウェアやそのソースコードにアクセスできるようにするオープンソースの考え方が私は好きです。しか
しフランス人であり、ソフトウェアのオープン度がライセンスのみでないことをよく意識しています。翻訳されてい
ないフリーソフトウェアは、非英語圏の人々には役に立たないのです。ですから本当に誰でも利用できるように、ま
だ作業を行っています。
オープンソース活動家のこの状況の認知度は、最近劇的に向上しました。翻訳者として最初の戦いに勝利し、翻訳の
重要性を周知できました。しかし残念ながら、これはまだ簡単な部類でした。今度は、すべてを翻訳するよう作業し
なければなりません。
実際には、オープンソースソフトウェア自身は、すばらしい gettext ツール群のおかげでかなりきちんと翻訳の恩恵
にあずかっています。これはプログラムから翻訳する文字列を抽出し、翻訳者に決まった形で提供し、実行時に
は、作業の成果である翻訳済みのメッセージをユーザに表示できます。
しかし、ドキュメントに関しては状況が大きく異なります。あまりにも頻繁に、翻訳されたドキュメントが十分見え
るようになっていない (プログラムの一部として配布されない)、一部しか訳されていない、更新されていないといっ
たことが起きています。最後の状況はあり得る中で最悪なものです。古い翻訳がもはや使われなくなった古い動作を
説明しているため、まったく翻訳されていない状況よりもひどい結果になります。
解決すべき問題
ドキュメントの翻訳は、本来そんなに難しくありません。テキストはプログラムのメッセージよりもずっと長く、訳
了するのに時間がかかりますが、技術スキルが本当に必要というわけではないのです。難しい部分は成果物を保守し
ようとしたときに現れます。変更箇所や更新すべき箇所を探し出すのは非常に難しく、誤りやすく、苦痛をともなう
作業です。世の中にこんなにも時代遅れなドキュメントが存在しているのは、これが原因だと考えています。
po4a の回答
そこで、po4a の核心は、ドキュメントの翻訳を保守できるようにすることです。そのアイデアは、この新しい分野に
gettext の方法論を再利用することです。gettext のように、翻訳者に一様なフォーマットで提示するために、テキ
ストはそのオリジナルの場所から抽出されます。オリジナルの新しいリリースが出てきた時に、古典的な gettext
ツールは翻訳者が翻訳を更新するのを手助けします。しかし、古典的な gettext モデルとは異なり、翻訳はオリジナ
ルドキュメントの構造に再度注入され、翻訳は英語バージョンと同じように処理や配布をすることができます。
このおかげで、ドキュメントのどこが変更され、修正する必要があるかを見つけるのが、非常に簡単になりまし
た。ほかの長所としては、オリジナルドキュメントの構造が根本的に再編成されて、章が移動、結合、分割されたと
しても、ほとんどすべての作業をツールが行うということもあります。翻訳用にドキュメント構造からテキストを抽
出することで複雑なテキストフォーマットに触らずに済み、ドキュメントを壊してしまう可能性を (完全になくすと
いうわけには行きませんが) 低くできます。
このアプローチの利点と欠点のより詳しい一覧は、このドキュメントの後ろの FAQ を参照してください。
サポートするフォーマット
現在、このアプローチで実装に成功しているのは、以下のテキスト整形フォーマットです:
man
たくさんのプログラムで使われている、古き良きマニュアルページのフォーマットです。このフォーマットはいくら
か難しく、初心者には本当に易しくないので po4a のサポートは非常に歓迎されています。Locale::Po4a::Man(3pm)
モジュールは、BSD man ページ (Linux でも本当に一般的) で使用されている mdoc フォーマットもサポートしてい
ます。
pod
Perl のオンラインドキュメントフォーマットです。言語や拡張機能自体が、既存の Perl スクリプトと同じように記
述されています。同じファイルに組み込んで、実際のコードのそばにドキュメントを記述し保守しやすくしていま
す。プログラマーの生活は楽になりますが、残念ながら翻訳者の生活は楽にはなりません。
sgml
最近はいくらか XML に取って代わられましたが、このフォーマットは数画面以上の長いドキュメントでまだかなり頻
繁に使用されます。これで完全な本を作ることができます。あまりにもドキュメントが長いため、翻訳を更新するの
はまさしく悪夢といえます。また、オリジナルドキュメントを更新すると、インデントが再構成されるため、diff も
あまり役に立ちません。幸い、po4a はこの処理でも助けになります。
現在、DebianDoc と DocBook DTD のみサポートしていますが、新しくサポートするものを追加するのは、本当に簡単
です。また、コマンドラインに必要な情報を与え、コードを変更せずに未知の SGML DTD を po4a で使用することも
できます。詳細は Locale::Po4a::Sgml(3pm) を参照してください。
TeX / LaTeX
LaTeX フォーマットはフリーソフトウェア界や出版界で使われている有名なフォーマットで
す。Locale::Po4a::LaTeX(3pm) モジュールは Python のドキュメントや書籍、各種発表でテストされています。
texinfo
GNU のドキュメントはすべてこのフォーマットで書かれています (公式 GNU プロジェクトになる必要条件の一つで
す)。po4a のLocale::Po4a::Texinfo(3pm) サポートは始まったばかりです。バグ報告や機能のリクエストをお願いし
ます。
xml
XML フォーマットは多くのドキュメントフォーマットの基礎になっています。
現在、po4a では DocBook の DTD をサポートしています。詳細は、Locale::Po4a::Docbook(3pm) を参照してくださ
い。
その他
Po4a can also handle some more rare or specialized formats, such as the documentation of compilation
options for the 2.4+ Linux kernels or the diagrams produced by the dia tool. Adding a new one is often
very easy and the main task is to come up with a parser of your target format. See
Locale::Po4a::TransTractor(3pm) for more information about this.
サポート外のフォーマット
残念ながら、po4a はいくつかのドキュメントフォーマットのサポートを欠いています。
ドキュメントだけではなく、po4a でサポートしたいほかのフォーマットがたくさんあります。まさしく私たちは、古
典的な gettext ツールが残した「市場の穴」を埋めるのを目標としています。そこには、パッケージの説明 (deb や
rpm) や、パッケージのインストールスクリプトの質問、パッケージの changelog、ゲームのシナリオや wine リソー
スファイルといったプログラムが使用するすべての特殊ファイルが含まれます。
po4a の使い方は?
この章は、処理全体を理解していただけるようにユーザの質問に答える形のリファレンスマニュアルの一種で
す。po4a をどのように使用するかを紹介し、特定のツールのドキュメントへの導入として役立ちます。
概要図
以下の図は po4a を用いたドキュメント翻訳過程の概要です。複雑になってしまいましたが、おじけづかないでくだ
さい。処理の 全体 を表そうとして、このようになってしまいました。いったんプロジェクトを po4a に変換すると
図の右の部分のみが関係します。
Note that master.doc is taken as an example for the documentation to be translated and translation.doc is
the corresponding translated text. The suffix could be .pod, .xml, or .sgml depending on its format.
Each part of the picture will be detailed in the next sections.
master.doc
|
V
+<-----<----+<-----<-----<--------+------->-------->-------+
: | | :
{translation} | { update of master.doc } :
: | | :
XX.doc | V V
(optional) | master.doc ->-------->------>+
: | (new) |
V V | |
[po4a-gettextize] doc.XX.po -->+ | |
| (old) | | |
| ^ V V |
| | [po4a-updatepo] |
V | | V
translation.pot ^ V |
| | doc.XX.po |
| | (fuzzy) |
{ translation } | | |
| ^ V V
| | {manual editing} |
| | | |
V | V V
doc.XX.po --->---->+<---<-- doc.XX.po addendum master.doc
(initial) (up-to-date) (optional) (up-to-date)
: | | |
: V | |
+----->----->----->------> + | |
| | |
V V V
+------>-----+------<------+
|
V
[po4a-translate]
|
V
XX.doc
(up-to-date)
左側で、po4a を使用していない翻訳のこのシステムへの変換を表します。右側の先頭でオリジナルの作者の行動 (ド
キュメントの更新) を描いています。右側の中盤で po4a が自動で行う動作を描いています。新しい要素を抽出
し、既存の翻訳と比較しています。変更のなかった部分には以前の翻訳を使います。一部変更がある部分には、以前
の翻訳を使いますが、翻訳を更新する必要があるというマークが付きます。図の下部は、整形済みドキュメントがど
のように組み立てられるかを示しています。
実際には、翻訳者として唯一手で操作しなければならないのは {手動編集} と印が付いている部分です。あぁ申し訳
ありません。po4a は翻訳の助けにはなりますが、翻訳をしてくれるわけではありません……
新規翻訳を始めるには?
この節では、po4a で新しく翻訳を始めるのに必要な手順を説明します。既存プロジェクトをこのシステムに変換する
方法は、関連する節で詳しく取り扱います。
po4a を用いて新しく翻訳を始めるには、以下の手順を行う必要があります:
- オリジナルの <master.doc> ドキュメントから、翻訳するテキストを新しい翻訳テンプレート <translation.pot>
ファイル (gettext フォーマット) に抽出します。これには po4a-gettextize プログラムを以下のように使いま
す:
$ po4a-gettextize -f <format> -m <master.doc> -p <translation.pot>
<format> は、当然 master.doc ドキュメントで使用されるフォーマットです。予想されたように、出力は
translation.pot になります。既存のオプションの詳細は po4a-gettextize(1) を参照してください。
- Actually translate what should be translated. For that, you have to rename the POT file for example to
doc.XX.po (where XX is the ISO 639-1 code of the language you are translating to, e.g. fr for French),
and edit the resulting file. It is often a good idea to not name the file XX.po to avoid confusion with
the translation of the program messages, but this your call. Don't forget to update the PO file
headers, they are important.
実際の翻訳には、Emacs や Vi の PO mode、Lokalize (KDE ベース)、Gtranslator (GNOME ベース)、その他 (例え
ば Virtaal) より、あなたが作業しやすいものを使うことができます。
翻訳作業について詳しく学びたい場合は、間違いなく gettext-doc パッケージにある gettext のドキュメントを
参照する必要があります。
翻訳をドキュメントファイルに適用するには?
翻訳を完了したら、翻訳されたドキュメントを取得し、オリジナルのものと一緒にユーザに提供したいと思いま
す。そのために、以下のように po4a-translate(1) プログラムを使用してください (XX の箇所は言語コードです):
$ po4a-translate -f <format> -m <master.doc> -p <doc.XX.po> -l <XX.doc>
As before, <format> is the format used in the master.doc document. But this time, the PO file provided
with the -p flag is part of the input. This is your translation. The output goes into XX.doc.
詳細は po4a-translate(1) を参照してください。
po4a 翻訳を更新するには?
オリジナルの master.doc ファイルが変更された時に翻訳を更新するには、po4a-updatepo(1) を以下のように使用し
ます:
$ po4a-updatepo -f <format> -m <new_master.doc> -p <old_doc.XX.po>
(詳細は po4a-updatepo(1) を参照してください)
当然のことながら、この操作でドキュメントの新しい段落が魔法のように PO ファイルで翻訳されているということ
はありません。PO ファイルを手で更新する必要があります。さらに、少し変更された段落のために翻訳を手直しする
必要があります。変更された段落を見逃さないように、処理中に "fuzzy" マーカが付けられるので、po4a-translate
でその翻訳を処理する前に、のマーカを消さなければなりません。最初の翻訳と同様に、作業しやすい PO エディタ
を使うのがベストです。
未訳部や fuzzy な部分を取り除いて PO ファイルを再度最新にしたら、前節で説明したように翻訳済みドキュメント
ファイルを生成できます。
既存の訳を po4a にコンバートするには?
オリジナルの master.doc ドキュメントが大きく再編成されるまでは、手で翻訳するのに不満はなかったでしょ
う。diff のようなツールがうまくいかなくなったから po4a に乗り換えようとしているのだと思います。もちろ
ん、この処理で既存の翻訳を失いたくはありません。ご心配なく。この場合も po4a では扱えます。これを gettext
化と呼びます。
ここで重要なのは、翻訳とオリジナルが同一の構造になっていることで、ツールがそれぞれの内容を対応付けられる
ことです。
あなたがツイていれば (つまり両方のドキュメントの構造が完全に一致するとか)、シームレスに一瞬で完了しま
す。そうでなければ、この手順になぜこんなひどい名前が付いているのか理解するでしょう。とはいえこんなひどい
作業でも準備しておくに越したことはありません。いずれにしろ、po4a で後々楽になるために支払う価値があると
思ってください。ありがたいことに一回だけやればいいのです。
I cannot emphasize this too much. In order to ease the process, it is thus important that you find the
exact version which were used to do the translation. The best situation is when you noted down the VCS
revision used for the translation and you didn't modify it in the translation process, so that you can
use it.
更新されたオリジナルテキストを古い翻訳と一緒に使用するのはうまくいきません。そういったこともできます
が、本当に大変で、できれば避けた方がいいでしょう。事実上、もう一度オリジナルテキストを見つけられないな
ら、一番いいのはあなたのために gettext 化してくれる人を見つけることでしょう。(あ、いや、私じゃないですよ
;)
おそらくドラマチックすぎるでしょうが、何か問題があるとしても、すべてをもう一度翻訳し直すよりは速いと思い
ます。既存の Perl ドキュメントフランス語訳を gettext 化するのに、問題も ありました が 1 日でできまし
た。これは 2MB のテキストで、新規に翻訳するには数ヶ月を要したでしょう。
ではまず、手順の基本を説明します。それから何か問題があれば戻ってきてヒントを示したいと思います。理解しや
すいように、もう一度上記の例を使用しましょう。
翻訳した XX.doc に対応する古い master.doc を用意できたら、translation.pot ファイルを手で訳さなくても PO
ファイル doc.XX.po を直接 gettext 化できます:
$ po4a-gettextize -f <format> -m <old_master.doc> -l <XX.doc> -p <doc.XX.po>
ツイているならこれで完了です。古い翻訳を po4a に変換し、すぐに更新タスクを行えます。数節前に説明した、最
新のオリジナルドキュメントと PO ファイルの同期を取る手順に従い、翻訳を更新してください。
うまくいっているように見えても、この処理に誤りの入り込む余地があることに注意してください。ポイント
は、po4a がオリジナルと翻訳が一致しているかどうかを理解できないということです。この処理の結果、すべての文
字列に "fuzzy" マークが付いてしまうのはこういうわけです。マーカを削除する前に、注意してチェックする必要が
あります。
しばしば、ドキュメント構造が完全には一致せず、po4a-gettextize が正常に機能しません。この時点で、ゲームは
その腐った構造をすりあわせていく作業がすべてになります。
後にある gettext 化: どのように動作しますか? 節を読むと参考になると思います。内部処理を理解すること
は、この作業の助けになります。po4a-gettextize の利点は、何か問題が発生すると、詳しく教えてくれることで
す。まず、ドキュメントに構造上の食い違いがある場合、その箇所を指摘します。これで一致しない文字列や、テキ
スト中の箇所、それらの型が分かります。さらに、そこまでで生成した PO ファイルは gettextization.failed.po
に書き出してあります。
- 翻訳者名や、翻訳に貢献した人々への謝辞といった、翻訳で追加した箇所を取り除いてください。次節で説明す
る追加内容に後で改めて追加できます。
- 遠慮なくオリジナルと翻訳の両方を編集してください。最も重要なのは PO ファイルを手に入れることです。更
新は後でできます。どちらも可能であれば、gettext 化の完了後に楽になるよう、前述のように翻訳側を編集す
るとよいでしょう。
- 必要に応じて、一部が翻訳されない問題が起きたら、そのオリジナルの一部を消してください。後で PO をド
キュメントと同期すると、それらが復活するでしょう。
- 構造を少しだけ変えた (二つの段落をまとめたとか、一つの段落を分けたとか) のなら、その変更を元に戻して
ください。オリジナルに問題があるなら、オリジナルの作者に連絡するべきでしょう。あなたの翻訳の中だけを
修正することは、コミュニティの一部だけのための修正です。さらにいえば、po4a を使用する限り不可能です
;)
- 時には、段落の内容は一致するけれども、型があわない場合があります。その修正法はフォーマットに依存しま
す。POD や man では、片方の行は空白で始まっているのに、もう片方はそうではない、ということが実際にあり
ます。こういったフォーマットでは、そのような段落は改行できず、別の型となります。そのようなときは空白
を削除してください。おそらくタグ名のタイプミスでしょう。
同様に、POD では、分割行に空白が入っていたり、=item 行と item の内容の間に空行がない場合、二つの段落
を一つにまとめてしまいます。
- 時々、ファイル間で同期が取れておらず、翻訳が間違った段落に割り当てられることがあります。これはファイ
ルに以前から問題があったことを示しています。gettextization.failed.po をチェックして、同期が取れない箇
所を探し、修正してください。
- 時々、po4a がオリジナルや翻訳のテキスト部分を、食べてしまったと強く思うかもしれませ
ん。gettextization.failed.po に緩く一致した箇所が、どちらも記録されます。その後、前後の正しいものと一
致するかを試して gettext 化は失敗し、正しいものが見えなくなります。初めて私の身に起きたとき私がしたよ
うに、po4a を盛大に罵ってください。
この不幸な状況は、同じ段落がドキュメント中で繰り返されているときに起こります。この場合、PO ファイルに
新しいエントリは追加されませんが、既存のエントリに参照が追加されます。
So, when the same paragraph appears twice in the original but both are not translated in the exact
same way each time, you will get the feeling that a paragraph of the original disappeared. Just kill
the new translation. If you prefer to kill the first translation instead when the second one was
actually better, replace the first one with the second.
反対に、二つの似て非なる段落が全く同じように翻訳されていると、翻訳した段落が消えてしまったように感じ
ることでしょう。その場合は、無駄な文字列をオリジナルの段落に追加すると解決します ("I'm different" な
ど)。これは同期の際に消えますが、気にしないでください。追加したテキストが十分短ければ、gettext はその
翻訳と既存のテキストをマッチします。(fuzzy にしますが、gettext 化した後は、すべての文字列が fuzzy に
なるので気にすることはありません)
うまくいけば、以上の小技は gettext 化作業を助け、貴重な PO ファイルが得られるでしょう。ファイルの同期
や、翻訳を始める準備ができています。大きなテキストの場合、最初の同期に時間がかかる場合があることに注意し
てください。
例えば、初めてフランス語版 Perl ドキュメント (5.5 MB の PO ファイル) に po4a-updatepo を実行したと
き、1GHz G5 コンピュータでまるまる 2 日かかりました。ええ、48 時間です。しかしその後は、私の古いノートパ
ソコンで十数秒しかかかりません。これは初回の実行で、PO ファイルのほとんどの msgid が POT ファイルのものと
一致しなかったからです。このため gettext は、もっとも近いものを探すのに、実行コストの高い文字列近接アルゴ
リズムを使わなくてはなりません。
翻訳におまけのテキスト (翻訳者名など) を追加するには?
gettext アプローチのため、po4a でのテキストの追加は単にオリジナルのものにそって新しいファイルを編集するよ
りも難しくなっています。しかし、いわゆる 追加内容 のおかげで追加できます。
追加内容を、処理後のローカライズしたドキュメントに適用するパッチの類として見なすとわかりやすいでしょ
う。通常のパッチとはかなり異なっています (1 行だけの文章、Perl の正規表現を埋め込み、削除できず新しいテキ
ストの追加のみ) が、実用上は同じです。
目的は、オリジナルドキュメントにない内容を翻訳済みドキュメントに追加できるようにすることです。よくある使
用法は、翻訳自体に関する節や、貢献者リスト、翻訳についてのバグレポートのしかたを追加することです。
追加内容は別個のファイルで提供されなければなりません。最初の行では、生成したドキュメントのどこに配置する
かのヘッダを記述します。追加内容ファイルの残りは、結果のドキュメントの決まった場所にそのまま追加されま
す。
ヘッダには、以下のようにかなり厳密な文法があります。PO4A-HEADER: で始めなければならず、セミコロン (;) 区
切りの key=value フィールドが続きます。空白が重要です。値にはセミコロン (;) を使えません。引用符で囲んで
も使えないことに注意してください。
また恐ろしげに聞こえますが、以下の例は、必要なヘッダ行の記述法を見つける手助けになるでしょう。議論の前提
として、"About this document" 節の後に "About this translation" 節を追加することとします。
以下に有効なヘッダキーを挙げます:
position (必須)
a Perl regexp. The addendum will be placed near the line matching this regexp. Note that we're
speaking about the translated document here, not the original. If more than a line match this
expression (or none), the addition will fail. It is indeed better to report an error than inserting
the addendum at the wrong location.
以下この行を目印と呼びます。追加内容を追加するポイントを追加位置と呼びます。この二つのポイントはお互
い近くにありますが、同じではありません。例えば、新しい節を挿入する場合、目印を前節のタイトルとし
て、po4a にはその節の最後に挿入するよう指示するのが簡単です (目印は特定の行がマッチするような正規表現
で表すことを覚えておいてください)。
目印に対する追加位置の地域化は、以下で説明する mode, beginboundary, endboundary の各フィールドで制御
します。
この場合、以下のようになります:
position=<title>About this document</title>
mode (必須)
It can be either the string before or after, specifying the position of the addendum, relative to the
position point. In case before is given the insertion point will placed exactly before the position
point. The after behaviour is detailed bellow.
新しい節をマッチした箇所の次に配置したい場合、以下のようにします:
mode=after
beginboundary (mode=after の時のみ使用。この場合必須)
endboundary (同上)
追加内容を後ろに続ける節の最後にマッチする正規表現です。
mode=after の場合、追加位置は目印の後になりますが、すぐ後ではありません! 追加位置で始まる節の終わり
になります。つまり、beginboundary と endboundary のどちらを指定したのかにより、それぞれの引数にマッチ
した場所の前、後に置かれます。
この場合、以下のように追加して節の終わりに一致するように指定できます:
endboundary=</section>
また、以下のようにして次の節の直前を指定できます:
beginboundary=<section>
どちらの場合でも、</section> の後で <section> の前に追加内容を配置します。ドキュメントが再構成されて
も動作するので、前者の方がいいでしょう。
どちらの形態もあるのは、異なるドキュメントフォーマットがあるからです。その中には (使用したばかりの
</section> のような) 節の終わりを示すもの、(man のような) 節の終わりを明確に示さないものがありま
す。前者では、boundary が節の最後にマッチするので、追加位置はその後になります。後者では、boundary が
次節の先頭にマッチするので、追加位置はその前になります。
これは分かりにくいですが、次の例でよく分かると思います。
今まで説明したことをまとめると、SGML ドキュメントの "About this document" の後に "About this translation"
を追加するには、以下のヘッダ行のどちらかを使用できます:
PO4A-HEADER: mode=after; position=About this document; endboundary=</section>
PO4A-HEADER: mode=after; position=About this document; beginboundary=<section>
以下の nroff 節の後に何か追加したいとします:
.SH "AUTHORS"
この行とマッチする position、そして次節の先頭 (すなわち、^\.SH) とマッチする beginboundary を入れるべき
です。追加内容は、目印の後そして beginboundary とマッチする最初の行のすぐ前に追加されます。以下のように
なります:
PO4A-HEADER:mode=after;position=AUTHORS;beginboundary=\.SH
節全体を追加するのではなく、節の内部 ("Copyright Big Dude" の後など) に何か追加したい場合、この行とマッチ
する position、および任意の行とマッチする beginboundary を指定します。
PO4A-HEADER:mode=after;position=Copyright Big Dude, 2004;beginboundary=^
ドキュメントの最後に何か追加したい場合、position はドキュメントの任意の行 (しかし 1 行のみ。ユニークでな
いと po4a は処理しません) にマッチするように与え、endboundary は何もマッチしないように与えます。"EOF" の
ような単純な文字列を使用せず、ドキュメントにたまたま含まれているものを使用してください。
PO4A-HEADER:mode=after;position=<title>About</title>;beginboundary=FakePo4aBoundary
いずれの場合にも、正規表現であることを忘れないでください。例えば、次の行で終わっている nroff 節の最後に
マッチしたい場合を考えます。
.fi
endboundary として .fi を使用しないでください。明らかに想定していない "the[ fi]le" にもマッチしてしまいま
す。この場合の正しい endboundary は ^\.fi$ です。
追加内容が想定通りにうまく動作しない場合、-vv 引数をツールに渡してみてください。追加内容を配置する際の挙
動を表示してくれます。
もっと詳細な例
オリジナルドキュメント (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
This works because the next line matching the beginboundary /^=head1/ after the section "NAME"
(translated to "NOM" in French), is the one declaring the authors. So, the addendum will be put between
both sections. Note that if later some other section will be added between NAME and AUTHOR sections, it
will break this example making the addenda to be added before this newly added section.
To avoid this you may accomplish the same using mode=before:
PO4A-HEADER:mode=before;position=^=head1 AUTEUR
一度のプログラム実行でこのすべてを行うには?
po4a を使うことは、それぞれ 3 つ以上の引数が必要な二つの異なるプログラムをユーザが正しい順番
(po4a-updatepo のあとに po4a-translate) で実行しなければならないということで、少々誤る傾向にあるというこ
とがわかりました。その上、複数のフォーマットが使われているすべてのドキュメントを一つだけの PO ファイルに
するのは、このシステムでは難しいことでした。
この難しさを解消するために po4a(1) プログラムは設計されました。一度このシステムに移行してしまえば、簡単な
設定ファイルに翻訳用ファイル (po と pot) の位置、原版の位置や形式、翻訳版の位置を記述するシンプルな設定
ファイルを書くことになります。
Then, calling po4a(1) on this file ensures that the PO files are synchronized against the original
document, and that the translated document are generated properly. Of course, you will want to call this
program twice: once before editing the PO files to update them and once afterward to get a completely
updated translated document. But you only need to remember one command line.
po4a をカスタマイズするには?
po4a モジュールには、モジュールの挙動を変更するオプション (-o オプションで指定) があります。
You can also edit the source code of the existing modules or even write your own modules. To make them
visible to po4a, copy your modules into a path called "/bli/blah/blu/lib/Locale/Po4a/" and then adding
the path "/bli/blah/blu" in the "PERLIB" or "PERL5LIB" environment variable. For example:
PERLLIB=$PWD/lib po4a --previous po4a/po4a.cfg
注: lib ディレクトリの実際の名前は重要ではありません。
どのように動作しますか?
この章では、保守改良を自信を持って助けていただけるよう po4a 内部の概要を説明します。また、なぜ思ったよう
に動作しないか、どのように問題を解決すればいいかを理解する助けになるかもしれません。
この大きな絵はなんですか?
po4a のアーキテクチャはオブジェクト指向です (Perl で。イケてる?)。すべてのパーサクラス共通の派生元
は、TransTractor と呼ばれています。このヘンな名前は、ドキュメントの翻訳と文字列の抽出を同時に行うところか
ら付けられています。
もっと形式張っていうと、入力として翻訳するドキュメントと翻訳が入っている PO ファイルを取り、結果を以下の
二つに分けて出力します。別の PO ファイル (入力ドキュメントから翻訳可能な文字列を抽出した結果) と、翻訳済
みドキュメント (入力したファイルと同じ構造ですが、翻訳可能な文字列は入力 PO ファイルの内容で置換されてい
るファイル) です。以下に図示します:
入力ドキュメント-\ /---> 出力ドキュメント
\ TransTractor:: / (翻訳済み)
+-->-- parse() --------+
/ \
入力 PO ---------/ \---> 出力 PO
(抽出済み)
この小さな骨状の絵は、po4a アーキテクチャのすべてのコアを表しています。入力 PO や出力ドキュメントを省略す
ると、po4a-gettextize になります。両方の入力を行い、出力 PO を無視すると、po4a-translate になります。
TransTractor::parse() は各モジュールで実装されている仮想関数です。どのように動作するかを説明するのに、簡
単なサンプルがあります。これは、先頭に <p> が付いた段落のリストをパースします。
1 sub parse {
2 PARAGRAPH: while (1) {
3 $my ($paragraph,$pararef,$line,$lref)=("","","","");
4 $my $first=1;
5 while (($line,$lref)=$document->shiftline() && defined($line)) {
6 if ($line =~ m/<p>/ && !$first--; ) {
7 $document->unshiftline($line,$lref);
8
9 $paragraph =~ s/^<p>//s;
10 $document->pushline("<p>".$document->translate($paragraph,$pararef));
11
12 next PARAGRAPH;
13 } else {
14 $paragraph .= $line;
15 $pararef = $lref unless(length($pararef));
16 }
17 }
18 return; # Did not got a defined line? End of input file.
19 }
20 }
6 行目で、2 度目の <p> に遭遇します。それは次の段落のシグナルです。そこで、得られた行をオリジナルドキュメ
ントに戻し (7 行目)、これまでに生成された段落を出力に押し出します。9 行目でそれの先頭の <p> を削除した
後、このタグと段落の残りの翻訳を連結して押し出します。
translate() 関数はとてもクールです。引数を出力 PO ファイルに渡して (抽出)、入力 PO ファイルで見つかった翻
訳を返します (翻訳)。pushline() の引数の一部で使用するため、この翻訳が出力ドキュメントに定着します。
クールじゃないですか? 十分シンプルなフォーマットなら、完全な po4a のモジュールを 20 行以下で作成できま
す……
Locale::Po4a::TransTractor(3pm) で、これについてもっと知ることができます。
gettext 化: どのように動作しますか?
ここでの考え方は、オリジナルドキュメントとその翻訳を取り、翻訳から抽出した N 番目の文字列は、オリジナルか
ら抽出した N 番目の文字列の翻訳であるということです。動作するには、双方のファイルの構造がまったく同じでな
ければなりません。例えば、ファイルが以下の構造を持つ場合、残念ながら翻訳の 4 番目の文字列 (型が「章」)
は、オリジナルの 4 番目の文字列 (型が「段落」) の翻訳だということはまずあり得ません。
オリジナル 翻訳
章 章
段落 段落
段落 段落
段落 章
章 段落
段落 段落
そのため、ファイルを抽出する際、オリジナルファイルからの場合も翻訳ファイルからの場合も po4a のパーサを使
い、二つ目から抽出した文字列を一つ目から抽出した文字列の翻訳として第三の PO ファイルを構成します。出力し
た文字列が実際にそれぞれの翻訳となっているかをチェックするために、po4a のドキュメントパーサは、ドキュメン
トから抽出した文字列の構文タイプ情報を出力すべきです (既存のものはすべてそうしますし、あなたのものもそう
するべきです)。さらにその情報を、双方のドキュメントが同じ構文であるかどうかを確認するのに使用します。先の
例では、4 番目の文字列は片方では段落ですが、もう一方では章見出しであることを検出し、問題を報告できます。
理論上、問題を検出した後でファイルを (ちょうど diff がするように) 再同期することは可能です。しかし、非同
期の前にある、再同期するべき文字列は明確ではなく、何度もまずい結果に終わるでしょう。以上が、何かまずい場
合、現在の実装では再同期を行わず、失敗について詳しく出力する理由です。問題の修正にはファイルの手修正が必
要です。
これだけ用心していても、この部分は非常に間違いやすいです。そのため、このように推測された翻訳すべてを
fuzzy とマークし、翻訳者によりレビューと確認を行うようにしています。
追加内容: どのように動作しますか?
さて、これはかなり簡単です。すべての追加内容が適用されるまで、翻訳済みドキュメントは、直接ディスクに書か
れていませんが、メモリに保管されています。ここに関わるアルゴリズムはかなり率直です。position 正規表現に
マッチする行を探し、mode=before の場合はその前に追加内容を挿入します。そうでなければ、boundary にマッチす
る次の行を探し、それが endboundary の場合はその行の後に、beginboundary の場合はその行の前に追加内容を挿入
します。
FAQ
本章ではよく訊かれる質問を分類します。実際、以下のような形でほとんどの質問を定型化できました。「なぜああ
ではなく、このような設計をしたのですか?」 po4a がドキュメントを翻訳する正しい方法ではないと感じたら、この
節を読むようにするべきです。あなたの疑問への答えにならないなら、<po4a-devel@lists.alioth.debian.org> メー
リングリストで私たちにお問い合わせください。私たちはフィードバックが大好きです。
なぜ段落ごとに分割して翻訳するのでしょうか?
はい、po4a は段落ごとに区切って翻訳しています (実際、その決定は各モジュールで行っていますが、既存のモ
ジュールは全てそうなっています。また、自作モジュールでも通常はそのようにすべきでしょう)。この方法には二つ
の主な利点があります:
• 場面からドキュメントの技術的な部分を隠すと、翻訳者はそこに干渉することができません。翻訳者に提示するタ
グなどの目印が少なければ少ないほど、間違いにくくなります。
• ドキュメントを切るのは、オリジナルドキュメントの変更点を隔離する助けになります。オリジナルが変更された
とき、このプロセスにより、翻訳のどの部分が更新が必要なのかを探しやすくなります。
以上の利点をもってしても、段落ごとに区切って翻訳するというアイディアが気に入らない人はいます。彼らが恐れ
ていることに対して、以下のように、いくつか回答を用意しています:
• このアプローチは、KDE プロジェクトで成功が実証されました。またそこで翻訳の巨大なコーパスを作成し、私の
知る限りドキュメントを更新しています。
• 翻訳者は翻訳の際に、PO ファイル内の文字列がオリジナルドキュメントと同じ順番であるため、まだ文脈を利用で
きます。そのため、po4a を使う使わないにかかわらず、順番通り訳していくのはかなり比較しやすいです。いずれ
の場合でも、これは私見ですが、書式付きテキストは、真に読みやすいわけではないので、印刷可能なフォーマッ
トにドキュメントを変換できる状態にしておくのが、文脈を把握する最善の方法だと思います。
• このアプローチは、プロの翻訳者が採用しています。確かに、彼らはオープンソース翻訳者とは多少異なる目標を
持っています。例えば、内容が変更されるのはまれなので、保守がそれほど重要というわけではありません。
文レベル (またはそれ以下) で分割しないのはなぜですか?
プロ仕様の翻訳ツールは、ドキュメントを文レベルで分割し、以前の翻訳を最大限再利用し、作業のスピードアップ
を図るものがあります。これは、同じ文が文脈によっては異なる翻訳になる場合に問題になります。
段落は、その定義上、文よりも長いです。これにより、二つのドキュメントの同じ段落は、それぞれの文脈に関係な
く、同じ意味 (と翻訳) になることが、おそらく保証できるでしょう。
文よりも小さい単位で分割するのは、非常にまずいでしょう。なぜまずいのかは、ここで説明するには少々長いの
で、興味のある方は、例えば Locale::Maketext::TPJ13(3pm) の man ページ (Perl のドキュメントに同梱) を参照
してください。短くするにしろ、各言語は特定の構文規則を持ち、既存の全言語で (話者の多い 10 言語のうち 5 言
語やそれ以下でも) 機能するように文の一部を集めて文を組み立てる方法はありません。
オリジナルをコメントとして翻訳中 (やその他のところ) につけないのはなぜですか?
一見したところ、gettext はすべての種類の翻訳に適合できるようには見えません。例えば、debconf (すべての
Debian パッケージが使用する、インストール時の対話インターフェース) には適合できるようには見えませんでし
た。この場合、翻訳するテキストはかなり短く (パッケージごとに 1 ダース)、パッケージのインストール前に使用
可能でなければならないため、特殊なファイルに翻訳を翻訳を置くことは困難でした。
これが debconf の開発者が翻訳を元と同じファイルに配置する別のソリューションの実装を決めた理由です。これは
かなり魅力的です。例えば、XML のためにこうしたいと思う人さえいます。次のようになります:
<section>
<title lang="en">My title</title>
<title lang="fr">Mon titre</title>
<para>
<text lang="en">My text.</text>
<text lang="fr">Mon texte.</text>
</para>
</section>
しかしこれには問題があるため、現在は PO ベースのアプローチを採用しています。ファイルではオリジナルしか編
集できず、翻訳はマスターテンプレートから抽出した PO ファイルに置かなければなりません (そしてパッケージコ
ンパイル時に配置します)。この古いシステムは以下のいくつかの理由で非推奨です:
• 保守の問題
複数の翻訳者が同時にパッチを提供した場合、それらをマージするのは大変です。
翻訳を適用する必要のある、オリジナルからの変更をどのように検出したらよいでしょう? diff を使用するに
は、どの版を元にして翻訳を行ったか記しておかねばなりません。言い換えると、あなたのファイルには PO
ファイルが必要です ;)
• エンコーディングの問題
この解は、ヨーロッパの言語だけが関わる場合には有効ですが、韓国語、ロシア語、アラビア語 (訳注: もちろ
ん日本語も) の導入は、本当に構図を複雑にします。UTF は解になり得ますが、まだ問題があります。
さらに、この問題を検出するのが難しいのです (言い換えると、「ロシア語の翻訳者のせいで」韓国語のエン
コードが壊れていることを検出するのは、韓国人の読者のみです)。
gettext はこの問題をすべて解決します。
しかし、gettext はこんな用途向けには設計されていません!
そうですね。しかし現在のところ他にもっといい方法がないのです。唯一の代替手段が手動翻訳であり、それには保
守の問題があります。
gettext を使ったドキュメント翻訳ツールは他に何がありますか?
知る限りでは、以下の二つしかありません:
poxml
KDE の人たちが DocBook XML を扱うために開発したツールです。知る限りでは、ドキュメントから PO ファイル
へ翻訳する文字列を抽出し、翻訳後に注入する初めてのプログラムです。
これは XML のみ、さらに特定の DTD のみを扱えます。リストが一つの大きな msgid になってしまうため、私は
リストの扱いにかなり不満があります。リストが大きくなると、ひとかたまりの構造をつかみにくくなります。
po-debiandoc
Denis Barbier によって作られたこのプログラムは、多少の異論があるとはいえ po4a SGML モジュールの先駆け
といえます。名前の通り、少々非推奨の DTD である DebianDoc DTD のみを扱います。
以上に対する po4a の主な利点は、簡単に内容を追加できること (欠点かもしれませんが) と、gettext 化が簡単な
ことです。
翻訳についての開発者教育
ドキュメントやプログラムの翻訳を行う際、3 つの問題に行き当たります。言語について (皆が二つの言語で話せる
わけではありません)、技術について (po4a が存在する理由です)、人との連携についてです。すべての開発者が、翻
訳の必要性について理解しているわけではありません。立派な意志があったとしても、翻訳者が作業しやすいやり方
を無視する可能性もあります。これを補助するのに、po4a は参照可能なたくさんのドキュメントを用意しています。
その他の重要な点として、このファイルが何で、どのように使用するのか、を示す短いコメントで、各翻訳済みファ
イルが始まるということがあります。これは、話すのも困難な言語の洪水におぼれている哀れな開発者を助け、ファ
イルを正しく扱う助けとなるはずです。
In the po4a project, translated documents are not source files anymore, in the sense that these files are
not the preferred form of the work for making modifications to it. Since this is rather unconventional,
that's a source of easy mistakes. That's why all files present this header:
| *****************************************************
| * GENERATED FILE, DO NOT EDIT *
| * THIS IS NO SOURCE FILE, BUT RESULT OF COMPILATION *
| *****************************************************
|
| This file was generated by po4a-translate(1). Do not store it (in VCS,
| for example), but store the PO file used as source file by po4a-translate.
|
| In fact, consider this as a binary, and the PO file as a regular source file:
| If the PO gets lost, keeping this translation up-to-date will be harder ;)
同様に、gettext の通常の PO ファイルは、po/ ディレクトリにコピーされる必要があるだけです。しかし、これは
po4a によって操作されたものに当てはまりません。ここには、開発者が、ドキュメントの翻訳が存在する場合に、プ
ログラム側の翻訳を削除してしまうという、大きな危険があります (双方を同じ PO ファイルに納めることはできま
せん。これは、ドキュメントはコンパイル時にのみ翻訳が必要であるのに対して、プログラムは翻訳を mo ファイル
としてインストールしなければならないからです)。以上が、po-debiandoc モジュールが以下のヘッダをつけて PO
ファイルを提供する理由です:
#
# ADVISES TO DEVELOPERS:
# - you do not need to manually edit POT or PO files.
# - this file contains the translation of your debconf templates.
# Do not replace the translation of your program with this !!
# (or your translators will get very upset)
#
# ADVISES TO TRANSLATORS:
# If you are not familiar with the PO format, gettext documentation
# is worth reading, especially sections dedicated to this format.
# For example, run:
# info -n '(gettext)PO Files'
# info -n '(gettext)Header Entry'
#
# Some information specific to po-debconf are available at
# /usr/share/doc/po-debconf/README-trans
# or http://www.debian.org/intl/l10n/po-debconf/README-trans
#
gettext ベースアプローチの利点まとめ
• 翻訳はオリジナルと一緒に保存されません。その翻訳が古くなった場合、検出することが可能となります。
• 翻訳は互いに別々のファイルに格納され、異なる言語の翻訳者がパッチの提供やエンコードレベルの干渉を、互い
に受けないようにします。
• 内部的には gettext をベースにしています (が、po4a は非常にシンプルなインターフェースを提供するので、内
部で使用していることを理解する必要はありません)。そんなところで車輪の再発明をする必要はなく、これは広く
用いられているので、バグに悩まされることはないと考えていいでしょう。
• エンドユーザにとっては何も変化ありません (願わくば翻訳がよりよく保守されるようになる、という事実は置い
ておいて)。出来上がりの配布されるファイルはまったく同じです。
• 翻訳者は、新しいファイルの文法を学習する必要はなく、好みの PO ファイルエディタ (Emacs の PO mode
や、Lokalize、Gtranslator など) でうまく動作します。
• gettext は、完了しているもの (t)、レビューや更新が必要なもの (f)、そしてまだ翻訳作業が残っているもの
(u) について、統計を取得する簡単な方法を提供しています。以下のアドレスでいくつか例を見つけることができ
ます:
- http://kv-53.narod.ru/kaider1.png
- http://www.debian.org/intl/l10n/
しかし、すべて問題ないわけではありません。このアプローチには対処するべき欠点もあります。
• 追加内容は……一見して、変です。
• 翻訳したテキストを、段落をここで分割する、二つの段落を片方に結合するといった、あなたの好みに合わせるこ
とができません。しかし、オリジナルに問題があるのであれば、とりあえずバグとして報告すべきだ、という意見
もあります。
• 簡単なインターフェースですが、学習が必要な新しいツールのままです。
One of my dreams would be to integrate somehow po4a to Gtranslator or Lokalize. When a documentation
file is opened, the strings are automatically extracted, and a translated file + po file can be written
to disk. If we manage to do an MS Word (TM) module (or at least RTF) professional translators may even
use it.
著者
Denis Barbier <barbier,linuxfr.org>
Martin Quinson (mquinson#debian.org)
訳者
倉澤 望 <nabetaro@debian.or.jp>
Debian JP Documentation ML <debian-doc@debian.or.jp>
Po4a Tools 2017-08-26 PO4A(7)