プログラマへ

PostgreSQL 8.4.1文書
前のページ | 巻戻し | 第 47章多言語サポート | 早送り | 次のページ

# 47.2. プログラマへ

## 47.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)

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

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

## 47.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)

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

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

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

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

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

前のページ | ホーム | 次のページ
翻訳者へ | 上に戻る | 手続き言語ハンドラの作成