Next: Special cases, Previous: Marking, Up: Sources [Contents][Index]
Cプログラム中の文字列は、しばしばprintf
ファミリーと呼ばれる関数呼び出しで使用されます。これらで使用される書式指定文字列に関して特筆すべきは、%で始まる書式指定子が含まれていることです。以下のようなコードがあるとしましょう。
printf (gettext ("String `%s' has %d characters\n"), s, strlen (s));
上記の文字列にたいして、以下のようなGermanの翻訳が考えられます:
"%d Zeichen lang ist die Zeichenkette `%s'"
Germanを話せないCプログラマーでも、まずい点があることに気がつくでしょう。文字列中の書式指定子の順序が変更されていますが、printf
の引数の順序は変更されません。一番問題なのは、文字列のアドレスが期待されている箇所に、文字列の長さが渡していることです。
翻訳に起因する実行時のエラーを防ぐために、msgfmt
は翻訳前の文字列と、翻訳後の文字列に含まれる引数のタイプと数を、静的にチェックすることができます。このチェックを満足しないような場合、msgfmt
に‘-c’が指定されていると、msgfmt
はエラーを発生させてMOファイルを生成しません。‘msgfmt
-c’を使用することにより、エラーを事前に検出して、実行時の問題を防ぐことができます。
Germanの翻訳で上述の単語順が正しい場合は、以下のように記述する必要があります
"%2$d Zeichen lang ist die Zeichenkette `%1$s'"
msgfmt
ルーチンは、この特別な表記法を認識できます。
プログラムのすべての文字列が書式文字列というわけではないので、.poファイルの中のすべての文字列をmsgfmt
がテストする必要はありません。また文字列の中に書式指定子と似た文字列が含まれるが、その文字列がprintf
で使われる文字列ではないような場合は、問題が発生します。
そのためxgettext
は、それらの書式文字列と思われるメッセージに特別なタグを付与します。このタグ付けは絶対的なルールではなく、発見的なルールです。.poファイルの中のそれらのエントリーには、#,
によるコメント行で、c-format
というフラグによりマークされます(PO Filesを参照してください)。
注意深い読者は、まだ問題があると気づくでしょう。発見されたものが間違っている場合です。これは真実であり、そのためにxgettext
は、プログラマーが意志決定すべき特別な種類のコメントを認識することができるのです。gettext
キーワードと同じ行、またはそれに続く行にxgettext:c-format
という単語を含むコメントを発見すると、xgettext
はどのような場合であれ、文字列をc-format
フラグでマークします。この種のコメントは、xgettext
が文字列を書式文字列と認識しない場合(テストしてみて実際に認識されない場合)に使う必要があります。gettext
キーワードと同じ行にコメントがある場合、翻訳される前にコメントを挿入しなければならないことに注意してください。
このような状況は頻繁に発生します。printf
関数にわたされる文字列に書式指定子が含まれない場合もあります。そのようなケースでは通常、fputs
を使用するのでしょうが、それでもこのような状況はあり得ます。このような場合、xgettext
はそれを書式文字列として認識しませんが、翻訳に書式指定子として認識されるような文字列が含まれていると何が起こるでしょうか?
printf
関数はパラメーターにアクセスしようとしますが、翻訳前の文字列には何も引数がわたされないため、パラメーターは存在しません。
もちろん他の原因により、xgettext
が間違って書式文字列ではない文字列を、書式文字列と認識することがあります。このような場合、msgfmt
は多くの警告を出力し、.poファイルへの変換は失敗します。このように間違って書式文字列と認識されるのを防ぐには、上記と同様にxgettext:no-c-format
という文字列を含むコメントを使用します。
文字列がc-format
と間違ってマークされている場合、ユーザーは何が原因なのか調べることができます。--debug
オプション使用して、どのように問題を解決するかについては、xgettext Invocationを参照してください。