LOCALE::PO4A::TRANSTRACTOR.3PM(1)

名前
Locale::Po4a::TransTractor - 汎用翻訳抽出機構。

説明
po4a (PO for anything) プロジェクトは、gettext ツールが想定していないドキュメントのような領域で翻訳をしやすくすること (またより興味深いのは、翻訳文の保守がしやすくなること) を目標にしています。

このクラスは、翻訳可能な文字列を検索するためのドキュメントのパース、PO ファイルへの抽出、出力したドキュメントへの翻訳した文字列の置換に使用する、すべての po4a パーサの祖先になります。

もっと形式張って言うと、入力として以下の引数を取ります:

-   翻訳する文書；

-   使用する翻訳を含むPO ファイル。

以下を出力します:

-   入力ドキュメントから翻訳可能な文字列を抽出した、別の PO ファイル。

-   入力したものと同じ構造で、入力した PO ファイルにある翻訳で翻訳可能な文字列を置換した、翻訳済みドキュメント。

これを視覚的に表すと次のようになります:

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

個別のパーサでオーバーライドするべき関数

parse()
    ここに、入力ドキュメントのパース、出力の生成、翻訳可能文字列の抽出といった、すべての動作を定義しています。後述する 内部関数 節で説明する提供された関数を使用するのはかなり簡単です。サンプル付きの 書式 も参照してください。

    この関数は後述の process() 関数から呼ばれますが、new() 関数を使用してドキュメントに内容を手で追加するのを選んだ場合、この関数自体を呼ばねばなりません。

docheader()
    この関数は、ターゲットの言語でコメントにするために適切にクォートした、生成したドキュメントに追加するべきヘッダを返します。この何がよいのかは、po4a(7) の 翻訳についての開発者教育 節を参照してください。

書式
以下の例は、"<p>" で始まる段落のリストをパースします。簡単にするために、ドキュメントは整形されている、すなわち、現れるタグは '<p>' のみで、各段落はこのタグで必ず始まると仮定します。

 sub parse {
   my $self = shift;

   PARAGRAPH: while (1) {
       my ($paragraph,$pararef)=("","");
       my $first=1;
       my ($line,$lref)=$self->shiftline();
       while (defined($line)) {
           if ($line =~ m/<p>/ && !$first--; ) {
               # <p> があったのは初めてではありません。
               # 入力に現在の行を再追加します。
               # そして、構築された段落を出力に追加します
               $self->unshiftline($line,$lref);

               # 文書が形成されたため、翻訳します：
               #   - 先頭のタグを削除
               $paragraph =~ s/^<p>//s;

               #   - （翻訳されていない）先頭のタグを出力に追加し、
               #     （翻訳されている）残りの段落を追加します
               $self->pushline(  "<p>"
                               . $self->translate($paragraph,$pararef)
                               );

               next PARAGRAPH;
           } else {
               # 段落に連結
               $paragraph .= $line;
               $pararef = $lref unless(length($pararef));
           }

           # 繰り返しの初期化処理を改めて
           ($line,$lref)=$self->shiftline();
       }
       # 定義された行が得られませんでしたか？入力ファイルの終わりです。
       return;
   }
 }

parse 関数を実装したら、次節で説明するパブリックインターフェースを用いて document クラスを使用できます。

パーサで使用するスクリプトのパブリックインターフェース

  コンストラクタ

process(%)
    この関数は、po4a ドキュメントで行うのに必要なすべてを、一度の実行で行います。引数はハッシュとしてパックしなくてはなりません。動作は以下のようになります:

    a.  po_in_name で指定したすべての PO ファイルの読み込み

    b.  file_in_name で指定したすべてのオリジナルドキュメントの読み込み

    c.  ドキュメントのパース

    d.  指定したすべての追加内容の読み込みと適用

    e.  翻訳したドキュメントの file_out_name への書き出し (与えられた場合)

    f.  抽出した PO ファイルの po_out_name への書き出し (与えられた場合)

    new() で受け付けるもの以外の引数 (と想定する型):

    file_in_name (@)
        読み込むべき入力ドキュメントのファイル名のリストです。

    file_in_charset ($)
        入力文書で使用する文字集合です（指定しない場合、UTF-8を使用）。

    file_out_name ($)
        書き出すべき出力ドキュメントのファイル名です。

    file_out_charset ($)
        出力文書で使用する文字集合です（指定しない場合、UTF-8を使用）。

    po_in_name (@)
        読み込むべき入力 PO ファイル (ドキュメントの翻訳に使用する翻訳) のファイル名のリストです。

    po_out_name ($)
        入力ドキュメントから抽出した文字列を含む、書き出すべき出力 PO ファイルのファイル名です。

    addendum (@)
        読み込むべき追加内容のファイル名のリストです。

    addendum_charset ($)
        追加内容の文字セット。

new(%)
    新規 po4a ドキュメントを作成します。以下の（引数として渡されたハッシュの）オプションを受け取ります：

    verbose ($)
        冗長表示を有効にします。

    debug ($)
        デバッグを有効にします。

    wrapcol ($)
        出力文書でテキストを折り返す列です（既定は76）。

        負値は行を全く折り返さない意味です。

    通底するPoファイルは次のオプションも受け付けます。すなわちporefs, copyright-holder, msgid-bugs-address, package-name, package-version, wrap-poです。

  ドキュメントファイルの操作

read($$$)
    既存の配列 "@{$self->{TT}{doc_in}}" の末尾に別の入力文書データを加えます。

    この関数は2つの必須の実引数と1つの省略できる実引数を取ります。
     * ディスクから読むファイル名
     * POファイルで参照を構成するときにファイル名として使う名前
     * そのファイルを読むために使う文字集合（既定でUTF-8）

    この配列 "@{$self->{TT}{doc_in}}" にはこの入力文書のデータが 別の意味合いを持つ文字列の配列として保管されています。
     * 文字列 $textline には入力テキストデータのそれぞれの行が含まれます。
     * 文字列 "$filename:$linenum" には位置が含まれており
       「参照」と呼ばれます（"linenum"は1始まりです）。

    パースは一切行わないことに注意してください。入力ファイルがドキュメントに格納した時点で parse() 関数を使用するべきです。

write($)
    与えたファイル名で翻訳済みドキュメントを書き出します。

    この翻訳された文書データは以下によって与えられます。
     * "$self->docheader()" はプラグインのヘッダテキストを保有します。また、
     * "@{$self->{TT}{doc_out}}" は配列に翻訳されたメインのテキストのそれぞれの行を保有します。

  PO ファイルの操作

readpo($)
    既存の入力 PO に、(引数で渡した名前の) ファイルの内容を追加します。古い内容は破棄されません。

writepo($)
    抽出した PO ファイルを与えたファイル名で書き出します。

stats()
    現在までに翻訳した内容に関する統計を返します。msgfmt --statistic が出力する統計とは同じとは限らないことに注意してください。ここでは、PO ファイルの最新の使用法についての統計ですが、msgfmt が報告するのは、ファイルの状態についてです。これは、Locale::Po4a::Po::stats_get 関数を入力した PO ファイルに適用するラッパーです。サンプルは以下のようになります:

        [po4a文書の通常の利用……]

        ($percent,$hit,$queries) = $document->stats();
        print "$percent\%（$queries中$hit）の文字列の翻訳があります。\n";

  追加内容の操作

addendum($)
    追加内容とは何か、や、翻訳者はどのように書いたらよいのかといった情報は、po4a(7) を参照してください。翻訳したドキュメントに追加内容を適用するには、この関数に単純にファイル名を渡し、実行するだけです ;)

    この関数は、エラー時に null 以外の数値を返します。

派生パーサ作成時に使用する内部関数

  入力と出力
入力を取得し出力を返すために4つの関数が提供されています。これらはPerlのshift/unshiftとpush/popに大変似ています。

 * Perlのshiftは最初の配列の要素を返し配列からその要素を切り落とします。
 * Perlのunshiftは配列に要素をその配列の最初の要素として前置します。
 * Perlのpopは配列の最後の要素を返しそれを配列から切り落とします。
 * Perlのpushは配列にその配列の最後の要素として後置します。

1つ目の対は入力についてのもので、2つ目は出力についてのものです。覚え方としては、入力ではshiftにより得られる最初の行に関心があり、出力ではpushがするように結果を末尾に加えたいのだ、とできます。

shiftline()
    この関数は解析される最初の行と配列"@{$self->{TT}{doc_in}}"からの（配列として詰め込まれた）参照を返し、これらの配列の最初2つの要素を除きます。ここで参照は文字列"$filename:$linenum"によって与えられます。

unshiftline($$)
    入力文書の最後にshiftされた行をunshiftして対応する参照を"{$self->{TT}{doc_in}}"の先頭に戻します。

pushline($)
    "{$self->{TT}{doc_out}}"の末尾に開業を押し込みます。

popline()
    "{$self->{TT}{doc_out}}"の末尾から最後に押し込んだ行を取り出します。

  文字列を翻訳可能としてマーク
翻訳するべきテキストを扱う関数を一つ用意しています。

translate($$$)
    必須の引数:

    -   翻訳する文字列

    -   この文字列の参照 (言い換えると、入力ファイルの場所)

    -   文字列の型 (つまり構造上の役割をテキストで説明したもの。Locale::Po4a::Po::gettextization() で使用します。 po4a(7) の gettext 化: どのように動作しますか? 節も参照してください)

    この関数は、いくつか追加引数を取れます。ハッシュとしてまとめなければなりません。例えば:

      $self->translate("string","ref","type",
                       'wrap' => 1);

    wrap
        文字列中の空白が重要でないとして扱うかどうかを示す真偽値です。重要でない場合、この関数は、翻訳を探したり抽出したりする前の文字列を納め、翻訳を折り返します。

    wrapcol
        折り返す列です（既定ではTransTractor作成時に指定された wrapcol 値か76）。

        負値は既定値から差し引きます。

    comment
        エントリに追加する更なるコメント。

    動作:

    -   文字列、参照、型を po_out に push します。

    -   パーサが doc_out をビルドできるように、文字列の翻訳 (po_in に見つかったもの) を返します。

    -   文字列を po_out に送る前や翻訳を返す前に、文字列を再コード化する文字セットを扱います。

  その他の関数

verbose()
    TransTractor の生成時に verbose オプションが渡された場合、返します。

debug()
    TransTractor の生成時に debug オプションが渡された場合、返します。

get_in_charset()
    この関数はマスター文書の文字集合として与えられる文字集合を返します

get_out_charset()
    この関数は、出力文書で使用する文字セットを返します（この関数により見付かった入力文書で検出された文字セットを置き換えるのに、大抵の場合で便利です）。

    コマンドラインで指定した出力文字セットが使われます。指定しない場合は、入力 PO ファイルの文字セットを使用します。入力 PO ファイルにデフォルトの "CHARSET" がある場合は、入力ドキュメントの文字セットを返します。そして、エンコーディングの変換は行われません。

将来の方向性
現在の TransTractor の欠点の一つに、(debconf テンプレートや、.desktop ファイルのような) すべての言語を含む翻訳済みドキュメントを扱えないというものがあります。

この問題に対処するには、以下のようにインターフェースのみを変更することが必要です:

-   po_in_name (言語ごとのリスト) としてハッシュを取ります

-   対象言語を示すための翻訳する引数を追加します

-   pushline_all 関数を作ります。この関数により全ての言語を対象とする内容のpushlineを生み出します。これにはmapのような構文が使われます。

        $self->pushline_all({ "Description[".$langcode."]=".
                              $self->translate($line,$ref,$langcode)
                            });

これで十分だといいのですが ;)

著者
 Denis Barbier <barbier@linuxfr.org>
 Martin Quinson (mquinson#debian.org)
 Jordi Vilalta <jvprat@gmail.com>

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