Next: Using libintl.a, Previous: gettext, Up: Programmers [Contents][Index]
以下の議論は幾分誇張されたものかもしれません。これまで述べてきたように、わたしたちはUniforumの勧告にしたがう理由があって、GNU
gettext
を実装しました。しかし、どのようにしてこの決定に至ったかをお見せするべきでしょう。
最初に開発プロセスを概観してみましょう。わたしたちがgettext
により提供されるNLSを使ってアプリケーションを記述するときは、いつものとおり処理のことです。ユーザーの目に触れるので文字列を翻訳する必要があるときだけ、わたしたちは"…"
のかわりにgettext("…")
を使って翻訳を行います。各ソースファイル(または中核となるヘッダーファイル)で、以下を定義します
#define gettext(String) (String)
この定義により、システムのCライブラリー自体でgettext
がサポートされていても、それを無効化できます。このコードをコンパイルすると、NLSコードを使わない場合と同じ結果が得られます。GNU
gettext
のコードを見ると、gettext("…")
のかわりに_("…")
を使っているのがわかるでしょう。これにより翻訳可能な文字列のために余分にタイプしなければならない文字数を3文字まで減らせます。
これを出荷するバージョンのプログラムにする場合は、単に以下の定義
#define _(String) (String)
を、以下の定義に置き換えるだけで済みます。
#include <libintl.h> #define _(String) gettext (String)
そして、翻訳可能な文字列を含むすべてのソースファイルにたいしてxgettextプログラムを実行します。わたしたちは翻訳が利用できないものにたいしても、利用可能になったら使えるように、プログラムを実行します。
同様のことはgettext_noop
呼び出しでも行うことができます(Special casesを参照してください)。gettext_noop
は通常、no-op(訳注: no-operation = 何もしない)
マクロとして定義します。プロジェクトでは以下のようなコードを考慮する必要があります:
#define gettext_noop(String) String #define N_(String) gettext_noop (String)
N_
は、_
と同様、省略形です。GNU
gettext
のpo/ディレクトリーにあるMakefileは、これらの省略形を認識するので、必要に応じて使うことができます。
今度はcatgets
を見てみましょう。主な問題点はプログラマー向けの機能にあります。彼は、翻訳可能な文字列ごとに、毎回異なる数字(または記号定数)を割り当てる必要があります。彼は重複したエントリー、重複したメッセージID、etc...にも注意を払わなければなりません。もしGNU
gettext
プログラムが提供するのと同じ品質をメッセージカタログにもたせたい場合、文字列にたいする説明コメントやソースコード中での場所をメッセージカタログに記述しなければなりません。これはほとんどMission:
Impossibleでしょう。
しかしcatgets
の優位性を語る人たちが触れる点もいくつかあります。文字列内にある単語があり、その文字列が異なるコンテキストや他の言語で使われている場合に、その単語は異なる翻訳をもつことができます。以下に例を示しましょう:
printf ("%s: %d", gettext ("number"), number_of_errors) printf ("you should see %d %s", number_count, number_count == 1 ? gettext ("number") : gettext ("numbers"))
この例では、"number"
という文字列を2回翻訳する必要があります。たとえあなたがEnglishに類する言語を話さなくても、この単語が2つの文で異なる意味をもつかもしれないことに気づくでしょう。Germanでは、1番目にたいして"Anzahl"
、2番目には"Zahl"
と翻訳する必要があります。
これであなたはこのが難解な例だということに同意するでしょう。そしてあなたは間違っていません! では問題を正確に把握して、その問題がそれほど深刻ではないことにも気づくはずです。この問題は以下のようにして簡単に解決することができます:
printf ("%s %d", gettext ("number:"), number_of_errors) printf (number_count == 1 ? gettext ("you should see %d number") : gettext ("you should see %d numbers"), number_count)
わたしたちは、この方法で文字列の競合はすべて解決できると信じます。もし競合する文字列の一方を変更するのが困難なら、もう一方の文字列を少しだけ変更することも考慮できます。これを克服するのは不可能ではありません。
catgets
は、同じ元文字列にたいして異なる翻訳をもたせることができます。gettext
では同じ元文字列にたいして異なる翻訳をもたせることはできませんが、この種のあいまいさによる問題を解決する、よりスケーラブルな解決策があります。Ambiguitiesを参照してください。