★PostgreSQLカンファレンス2024 12月6日開催/チケット販売中★
他のバージョンの文書 16 | 15 | 14 | 13 | 12 | 11 | 10 | 9.6 | 9.5 | 9.4 | 9.3 | 9.2 | 9.1 | 9.0 | 8.4 | 8.3 | 8.2 | 8.1 | 8.0 | 7.4 | 7.3 | 7.2

57.2. プログラマへ

57.2.1. 仕組み

本節では、PostgreSQL配布物の一部であるプログラムやライブラリにおける各国語サポートの実装方法を説明します。 現在はCプログラムにのみ適用できます。

プログラムにNLSサポートを追加する

  1. プログラムの起動処理に以下のコードを追加してください。

    #ifdef ENABLE_NLS
    #include <locale.h>
    #endif
    
    ...
    
    #ifdef ENABLE_NLS
    setlocale(LC_ALL, "");
    bindtextdomain("progname", LOCALEDIR);
    textdomain("progname");
    #endif
    

    prognameは実際には自由に選択できます。)

  2. どこであろうと翻訳の候補となるメッセージが見つかったら、gettext()の呼び出しが追加される必要があります。 例えば、

    fprintf(stderr, "panic level %d\n", lvl);
    

    は、次のように変更されます。

    fprintf(stderr, gettext("panic level %d\n"), lvl);
    

    (NLSサポートが組み込まれていない場合、gettextはノーオペレーション命令として定義されます。)

    これは混乱しがちになります。一般的なショートカットは以下のものです。

    #define _(x) gettext(x)
    

    他の解決方法は、バックエンドにおけるereport()のように、そのプログラムが通信のほとんどを1つまたは数個の関数で行っている場合有効です。 その場合、この関数の内部で全ての入力文字列に対しgettextを呼び出すようにすることになります。

  3. プログラムのソースのあるディレクトリにnls.mkを追加してください。 これはmakefileとして読まれます。 以下の変数への代入をここで設定する必要があります。

    CATALOG_NAME

    textdomain()の呼び出しに使用されるプログラム名です。

    AVAIL_LANGUAGES

    用意された翻訳のリストです。初めは空です。

    GETTEXT_FILES

    翻訳可能文字列を含むファイルの一覧です。 つまり、これらはgettextもしくは他の解決法として印が付けられます。 結局、これはプログラムのほとんど全てのソースファイルを含むことになります。 この一覧があまりに長くなる場合、最初のfile+とし、2番目の単語を1行に対して1つのファイル名を持ったファイルとすることができます。

    GETTEXT_TRIGGERS

    翻訳者が作業を行う上で、どの関数呼び出しが翻訳可能文字列を含むかを知る必要に迫られた場合に、メッセージカタログを生成するツールです。 デフォルトでは、gettext()呼び出しのみを認識します。 _や他の識別子を使用した場合、ここに記載しなければなりません。 翻訳可能文字列がその最初の引数ではない場合、その項目は(例えば2番目の引数の場合)func:2という形式でなければなりません。 複数形メッセージをサポートする関数がある場合、その項目は(単一形および複数形メッセージ引数を特定する)func:1,2のようになります。

ビルドシステムは、自動的にメッセージカタログの構築およびインストールを行います。

57.2.2. メッセージ記述の指針

メッセージの翻訳を簡単にするために以下に指針をいくつか示します。

  • 以下のように実行時に文章を構築することはしないでください。

    printf("Files were %s.\n", flag ? "copied" : "removed");
    

    文章内の単語の順番は言語によって異なる可能性があります。 さらに全ての断章に対してgettext()を呼び出すことを覚えていたとしても、断章が個別に的確に翻訳されるわけではありません。 それぞれのメッセージが全て調和して翻訳されるかどうか、ちょっとしたコードの複製を用意するとよいかもしません。 番号、ファイル名、および実行時変数のみメッセージテキストに実行時に挿入するべきです。

  • 同様の理由で、以下も上手くいきません。

    printf("copied %d file%s", n, n!=1 ? "s" : "");
    

    これは複数形がどのように形成されるかを決めてかかっているからです。 もし、以下のようにして回避できたと考えると、

    if (n==1)
        printf("copied 1 file");
    else
        printf("copied %d files", n):
    

    失望することになります。 言語の中には、独特の規則によって2つ以上の形式になるものもあります。 問題全体を回避するためこのメッセージを設計することが最善です。たとえば以下のようにします。

    printf("number of copied files: %d", n);
    

    適切に複数形を持つメッセージを構築したいと本当に思うのなら、これに対するサポートがありますが、多少厄介です。 ereport()内の主たる、または詳細なエラーメッセージを生成する場合、以下のように書くことができます。

    errmsg_plural("copied %d file",
                  "copied %d files",
                  n,
                  n)
    

    最初の引数は英文の単数形に適切な書式文字列で、二番目は英文の複数形に適切な書式文字列、そして三番目はどの複数形を使用するのかを決定する整数制御値です。 引き続く引数はいつものように書式文字列毎に書式化されます。 (通常、複数化制御値は書式化されるべき値の内の1つでもありますので、2回書かなければなりまません。) 英語ではnが1であるか、そうでないかのみ重要ですが、他の言語では数多くの複数書式が存在します。 翻訳者にはグループとして2つの英文書式を参照し、nの実行時の値に基づいて選択される適切な1つでもって、複数の代替文字列を供給する機会があります。

    errmsgあるいはerrdetail報告に直接行かない複数形メッセージが必要であれば、基礎となっている関数、ngettextを使用する必要があります。 gettextのドキュメントを参照してください。

  • メッセージをどのように他の出力と合わせる予定なのかなど翻訳者と何か連絡を取り合いたい場合、translatorで始まるコメントを最初に付けてどうなるかを知らせてください。 以下のようにします。

    /* translator: This message is not what it seems to be. */
    

    これらのコメントはメッセージカタログにコピーされますので翻訳者は参照できます。