小林儀
匡
|
翻訳の保守は新規翻訳よりも手間のかかる作業になりがちです。 しかし、 これを怠ると原文との乖離は大きくなり、 折角の翻 訳も価値が下がっていきます。 Debian で開発されている Po4a は、 プレーンテキスト、 XML、 HTML、 LaTeX、 nroff (man) など様々な形式のドキュメント翻訳を PO という形式で管理し、 保守性を上げるツールです。 今回はこの Po4a の使い方と、 新たなドキュメント形式を PO で管理するために知っておくべき内部構造について説明し ます。
長期的に見れば、 ドキュメント翻訳者の作業で最も大変で最も大切なのは、 ドキュメントの翻訳作業ではなく翻訳の保守作業で しょう。 何週間、 何ヶ月もの作業の末、 1 万行を超える長いドキュメントの翻訳作業を終えたとしても、 原文が変わり続ける限 り、 保守をしなければ翻訳の価値は下がっていきます。
保守は地味で地道な作業です。 原文に対しては、 次のような変更が発生します。
同時に、 次のような非本質的な変更も頻繁に発生します。
こういった様々な種類の変更は大抵は混ざっています。 ドキュメントの翻訳者は通常、 diffで差分を眺めて変更を把握し、 それを翻訳に反映させます。 差分を読んで変更を把握する能力によって、 翻訳に反映させる作業が楽にも大変にもなり ます。
このようなドキュメント翻訳の保守作業に必要な労力を和らげてくれるのが Po4a です。 Po4a は、 様々な形式のドキュメン ト翻訳を PO という形式で一括して管理し、 保守性を上げるツールです。 以下では、 まず PO というファイ ル形式が、 翻訳にとってどのように便利なのかを説明し、 その上で Po4a がどのようなツールなのか説明し ます。
PO は、 プログラムのメッセージの翻訳のために作られたファイル形式です。 ここではその書式や編集用のツールについて見て いきましょう。
まずは、 PO の基本的な書式を説明します。
PO には、 原文と訳文の対からなるエントリが空行区切りで多数収められています。 最初に、 簡単なエントリの例を紹介し ます。
#: src/apt_config_treeitems.cc:99
msgid "" "%BOption:%b %s\n" "%BDefault:%b %s\n" "%BValue:%b %s\n" msgstr "" "%B オプション:%b %s\n" "%B デフォルト:%b %s\n" "%B 値:%b %s\n" |
一目瞭然ですが、 msgidから始まる一連の行、 msgstrから始まる一連の行の、 "で囲まれた部分は、 それぞれ原文と訳文 です。
「#」 で始まる行は基本的にすべてコメントです。 特に「#:」 で始まる行は、 原文を抽出した位置を示す参照用の行です。 こ れはxgettextがメッセージを抽出して POT を生成するときに設定します。 翻訳者は、 msgidを見ても理解できない場合、 こ の参照コメントをもとにしてソースコードを眺めることができます。
「#:」 以外にも、 様々な種類のコメントがあります。 そのようなコメントを含んだエントリの例を紹介し ます。
# 最後の %s は「 (core dumped)」 。 #. ForTranslators: "%s update %s" gets replaced by a command line, do not translate it! #: src/generic/apt/download_update_manager.cc:383 #, c-format msgid "The debtags update process (%s update %s) was killed by signal %d%s." msgstr "" "debtags 更新プロセス (%s update %s) がシグナル %d に kill されました %s。 " |
「#.」 で始まる行は、 原文のメッセージと一緒にソースコードから抽出されたコメントです。 主に、 メッセージの翻訳に注意 が必要な場合やメッセージが翻訳しにくい場合に、 開発者から翻訳者への説明に使われます。 これもxgettextがメッセージ抽 出時に設定します。
「#,」 で始まる行はフラグです。 最もよく使われるフラグは fuzzy というフラグでしょう。 これについては後述します。 これ は 様 々な ツ ー ル が 設 定 し ま す 。
それ以外の、 「#」 の後に何の記号もない行は、 翻訳者が翻訳作業時に勝手に追加したコメントです。 各エントリにはこのよう な翻訳者コメントを自由自在につけることができます。
このようなコメント情報は、 プログラムのソースコードに書くコメントと同様、 人間の作業にのみ必要となるものなので、 MO に変換するとき にすべて削除されます*1 。
msgmergeが古い PO に新しい POT をマージする際、 既に翻訳されているエントリのmsgidに似たmsgidを持つエントリが 追加されることがあります。 例えば、 エントリ A のmsgidに似たmsgidを持つエントリ A’ が追加されるとします。 このと き、 msgmerge は A をベースとして A’ を翻訳できると判断し、 A’ の msgstr に A の msgstr の内容を設定し た上で、 A’ に fuzzy フラグをつけます。 このようにして作られるエントリが、 次のような fuzzy エントリ です。
#: src/main.cc:181
#, fuzzy, c-format msgid "" " -q In command-line mode, suppress the incremental progress\n" " indicators.\n" msgstr " -q コマンドラインモードで進行状況を逐一表示しません。 " |
しかしこれだけだと、 翻訳者には、 msgidがどう変化したのか分かりません。 そこで GNU gettext のバージョン 0.16 から 導入されたのが、 次のような、 「#|」 で始まるコメントです。
#: src/main.cc:181
#, fuzzy, c-format #| msgid "" #| " -q In command-line mode, suppress the incremental progress " #| "indicators." msgid "" " -q In command-line mode, suppress the incremental progress\n" " indicators.\n" msgstr " -q コマンドラインモードで進行状況を逐一表示しません。 " |
「#|」 で始まるコメントは、 以前のmsgidです。 msgmergeに--previousを指定した場合に設定されます。 このコメント を使えば、 以前のmsgidと現在のmsgidを比較できるので、 どのような変更をmsgstrに加えれば翻訳を現在のmsgidに対 応できるのかが簡単に分かります。 PO の保守性を上げる仕組みと言えます。 msgmergeに--previousが指定されていない場 合は指定しておくとよいでしょう。
翻訳を扱う際、 翻訳者やその連絡先、 原文の問題の連絡先、 翻訳の更新日時、 文字セットなどは重要なメタ情報です。 PO で は、 最初のエントリをヘッダとして使用し、 そのエントリのmsgstrにこれらのメタ情報を含めることになっています。 ヘッダ のmsgidは空文字列にすると決まっています。
また、 著作権情報など、 書式が曖昧な情報や長い情報は、 ヘッダのコメント (つまりファイルの冒頭) に書くことになってい ます。
以下は、 aptitude の ja.po の例です。
# Japanese translations for aptitude
# aptitude の日本語訳 # Copyright (C) 2006-2008 Noritada Kobayashi <nori1@dolphin.c.u-tokyo.ac.jp>. # This file is distributed under the same license as the aptitude package. # msgid "" msgstr "" "Project-Id-Version: aptitude 0.4.1\n" "Report-Msgid-Bugs-To: aptitude@packages.debian.org\n" "POT-Creation-Date: 2008-09-05 16:05+0200\n" "PO-Revision-Date: 2008-05-16 03:35+0900\n" "Last-Translator: Noritada Kobayashi <nori1@dolphin.c.u-tokyo.ac.jp>\n" "Language-Team: Japanese\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=1; plural=0;\n" |
なお、 ここでは省略しましたが、 筆者は、 メッセージカタログ内での用語統一を容易にするため、 aptitude や Subversion な ど大規模な PO では、 ヘッダのコメントに対訳表を含めています。
ここまでで、 PO のエントリの書式についてざっと見ました。
PO のエントリについては、 msgid と msgstr から成るもの以外にも、 複数形への対応として msgid、 msgid_plural、 msgstr[n] から成るものがあります。 詳しくは GNU gettext のドキュメン ト*2 の 『3 The Format of PO Files』 を参照してください。
PO で翻訳作業を行うには PO 編集ツールが便利です。 PO はテキストなのでどんなテキストエディタでも編集できますが、 翻 訳に含まれる「"」 や「\」 を手でエスケープするのは厄介です。 そのような機械的な処理は、 PO に特化した PO 編集ツールに 任せるのがよいでしょう。 また、 PO 編集ツールには翻訳支援機能を持つものもあるので、 作業効率も上がるはず です。
PO 編集ツールとしてよく知られているのは、 Emacs の PO 専用メジャーモードである po-mode、 KDE の PO 編集スイー トである KBabel、 GNOME の PO エディタである Gtranslator、 そして poedit です。
ここでは、 筆者が慣れている po-mode について、 筆者がよく使う操作だけざっと説明します。 説明中で何度も登場する「選 択エントリ」 とは「現在カーソルがあるエントリ」 の意味です。
まず、 エントリ間の移動には以下のようなキー操作が使えます。
また選択エントリの操作には以下のようなキー操作が使えます。
編集用バッファでは通常の Emacs の編集操作ができます。 特殊な操作は以下のとおりです。
最後に、 メインバッファでの PO 全体に関わる操作は以下のとおりです。
以上の簡単な説明から分かると思いますが、 po-mode は移動や編集がしやすく、 非常に便利です。
ただ、 po-mode には今のところ翻訳メモリのような機能はありません。 KBabel や Gtranslator は翻訳メモリを備えている ので、 翻訳メモリに興味のあるかたはこれらを試してみるのもよいでしょう。
翻訳作業には PO 編集ツールを使うことになるでしょうが、 一方で GNU gettext が提供する、 PO や POT に対してコマンド ラインから自動処理できるツール群も、 知っておくと便利です。 以下でざっと説明します。
開発者が主に使うのはxgettextとmsgmerge、 msgfmtですが、 他のツールも使いこなせるようになっておくと便利です。 使い方は各ツールのマニュアルページを参照してください。
PO はプログラム翻訳のために作られたファイル形式で、 参照コメントのような翻訳に有用な情報や、 fuzzy エントリのような 翻訳作業・保守作業の効率を上げるための仕組みを含んでいることを説明しました。 また、 PO という書式に特化した編集ツー ルについても説明しました。
プログラム翻訳のために生み出された PO は、 翻訳者にとって翻訳と保守の両方の作業をしやすい環境を提供する存在となり ました。 その理由としては以下のようなものが考えられます。
一方でドキュメント翻訳については、 通常は原文をそのままコピーして翻訳作業を開始するため、 翻訳以外の部分 (インデン ト、 ドキュメント内での位置など) に変更があった場合、 その影響を翻訳者が受けます。 プログラム翻訳と比べて分量が多いの に保守性が低いので、 結果として翻訳者への負担は非常に大きくなります。 この状況は、 翻訳者にとって大きな悩みの種で した。
そこで生まれたのが、 ドキュメント翻訳に対しても PO を使おうという考え方です。 具体的には、 ドキュ メントの各ブロックをエントリとした PO を作り、 ドキュメントと PO とを相互変換できるようにするこ とで、 翻訳者が PO での翻訳管理に集中できるようにします。 以下のツールがそのような思想で作られてい ます。
poxml や xml2po が DocBook XML のみを扱うツールであるのに対し、 Po4a が様々な形式をサポートしているのは、 おそ らく GNOME や KDE と Debian の立場の違いを反映しているのでしょう。 GNOME や KDE はプロジェクト内でドキュメン ト形式を DocBook XML に統一できますが、 ディストリビュータである Debian では、 様々なソフトウェアの様々なドキュメ ントに対応する必要があるのです。
以降のセクションでは、 ドキュメント翻訳に PO を使用する 3 つのツールのうち、 唯一複数のドキュメント形式をサポート し て い る Po4a について見ていきます。
Po4a というソフトウェア名は、 「po for anything」 から来ています。 名前からも分かるように、 最初から様々なドキュメント 形式の翻訳を PO で管理することを目的としており、 そのために入力形式として複数の形式を扱うことを想定した作りとなっ ています。
例えば、 以下のような形式が現在サポートされています。
サポートされている形式の一覧は、 po4a-gettextize、 po4a-translate、 po4a-updatepoなどのコマンドに--help-formatオプションを 与えると表示できます*5 。 コマンドに--format (-f) などを与えてドキュメント形式を指定する場合、 この一覧に載っている名前を使用してくだ さい。
noritada[3:39]% po4a-gettextize --help-format terra:~/svnwc/build-common/doc
有効フォーマット一覧: - dia: 非圧縮 Dia ダイアグラム。 - docbook: Docbook XML。 - guide: Gentoo Linux の xml ドキュメントフォーマット。 - ini: .INI フォーマット。 - kernelhelp: 各カーネルのコンパイルオプションのヘルプメッセージ。 - latex: LaTeX フォーマット。 - man: 古き良きマニュアルページフォーマット。 - pod: Perl オンラインドキュメントフォーマット。 - sgml: debiandoc と docbook DTD の双方。 - texinfo: info ページフォーマット。 - tex: 汎用 TeX ドキュメント (latex を参照)。 - text: シンプルなテキストフォーマット。 - wml: WML ドキュメント。 - xhtml: XHTML ドキュメント。 - xml: 汎用 XML ドキュメント (docbook を参照)。 |
Po4a を使ってドキュメントの翻訳をする場合、 最初にすべきことは、 原文のドキュメントファイルから POT を生成すること です。 POT の生成にはpo4a-gettextizeコマンドを使用します。 -fオプションの引数にドキュメントファイルの形式を、 -m オプションの引数に原文ドキュメントファイル (マスタードキュメント) の名前を、 -pオプションの引数に出力する POT の ファイル名を与えて、 コマンドを実行します。 -Mオプションの引数で、 原文ドキュメントファイルの文字セットを指定するこ とも可能です。
特に問題がない場合はすんなりとコマンドの実行が終了し、 POT が生成されます。 ドキュメントの構造に問題がある場合 (例えば XML においてタグがきちんと閉じられていない場合) はエラーになります。
POT が生成されたら、 翻訳作業はプログラム翻訳の場合と同じです。 POT をコピーして PO を作成し、 ヘッダを適切に設 定した上で翻訳作業を始めましょう。
例 次の例では、 hoge.en.htmlという XHTML ドキュメントからhoge.potを生成しています。
hoge.en.html (入力):
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en"> <head> <title>Test file</title> </head> <body> <h1>Test file</h1> <p>This is an <a href="apple">apple</a>.</p> <p>This is an <a href="orange">orange</a>.</p> </body> </html> |
コマンドライン:
noritada[14:14]% po4a-gettextize -v -f xhtml -m hoge.en.html -p hoge.pot
|
hoge.pot (出力):
# SOME DESCRIPTIVE TITLE
# Copyright (C) YEAR Free Software Foundation, Inc. # This file is distributed under the same license as the PACKAGE package. # FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. # #, fuzzy msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "POT-Creation-Date: 2008-09-20 14:21+0900\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Language-Team: LANGUAGE <LL@li.org>\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: ENCODING" # type: Attribute ’xml:lang’ of: <html> #: hoge.en.html:4 hoge.en.html:4 msgid "en" msgstr "" # type: Content of: <html><body><h1> #: hoge.en.html:6 hoge.en.html:9 msgid "Test file" msgstr "" # type: Content of: <html><body><p> #: hoge.en.html:10 msgid "This is an <a href=\"apple\">apple</a>." msgstr "" # type: Content of: <html><body><p> #: hoge.en.html:11 msgid "This is an <a href=\"orange\">orange</a>." msgstr "" |
原文と同じ形式で翻訳したドキュメントが既にあり、 それを Po4a 用の PO に移行したい場合にも、 po4a-gettextizeが使え ます。 「POT をコピーして PO を作った上で、 翻訳ドキュメントの各ブロックをコピー ・アンド・ペーストで PO の各エント リに埋め込む」 という、 間違いなくうんざりする作業は不要です。
ただしこの場合、 どの原文がどの訳文に対応するかを Po4a が把握する必要があるので、 原文ドキュメントファイルと翻訳ド キュメントファイルが同じ構造であることが前提になります。 「同じ構造」 とは、 Po4a が切り分ける単位、 つまりブロックのレ ベルで見たときに、 対応する要素が同じ順序で並んでいる、 という意味です。 もし翻訳側でブロックの追加や削除が行われてい たら、 変換はエラーで終わるでしょう。 一部のブロックの順序が入れ替わっている場合、 変換は見た目は無事に終 わるかもしれませんが、 入れ替わったブロックの msgid と msgstr の対応関係はおかしくなっているはず です。
訳注や翻訳者情報を別個のブロックとして翻訳ドキュメントに追加している場合、 それは一旦取り除いてください。 Po4a で は、 PO から翻訳ドキュメントを生成する際に、 原文にはない要素を追加する方法が提供されています。 方法については後述し ます。
原文ドキュメントファイルと翻訳ドキュメントファイルが同じ構造であれば、 po4a-gettextizeを用いた変換は成功するは ずです。 -fオプションの引数にドキュメントファイルの形式を、 POT を生成する場合の一連のオプションに加えて、 -lオプ ションの引数に翻訳ドキュメントファイルの名前を与えてコマンドを実行します。 -Lオプションの引数で、 翻訳ドキュメント ファイルの文字セットを指定することも可能です。
変換に成功すると、 すべてのエントリに fuzzy フラグが設定された PO が生成されます。 すべてのエントリに fuzzy フラグ が設定されるのは、 「ざっとでもいいので、 ユーザには変換後にすべてのエントリの原文と訳文を確認してほしい」 という開発 者の意図を反映したものですユーザが自由に編集できる普通のドキュメントに少し制限を与えて Po4a の管理下に置 く*6 際に は 、 何 か し ら の 問 題 が 発 生 し て い る 可 能 性 が あ る の で す 。
例 以下では、 先程のhoge.en.htmlに対応する日本語訳hoge.ja.htmlを PO に変換することを試みます。
まずは、 とりあえずpo4a-gettextizeを実行してみました。
hoge.ja.html (入力):
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" lang="ja" xml:lang="ja"> <head> <title>テストファイル</title> </head> <body> <h1>テスト用のファイル</h1> <p>これは<a href="apple">リンゴ</a>です。 </p> <p>これは<a href="orange">オレンジ</a>です。 </p> <p>(訳注: オレンジはミカンとは違います。 )</p> </body> </html> |
コマンドライン:
noritada[14:54]% po4a-gettextize -v -f xhtml -m hoge.en.html -l hoge.ja.html -p ja.po
po4a gettextize: Original has less strings than the translation (6<7). Please fix it by removing the extra entry from the translated file. You may need an addendum (cf po4a(7)) to reput the chunk in place after gettextization. A possible cause is that a text duplicated in the original is not translated the same way each time. Remove one of the translations, and you’re fine. po4a gettextization: Structure disparity between original and translated files: msgid (at hoge.en.html:6 hoge.en.html:9) is of type ’Content of: <html><body><h1>’ while msgstr (at hoge.ja.html:6) is of type ’Content of: <html><head><title>’. Original text: Test file Translated text: テストファイル (result so far dumped to gettextization.failed.po) The gettextization failed (once again). Don’t give up, gettextizing is a subtle art, but this is only needed once to convert a project to the gorgeous luxus offered by po4a to translators. Please refer to the po4a(7) documentation, the section "HOWTO convert a pre-existing translation to po4a?" contains several hints to help you in your task |
訳注を独立したパラグラフにしたために PO への変換が失敗したと考え、 訳注の行を削ってもう一度po4a-gettextizeを 実行してみます。 入力ファイルの内容は省略します。
コマンドライン:
noritada[14:55]% po4a-gettextize -v -f xhtml -m hoge.en.html -l hoge.ja.html -p ja.po
po4a gettextization: Structure disparity between original and translated files: msgid (at hoge.en.html:6 hoge.en.html:9) is of type ’Content of: <html><body><h1>’ while msgstr (at hoge.ja.html:6) is of type ’Content of: <html><head><title>’. Original text: Test file Translated text: テストファイル (result so far dumped to gettextization.failed.po) The gettextization failed (once again). Don’t give up, gettextizing is a subtle art, but this is only needed once to convert a project to the gorgeous luxus offered by po4a to translators. Please refer to the po4a(7) documentation, the section "HOWTO convert a pre-existing translation to po4a?" contains several hints to help you in your task |
なんだか変なエラーが出てしまっています。 どうも、 titleとh1の原文がともに「Test file」 なのに、 一方の訳は「テスト ファイル」 で、 他方の訳が「テスト用のファイル」 となっていることに原因があるようです。 そこで、 両方の訳を統一して po4a-gettextizeにかけると、 変換に成功します。
hoge.ja.html (入力):
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" lang="ja" xml:lang="ja"> <head> <title>テストファイル</title> </head> <body> <h1>テストファイル</h1> <p>これは<a href="apple">リンゴ</a>です。 </p> <p>これは<a href="orange">オレンジ</a>です。 </p> </body> </html> |
コマンドライン:
noritada[15:07]% po4a-gettextize -v -f xhtml -m hoge.en.html -l hoge.ja.html -p ja.po
|
ja.po (出力):
# SOME DESCRIPTIVE TITLE
# Copyright (C) YEAR Free Software Foundation, Inc. # This file is distributed under the same license as the PACKAGE package. # FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. # #, fuzzy msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "POT-Creation-Date: 2008-09-20 15:07+0900\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Language-Team: LANGUAGE <LL@li.org>\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: ENCODING" # type: Attribute ’xml:lang’ of: <html> #: hoge.en.html:4 hoge.en.html:4 #, fuzzy msgid "en" msgstr "ja" # type: Content of: <html><body><h1> #: hoge.en.html:6 hoge.en.html:9 #, fuzzy msgid "Test file" msgstr "テストファイル" # type: Content of: <html><body><p> #: hoge.en.html:10 #, fuzzy msgid "This is an <a href=\"apple\">apple</a>." msgstr "これは<a href=\"apple\">リンゴ</a>です。 " # type: Content of: <html><body><p> #: hoge.en.html:11 #, fuzzy msgid "This is an <a href=\"orange\">orange</a>." msgstr "これは<a href=\"orange\">オレンジ</a>です。 " |
po4a-translate
po4a-updatepo
po4a
第 44 回東京エリア Debian 勉強会 2008 年 9 月
____________________________________________________________________________________________