Locale::Po4a::TransTractor(3pm)

名前
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--; ) {
               # Not the first time we see <p>.
               # Reput the current line in input,
               #  and put the built paragraph to output
               $self->unshiftline($line,$lref);

               # Now that the document is formed, translate it:
               #   - Remove the leading tag
               $paragraph =~ s/^<p>//s;

               #   - push to output the leading tag (untranslated) and the
               #     rest of the paragraph (translated)
               $self->pushline(  "<p>"
                               . $self->translate($paragraph,$pararef)
                               );

               next PARAGRAPH;
           } else {
               # Append to the paragraph
               $paragraph .= $line;
               $pararef = $lref unless(length($pararef));
           }

           # Reinit the loop
           ($line,$lref)=$self->shiftline();
       }
       # Did not get a defined line? End of input file.
       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 ($)
        入力ドキュメントで使用している文字セットです (指定しない場合、入力ドキュメントから検出しようとします)。

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

    file_out_charset ($)
        出力ドキュメントで使用する文字セットです (指定しない場合、PO ファイルの文字セットを使用します)。

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

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

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

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

new(%)
    Create a new po4a document. Accepted options (in the hash passed as a parameter):

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

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

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

read($$)
    Add another input document data at the end of the existing array "@{$self->{TT}{doc_in}}". The argument is the filename to read. If a second argument is provided, it is the filename to use in the references.

    This array "@{$self->{TT}{doc_in}}" holds this input document data as an array of strings with alternating meanings.
     * The string $textline holding each line of the input text data.
     * The string "$filename:$linenum" holding its location and called as
       "reference" ("linenum" starts with 1).

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

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

    This translated document data are provided by:
     * "$self->docheader()" holding the header text for the plugin, and
     * "@{$self->{TT}{doc_out}}" holding each line of the main translated text in the array.

  PO ファイルの操作

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

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

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

        [po4a ドキュメントの通常の使用...]

        ($percent,$hit,$queries) = $document->stats();
        print "We found translations for $percent\%  ($hit from $queries) of strings.\n";

is_po_uptodate()
    Returns ($uptodate, $diagnostic) where $uptodate is whether the input po and the output po match (if not, it means that the input po should be updated) and $diagnostic is a string explaining why the po file is not uptodate, when this happens.

  追加内容の操作

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

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

INTERNAL FUNCTIONS used to write derivative parsers

  入力と出力
Four functions are provided to get input and return output. They are very similar to shift/unshift and push/pop of Perl.

 * Perl shift returns the first array item and drop it from the array.
 * Perl unshift prepends an item to the array as the first array item.
 * Perl pop returns the last array item and drop it from the array.
 * Perl push appends an item to the array as the last array item.

The first pair is about input, while the second is about output. Mnemonic: in input, you are interested in the first line, what shift gives, and in output you want to add your result at the end, like push does.

shiftline()
    This function returns the first line to be parsed and its corresponding reference (packed as an array) from the array "@{$self->{TT}{doc_in}}" and drop these first 2 array items. Here, the reference is provided by a string "$filename:$linenum".

unshiftline($$)
    Unshifts the last shifted line of the input document and its corresponding reference back to the head of "{$self->{TT}{doc_in}}".

pushline($)
    Push a new line to the end of "{$self->{TT}{doc_out}}".

popline()
    Pop the last pushed line from the end of "{$self->{TT}{doc_out}}".

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

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

    -   翻訳する文字列

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

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

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

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

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

    wrapcol
        改行を行う幅です (デフォルト: 76)。

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

    動作:

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

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

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

  その他の関数

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

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

detected_charset($)
    これは、入力ドキュメントから新しい文字セット (第一引数) を検出したと、TransTractor に伝えます。通常、ドキュメントのヘッダから読むことができます。process() の引数から来たものとドキュメントから検出したもののうち、最初の文字セットのみが対象となります。

get_out_charset()
    この関数は、出力ドキュメントで使用する文字セットを返します (入力ドキュメントの検出した (その場所にあった) 文字セットを置き換えるのに便利です)

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

recode_skipped_text($)
    この関数は、引数で渡したテキストを、入力ドキュメントの文字セットから、出力ドキュメントの文字セットへ、再コード化して返します。これは、文字列を翻訳する際には必要ありませんが (translate() は、自分ですべて再コード化します)、入力ドキュメントからの文字列をスキップし、出力ドキュメントを共通のエンコードで一致させたい場合に必要です。

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

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

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

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

-   make a pushline_all function, which would make pushline of its content for all languages, using a map-like syntax:

        $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>