Previous: , Up: Perl   [Contents][Index]


15.5.18.9 バグ、落とし穴、動作しない事柄

ここまでのセクションでは、Perlのソースから翻訳可能な文字列を抽出点において、xgettextがとてもスマートであることが証明されました。しかし動作すると期待されていたエキゾチックな構成物のうちのいくつかは、多かれ少なかれ動作しません。

それに関係する制限のうちの1つは、クォートされた文字列内の変数の補間に関する実装で見つけることができます。クォートされた文字列の場合、単純なhash lookupしか使うことができません:

print <<EOF;
$gettext{"The dot operator"
          . " does not work"
          . "here!"}
Likewise, you cannot @{[ gettext ("interpolate function calls") ]}
inside quoted strings or quote-like expressions.
EOF

これは有効なPerlのコードであり、実行時には実際にgettext関数を呼び出します。しかしxgettextのPerl parserは、文字列の認識に失敗します。これほど明確ではない実相の制限は、正規表現の補間で見つけることができます:

s/<!--START_OF_WEEK-->/gettext ("Sunday")/e;

修飾子eは、評価可能なステートメントとして解釈して置き換えを行います。その結果、実行時にgettext()関数が呼び出されまが、この場合もparserは文字列“Sunday”を抽出することに失敗します。この機能を本当に使いたいならば、シンプルな回避策は一時的な変数を使うことです:

my $sunday = gettext "Sunday";
s/<!--START_OF_WEEK-->/$sunday/;

hash slicesも手軽ですが、認識されません:

my @weekdays = @gettext{'Sunday', 'Monday', 'Tuesday', 'Wednesday',
                        'Thursday', 'Friday', 'Saturday'};
# Or even:
@weekdays = @gettext{qw (Sunday Monday Tuesday Wednesday Thursday
                         Friday Saturday) };

これはtied hash %gettextの完全に有効な使い方ですが、文字列は認識されないため、抽出もされません。

現在のバージョンにたいするその他の注意点は、識別子の中の非アスキー文字にたいするお粗末なサポートがあげられます。’A’-’Z’、’a’-’z’、’0’-’9’、およびアンダースコアー ’_’ の範囲外の文字を識別子に使った場合、あなたは深刻な問題に直面するでしょう。

これらの存在しない機能のうちのいくつかは将来のバージョンで実装されるかもしれませんが、最小限の努力により回避できるものばかりなので、開発の優先度は低くなっています。

たちの悪いのは、普通のテキストの中の一部にすでにbraceが含まれているようなbrace format stringsの問題です。たとえば、プログラムの使い方を説明する文字列は、プログラムの中で普通に出会うものです:

die "usage: $0 {OPTIONS} FILENAME...\n";

このPerlのbrace format stringsを含んだコードをインターナショナライズしようとすると、問題が起きます:

die __x ("usage: {program} {OPTIONS} FILENAME...\n", program => $0);

{program}’はplaceholderです。一方‘{OPTIONS}’はplaceholderではなく、おそらく翻訳される必要があります。しかし最初のものを認識して、他のものをそのままにしておくようにxgettextのPerl parserに教える術はありません。

この問題を回避するためには2つの方法が考えられます。プログラムが(printf()で位置パラメーターを扱える)Perl 5.8.0以降で実行されることがわかっている場合か、翻訳者が引数の順番を変える必要がないことがわかっている場合 – たとえば文字列に1つしかbraceのplaceholderがない場合や、上記の例のように構文を説明するためのものの場合 – 文字列をno-perl-brace-formatとマークしてprintf()を使うことができます:

# xgettext: no-perl-brace-format
die sprintf ("usage: %s {OPTIONS} FILENAME...\n", $0);

もっと可搬性のあるPerlのbrace formatを使いたいときは、placeholdersをリテラルのbracesの中に配置します:

die __x ("usage: {program} {[}OPTIONS{]} FILENAME...\n",
         program => $0, '[' => '{', ']' => '}');

Perlのbrace を使った書式文字列は、エスケープするための仕組みを知りません。このエスケープするための仕組みがどのようなものであれ、これはプログラマーに困難な時をもたらし、Perlのbrace を使った書式文字列の翻訳を困難にするか、format命令が実行されるときの実行時の性能を劣化させるでしょう。このような特別なケースでは、printf()のために幸せな時間のほとんどを費やすことになります。