22.1. "gettext" --- 多言語対応に関する国際化サービス
****************************************************

**ソースコード:** Lib/gettext.py

======================================================================

"gettext" モジュールは、 Python によるモジュールやアプリケーションの国
際化 (I18N, I-nternationalizatio-N) および地域化 (L10N,
L-ocalizatio-N) サービスを提供します。このモジュールは GNU "gettext"
メッセージカタログへの API と、より高レベルで Python ファイルに適して
いるクラスに基づいた API の両方をサポートしてます。以下で述べるインタ
フェースを使うことで、モジュールやアプリケーションのメッセージをある自
然言語で記述しておき、翻訳されたメッセージのカタログを与えて他の異なる
自然言語の環境下で動作させることができます。

ここでは Python のモジュールやアプリケーションを地域化するためのいくつ
かのヒントも提供しています。


22.1.1. GNU **gettext** API
===========================

"gettext" モジュールでは、以下の GNU **gettext** API に非常に良く似た
API を提供しています。この API を使う場合、メッセージ翻訳の影響はアプ
リケーション全体に及ぼすことになります。アプリケーションが単一の言語し
か扱わず、各言語に依存する部分をユーザのロケール情報によって選ぶのなら
、ほとんどの場合この方法でやりたいことを実現できます。Python モジュー
ルを地域化していたり、アプリケーションの実行中に言語を切り替えたい場合
、おそらくクラスに基づいた API を使いたくなるでしょう。

gettext.bindtextdomain(domain[, localedir])

   *domain* をロケール辞書 *localedir* に結び付け (bind) ます。具体的
   には、 "gettext" は与えられたドメインに対するバイナリ形式の ".mo"
   ファイルを、(Unixでは) "localedir/language/LC_MESSAGES/domain.mo"
   から探します。ここで *languages* はそれぞれ環境変数 "LANGUAGE" 、
   "LC_ALL" 、 "LC_MESSAGES" 、および "LANG" の中から検索されます。

   *localedir* が省略されるか "None" の場合、現在 *domain* に結び付け
   られている内容が返されます。 [1]

gettext.bind_textdomain_codeset(domain[, codeset])

   *domain* を *codeset* に結び付けて、 "gettext()" ファミリの関数が返
   す文字列のエンコード方式を変更します。 *codeset* を省略すると、現在
   結び付けられているコードセットを返します。

   バージョン 2.4 で追加.

gettext.textdomain([domain])

   現在のグローバルドメインを調べたり変更したりします。 *domain* が
   "None" の場合、現在のグローバルドメインが返されます。それ以外の場合
   にはグローバルドメインは *domain* に設定され、設定されたグローバル
   ドメインを返します。

gettext.gettext(message)

   現在のグローバルドメイン、言語、およびロケール辞書に基づいて、
   *message* の特定地域向けの翻訳を返します。通常、ローカルな名前空間
   ではこの関数に "_()" という別名をつけます (下の例を参照してください
   )。

gettext.lgettext(message)

   "gettext()" と同じですが、 "bind_textdomain_codeset()" で特にエンコ
   ードを指定しない限り、翻訳結果を優先システムエンコーディング
   (preferred system encoding) で返します。

   バージョン 2.4 で追加.

gettext.dgettext(domain, message)

   "gettext()" と同様ですが、指定された *domain* からメッセージを探し
   ます。

gettext.ldgettext(domain, message)

   "dgettext()" と同じですが、 "bind_textdomain_codeset()" で特にエン
   コードを指定しない限り、翻訳結果を優先システムエンコーディング
   (preferred system encoding) で返します。

   バージョン 2.4 で追加.

gettext.ngettext(singular, plural, n)

   "gettext()" と同様ですが、複数形の場合を考慮しています。翻訳文字列
   が見つかった場合、 *n* の様式を適用し、その結果得られたメッセージを
   返します (言語によっては二つ以上の複数形があります)。翻訳文字列が見
   つからなかった場合、 *n* が 1 なら *singular* を返します; そうでな
   い場合 *plural* を返します。

   複数形の様式はカタログのヘッダから取り出されます。様式は C または
   Python の式で、自由な変数 *n* を持ちます; 式の評価値はカタログ中の
   複数形のインデクスとなります。 ".po" ファイルで用いられる詳細な文法
   と、様々な言語における様式については、GNU gettext ドキュメントを参
   照してください。

   バージョン 2.3 で追加.

gettext.lngettext(singular, plural, n)

   "ngettext()" と同じですが、 "bind_textdomain_codeset()" で特にエン
   コードを指定しない限り、翻訳結果を優先システムエンコーディング
   (preferred system encoding) で返します。

   バージョン 2.4 で追加.

gettext.dngettext(domain, singular, plural, n)

   "ngettext()" と同様ですが、指定された *domain* からメッセージを探し
   ます。

   バージョン 2.3 で追加.

gettext.ldngettext(domain, singular, plural, n)

   "dngettext()" と同じですが、 "bind_textdomain_codeset()" で特にエン
   コードを指定しない限り、翻訳結果を優先システムエンコーディング
   (preferred system encoding) で返します。

   バージョン 2.4 で追加.

GNU **gettext** では "dcgettext()" も定義していますが、このメソッドは
あまり有用ではないと思われるので、現在のところ実装されていません。

以下にこの API の典型的な使用法を示します:

   import gettext
   gettext.bindtextdomain('myapplication', '/path/to/my/language/directory')
   gettext.textdomain('myapplication')
   _ = gettext.gettext
   # ...
   print _('This is a translatable string.')


22.1.2. クラスに基づいた API
============================

The class-based API of the "gettext" module gives you more flexibility
and greater convenience than the GNU **gettext** API.  It is the
recommended way of localizing your Python applications and modules.
"gettext" defines a "translations" class which implements the parsing
of GNU ".mo" format files, and has methods for returning either
standard 8-bit strings or Unicode strings. Instances of this
"translations" class can also install themselves  in the built-in
namespace as the function "_()".

gettext.find(domain[, localedir[, languages[, all]]])

   この関数は標準的な ".mo" ファイル検索アルゴリズムを実装しています。
   "textdomain()" と同じく、 *domain* を引数にとります。オプションの
   *localedir* は "bindtextdomain()" と同じです。またオプションの
   *languages* は文字列を列挙したリストで、各文字列は言語コードを表し
   ます。

   *localedir* が与えられていない場合、標準のシステムロケールディレク
   トリが使われます。 [2] *languages* が与えられなかった場合、以下の環
   境変数: "LANGUAGE" 、 "LC_ALL" 、 "LC_MESSAGES" 、および "LANG" が
   検索されます。空でない値を返した最初の候補が *languages* 変数として
   使われます。この環境変数は言語名をコロンで分かち書きしたリストを含
   んでいなければなりません。 "find()" はこの文字列をコロンで分割し、
   言語コードの候補リストを生成します。

   "find()" は次に言語コードを展開および正規化し、リストの各要素につい
   て、以下のパス構成:

   "localedir/language/LC_MESSAGES/domain.mo"

   からなる実在するファイルの探索を反復的に行います。 "find()" は上記
   のような実在するファイルで最初に見つかったものを返します。該当する
   ファイルが見つからなかった場合、 "None" が返されます。 *all* が与え
   られていれば、全ファイル名のリストが言語リストまたは環境変数で指定
   されている順番に並べられたものを返します。

gettext.translation(domain[, localedir[, languages[, class_[, fallback[, codeset]]]]])

   "Translations" インスタンスを *domain* 、 *localedir* 、および
   *languages* に基づいて生成して返します。 *domain* 、 *localedir* 、
   および *languages* はまず関連付けられている ".mo" ファイルパスのリ
   ストを取得するために "find()" に渡されます。同じ ".mo" ファイル名を
   持つインスタンスはキャッシュされます。実際にインスタンス化されるク
   ラスは *class_* が与えられていればそのクラスが、そうでない時には
   "GNUTranslations" です。クラスのコンストラクタは単一の引数としてフ
   ァイルオブジェクトを取らなくてはなりません。 *codeset* を指定した場
   合、翻訳文字列のエンコードに使う文字セットを変更します。

   複数のファイルが発見された場合、後で見つかったファイルは前に見つか
   ったファイルの代替でと見なされ、後で見つかった方が利用されます。代
   替の設定を可能にするには、 "copy.copy()" を使ってキャッシュから翻訳
   オブジェクトを複製します; こうすることで、実際のインスタンスデータ
   はキャッシュのものと共有されます。

   ".mo" ファイルが見つからなかった場合、 *fallback* が偽 (標準の設定
   です) ならこの関数は "IOError" を送出し、 *fallback* が真なら
   "NullTranslations" インスタンスが返されます。

   バージョン 2.4 で変更: *codeset* パラメータを追加しました.

gettext.install(domain[, localedir[, unicode[, codeset[, names]]]])

   "translation()" に *domain* 、 *localedir* 、および *codeset* を渡
   してできる関数 "_()" を Python の組み込み名前空間に組み込みます。
   *unicode* フラグは "translation()" の返す翻訳オブジェクトの
   "install()" メソッドに渡されます。

   *names* パラメータについては、翻訳オブジェクトの "install()" メソッ
   ドの説明を参照ください。

   以下に示すように、通常はアプリケーション中の文字列を関数 "_()" の呼
   び出しで包み込んで翻訳対象候補であることを示します:

      print _('This string will be translated.')

   利便性を高めるためには、 "_()" 関数を Python の組み込み名前空間に組
   み入れる必要があります。こうすることで、アプリケーション内の全ての
   モジュールからアクセスできるようになります。

   バージョン 2.4 で変更: *codeset* パラメータを追加しました.

   バージョン 2.5 で変更: *names* パラメータを追加しました.


22.1.2.1. "NullTranslations" クラス
-----------------------------------

翻訳クラスは、元のソースファイル中のメッセージ文字列から翻訳されたメッ
セージ文字列への変換処理が実際に実装されているクラスです。 全ての翻訳
クラスで基底クラスとして使われているクラスが "NullTranslations" です;
このクラスは、独自の翻訳クラスを実装するのに使える基本的なインタフェー
スを提供しています。 以下に "NullTranslations" のメソッドを示します:

class gettext.NullTranslations([fp])

   オプションのファイルオブジェクト *fp* を取ります。この引数は基底ク
   ラスでは無視されます。このメソッドは "保護された (protected)" イン
   スタンス変数 *_info* および *_charset* を初期化します。これらの変数
   の値は派生クラスで設定することができます。同様に *_fallback* も初期
   化しますが、この値は "add_fallback()" で設定されます。その後、 *fp*
   が "None" でない場合 "self._parse(fp)" を呼び出します。

   _parse(fp)

      基底クラスでは何もしない (no-op) ようになっています。このメソッ
      ドの役割はファイルオブジェクト *fp* を引数に取り、ファイルからデ
      ータを読み出し、メッセージカタログを初期化することです。サポート
      されていないメッセージカタログ形式を使っている場合、その形式を解
      釈するためにはこのメソッドを上書きしなくてはなりません。

   add_fallback(fallback)

      *fallback* を現在の翻訳オブジェクトの代替オブジェクトとして追加
      します。翻訳オブジェクトが与えられたメッセージに対して翻訳メッセ
      ージを提供できない場合、この代替オブジェクトに問い合わせることに
      なります。

   gettext(message)

      If a fallback has been set, forward "gettext()" to the fallback.
      Otherwise, return the translated message.  Overridden in derived
      classes.

   lgettext(message)

      If a fallback has been set, forward "lgettext()" to the
      fallback. Otherwise, return the translated message.  Overridden
      in derived classes.

      バージョン 2.4 で追加.

   ugettext(message)

      If a fallback has been set, forward "ugettext()" to the
      fallback. Otherwise, return the translated message as a Unicode
      string. Overridden in derived classes.

   ngettext(singular, plural, n)

      If a fallback has been set, forward "ngettext()" to the
      fallback. Otherwise, return the translated message.  Overridden
      in derived classes.

      バージョン 2.3 で追加.

   lngettext(singular, plural, n)

      If a fallback has been set, forward "lngettext()" to the
      fallback. Otherwise, return the translated message.  Overridden
      in derived classes.

      バージョン 2.4 で追加.

   ungettext(singular, plural, n)

      If a fallback has been set, forward "ungettext()" to the
      fallback. Otherwise, return the translated message as a Unicode
      string. Overridden in derived classes.

      バージョン 2.3 で追加.

   info()

      "protected" の "_info" 変数を返します。

   charset()

      "protected" の "_charset" 変数を返します。

   output_charset()

      翻訳メッセージとして返す文字列のエンコードを決める、 "protected"
      の "_output_charset" 変数を返します。

      バージョン 2.4 で追加.

   set_output_charset(charset)

      翻訳メッセージとして返す文字列のエンコードを決める、 "protected"
      の変数 "_output_charset" を変更します。

      バージョン 2.4 で追加.

   install([unicode[, names]])

      *unicode* フラグが偽の場合、このメソッドは "self.gettext()" を組
      み込み名前空間に組み入れ、 "_" と結び付けます。 *unicode* が真の
      場合、 "self.gettext()" の代わりに "self.ugettext()" を結び付け
      ます。標準では *unicode* は偽です。

      *names* パラメータには、 "_()" 以外に組み込みの名前空間にインス
      トールしたい関数名のシーケンスを指定します。サポートしている名前
      は "'gettext'" (*unicode* フラグの設定に応じて "self.gettext()"
      あるいは "self.ugettext()" のいずれかに対応します)、
      "'ngettext'" (*unicode* フラグの設定に応じて "self.ngettext()"
      あるいは "self.ungettext()" のいずれかに対応します)、
      "'lgettext'" および "'lngettext'" です。

      この方法はアプリケーションで "_()" 関数を利用できるようにするた
      めの最も便利な方法ですが、唯一の手段でもあるので注意してください
      。この関数はアプリケーション全体、とりわけ組み込み名前空間に影響
      するので、地域化されたモジュールで "_()" を組み入れることができ
      ないのです。その代わりに、以下のコードを使って "_()" を使えるよ
      うにしなければなりません。:

         import gettext
         t = gettext.translation('mymodule', ...)
         _ = t.gettext

      この操作は "_()" をモジュール内だけのグローバル名前空間に組み入
      れるので、モジュール内の "_()" の呼び出しだけに影響します。

      バージョン 2.5 で変更: *names* パラメータを追加しました.


22.1.2.2. "GNUTranslations" クラス
----------------------------------

"gettext" モジュールでは "NullTranslations" から派生したもう一つのクラ
ス: "GNUTranslations" を提供しています。このクラスはビッグエンディアン
、およびリトルエンディアン両方のバイナリ形式の GNU **gettext** ".mo"
ファイルを読み出せるように "_parse()" を上書きしています。また、このク
ラスはメッセージ id とメッセージ文字列の両方を Unicode に型強制します
。

このクラスではまた、翻訳カタログ以外に、オプションのメタデータを読み込
んで解釈します。GNU **gettext** では、空の文字列に対する変換先としてメ
タデータを取り込むことが慣習になっています。このメタデータは **RFC
822** 形式の "key: value" のペアになっており、 "Project-Id-Version" キ
ーを含んでいなければなりません。キー "Content-Type" があった場合、
"charset" の特性値 (property) は "保護された" "_charset" インスタンス
変数を初期化するために用いられます。値がない場合には、デフォルトとして
"None" が使われます。エンコードに用いられる文字セットが指定されている
場合、カタログから読み出された全てのメッセージ id とメッセージ文字列は
、指定されたエンコードを用いて Unicode に変換されます。 "ugettext()"
は常に Unicode を返し、 "gettext()" はエンコードされた 8 ビット文字列
を返します。どちらのメソッドにおける引数 id の場合も、Unicode 文字列か
US-ASCII 文字のみを含む 8 ビット文字列だけが受理可能です。国際化された
Python プログラムでは、メソッドの Unicode 版 (すなわち "ugettext()" や
"ungettext()") の利用が推奨されています。

key/value ペアの集合全体は辞書型データ中に配置され、"保護された"
"_info" インスタンス変数に設定されます。

".mo" ファイルのマジックナンバーが不正な場合、あるいはその他の問題がフ
ァイルの読み出し中に発生した場合、 "GNUTranslations" クラスのインスタ
ンス化で "IOError" が送出されることがあります。

以下のメソッドは基底クラスの実装からオーバライドされています:

GNUTranslations.gettext(message)

   カタログから *message* id を検索して、対応するメッセージ文字列を、
   カタログの文字セットが既知のエンコードの場合、エンコードされた 8 ビ
   ット文字列として返します。 *message* id に対するエントリがカタログ
   に存在せず、フォールバックが設定されている場合、フォールバック検索
   はオブジェクトの "gettext()" メソッドに転送されます。そうでない場合
   、 *message* id 自体が返されます。

GNUTranslations.lgettext(message)

   "gettext()" と同じですが、翻訳結果は "set_output_charset()" で特に
   エンコーディングが指定されていなければ、優先システムエンコーディン
   グで返します。

   バージョン 2.4 で追加.

GNUTranslations.ugettext(message)

   カタログから *message* id を検索して、対応するメッセージ文字列を、
   Unicode でエンコードして返します。 *message* id に対するエントリが
   カタログに存在せず、フォールバックが設定されている場合、フォールバ
   ック検索はオブジェクトの "ugettext()" メソッドに転送されます。そう
   でない場合、 *message* id 自体が返されます。

GNUTranslations.ngettext(singular, plural, n)

   メッセージ id に対する複数形を検索します。カタログに対する検索では
   *singular* がメッセージ id として用いられ、 *n* にはどの複数形を用
   いるかを指定します。返されるメッセージ文字列は 8 ビットの文字列で、
   カタログの文字セットが既知の場合にはその文字列セットでエンコードさ
   れています。

   メッセージ id がカタログ中に見つからず、フォールバックオブジェクト
   が指定されている場合、メッセージ検索要求はフォールバックオブジェク
   トの "ngettext()" メソッドに転送されます。そうでない場合、 *n* が 1
   ならば *singular* が返され、それ以外に対しては *plural* が返されま
   す。

   バージョン 2.3 で追加.

GNUTranslations.lngettext(singular, plural, n)

   "gettext()" と同じですが、翻訳結果は "set_output_charset()" で特に
   エンコーディングが指定されていなければ、優先システムエンコーディン
   グで返します。

   バージョン 2.4 で追加.

GNUTranslations.ungettext(singular, plural, n)

   メッセージ id に対する複数形を検索します。カタログに対する検索では
   *singular* がメッセージ id として用いられ、 *n* にはどの複数形を用
   いるかを指定します。返されるメッセージ文字列は Unicode 文字列です。

   メッセージ id がカタログ中に見つからず、フォールバックオブジェクト
   が指定されている場合、メッセージ検索要求はフォールバックオブジェク
   トの "ungettext()" メソッドに転送されます。そうでない場合、 *n* が
   1 ならば *singular* が返され、それ以外に対しては *plural* が返され
   ます。

   以下に例を示します。:

      n = len(os.listdir('.'))
      cat = GNUTranslations(somefile)
      message = cat.ungettext(
          'There is %(num)d file in this directory',
          'There are %(num)d files in this directory',
          n) % {'num': n}

   バージョン 2.3 で追加.


22.1.2.3. Solaris メッセージカタログ機構のサポート
--------------------------------------------------

Solaris オペレーティングシステムでは、独自の ".mo" バイナリファイル形
式を定義していますが、この形式に関するドキュメントが手に入らないため、
現時点ではサポートされていません。


22.1.2.4. Catalog コンストラクタ
--------------------------------

GNOME では、James Henstridge によるあるバージョンの "gettext" モジュー
ルを使っていますが、このバージョンは少し異なった API を持っています。
ドキュメントに書かれている利用法は:

   import gettext
   cat = gettext.Catalog(domain, localedir)
   _ = cat.gettext
   print _('hello world')

となっています。過去のモジュールとの互換性のために、 "Catalog()" は前
述の "translation()" 関数の別名になっています。

このモジュールと Henstridge のバージョンとの間には一つ相違点があります
: 彼のカタログオブジェクトはマップ型の API を介したアクセスがサポート
されていましたが、この API は使われていないらしく、現在はサポートされ
ていません。


22.1.3. プログラムやモジュールを国際化する
==========================================

国際化 (I18N, I-nternationalizatio-N) とは、プログラムを複数の言語に対
応させる操作を指します。地域化 (L10N, L-ocalizatio-N) とは、すでに国際
化されているプログラムを特定地域の言語や文化的な事情に対応させることを
指します。Python プログラムに多言語メッセージ機能を追加するには、以下
の手順を踏む必要があります:

1. プログラムやモジュールで翻訳対象とする文字列に特殊なマークをつけ
   て 準備します

2. マークづけをしたファイルに一連のツールを走らせ、生のメッセージカ
   タ ログを生成します

3. 特定の言語へのメッセージカタログの翻訳を作成します

4. メッセージ文字列を適切に変換するために "gettext" モジュールを使
   いま す

ソースコードを I18N 化する準備として、ファイル内の全ての文字列を探す必
要があります。翻訳を行う必要のある文字列はどれも "_('...')" --- すなわ
ち関数 "_()" の呼び出しで包むことでマーク付けしなくてはなりません。例
えば以下のようにします:

   filename = 'mylog.txt'
   message = _('writing a log message')
   fp = open(filename, 'w')
   fp.write(message)
   fp.close()

この例では、文字列 "'writing a log message'" が翻訳対象候補としてマー
ク付けされており、文字列 "'mylog.txt'" および "'w'" はされていません。

Python の配布物には、ソースコードに準備作業を行った後でメッセージカタ
ログの生成を助ける 2 つのツールが付属します。これらはバイナリ配布の場
合には付属していたりしなかったりしますが、ソースコード配布には入ってお
り、 "Tools/i18n" ディレクトリにあります。

**pygettext** プログラム [3] は全ての Python ソースコードを走査し、予
め翻訳対象としてマークした文字列を探し出します。このツールは GNU
**gettext** プログラムと同様ですが、Python ソースコードの機微について
熟知している反面、C 言語や C++言語のソースコードについては全く知りませ
ん。(C 言語による拡張モジュールのように) C 言語のコードも翻訳対象にし
たいのでない限り、 GNU "gettext" は必要ありません。

**pygettext** は、テキスト形式 Uniforum スタイルによる人間が判読可能な
メッセージカタログ ".pot" ファイル群を生成します。このファイル群はソー
スコード中でマークされた全ての文字列と、それに対応する翻訳文字列のため
のプレースホルダを含むファイルで構成されています。 **pygettext** はコ
マンドライン形式のスクリプトで、 **xgettext** と同様のコマンドラインイ
ンタフェースをサポートします; 使用法についての詳細を見るには以下を起動
してください。:

   pygettext.py --help

これら ".pot" ファイルのコピーは次に、サポート対象の各自然言語について
、言語ごとのバージョンを作成する個々の人間の翻訳者に頒布されます。翻訳
者たちはプレースホルダ部分を埋めて言語ごとのバージョンをつくり、 ".po"
ファイルとして返します。("Tools/i18n" ディレクトリ内の) **msgfmt.py**
[4] プログラムを使い、翻訳者から返された ".po" ファイルから機械可読な
".mo" バイナリカタログファイルを生成します。 ".mo" ファイルは、
"gettext" モジュールが実行時に実際の翻訳処理を行うために使われます。

"gettext" モジュールをソースコード中でどのように使うかは単一のモジュー
ルを国際化するのか、それともアプリケーション全体を国際化するのかにより
ます。次のふたつのセクションで、それぞれについて説明します。


22.1.3.1. モジュールを地域化する
--------------------------------

モジュールを地域化する場合、グローバルな変更、例えば組み込み名前空間へ
の変更を行わないように注意しなければなりません。GNU "gettext" API では
なく、クラスベースの API を使うべきです。

仮に対象のモジュール名を "spam" とし、モジュールの各言語における翻訳が
収められた ".mo" ファイルが "/usr/share/locale" に GNU **gettext** 形
式で置かれているとします。この場合、モジュールの最初で以下のようにしま
す:

   import gettext
   t = gettext.translation('spam', '/usr/share/locale')
   _ = t.lgettext

翻訳オブジェクトが ".po" ファイル中の Unicode 文字列を返すようになって
いるのなら、上の代わりに以下のようにします:

   import gettext
   t = gettext.translation('spam', '/usr/share/locale')
   _ = t.ugettext


22.1.3.2. アプリケーションを地域化する
--------------------------------------

アプリケーションを地域化するのなら、関数 "_()" をグローバルな組み込み
名前空間に組み入れなければならず、これは通常アプリケーションの主ドライ
バ (main driver) ファイルで行います。この操作によって、アプリケーショ
ン独自のファイルは明示的に各ファイルで "_()" の組み入れを行わなくても
単に "_('...')" を使うだけで済むようになります。

単純な場合では、単に以下の短いコードをアプリケーションの主ドライバファ
イルに追加するだけです:

   import gettext
   gettext.install('myapplication')

ロケールディレクトリや *unicode* フラグを設定する必要がある場合、それ
らの値を "install()" 関数に渡すことができます:

   import gettext
   gettext.install('myapplication', '/usr/share/locale', unicode=1)


22.1.3.3. 動作中 (on the fly) に言語を切り替える
------------------------------------------------

多くの言語を同時にサポートする必要がある場合、複数の翻訳インスタンスを
生成して、例えば以下のコードのように、インスタンスを明示的に切り替えて
もかまいません。:

   import gettext

   lang1 = gettext.translation('myapplication', languages=['en'])
   lang2 = gettext.translation('myapplication', languages=['fr'])
   lang3 = gettext.translation('myapplication', languages=['de'])

   # start by using language1
   lang1.install()

   # ... time goes by, user selects language 2
   lang2.install()

   # ... more time goes by, user selects language 3
   lang3.install()


22.1.3.4. 翻訳処理の遅延解決
----------------------------

コードを書く上では、ほとんどの状況で文字列はコードされた場所で翻訳され
ます。しかし場合によっては、翻訳対象として文字列をマークはするが、その
後実際に翻訳が行われるように遅延させる必要が生じます。古典的な例は以下
のようなコートです:

   animals = ['mollusk',
              'albatross',
              'rat',
              'penguin',
              'python', ]
   # ...
   for a in animals:
       print a

ここで、リスト "animals" 内の文字列は翻訳対象としてマークはしたいが、
文字列が出力されるまで実際に翻訳を行うのは避けたいとします。

こうした状況を処理する一つの方法を以下に示します:

   def _(message): return message

   animals = [_('mollusk'),
              _('albatross'),
              _('rat'),
              _('penguin'),
              _('python'), ]

   del _

   # ...
   for a in animals:
       print _(a)

ダミーの "_()" 定義が単に文字列をそのまま返すようになっているので、上
のコードはうまく動作します。かつ、このダミーの定義は、組み込み名前空間
に置かれた "_()" の定義で ("del" 命令を実行するまで) 一時的に上書きす
ることができます。もしそれまでに "_()" をローカルな名前空間に持ってい
たら注意してください。

二つ目の例における "_()" の使い方では、"a" は文字列リテラルではないの
で、 **pygettext** プログラムが翻訳可能な対象として識別しません。

もう一つの処理法は、以下の例のようなやり方です:

   def N_(message): return message

   animals = [N_('mollusk'),
              N_('albatross'),
              N_('rat'),
              N_('penguin'),
              N_('python'), ]

   # ...
   for a in animals:
       print _(a)

この例の場合では、翻訳可能な文字列を関数 "N_()" でマーク付けしており
[5] 、 "_()" の定義とは全く衝突しません。しかしメッセージ展開プログラ
ムには翻訳対象の文字列が "N_()" でマークされていることを教える必要が出
てくるでしょう。 **pygettext** および **xpot** は両方とも、コマンドラ
イン上のスイッチでこの機能をサポートしています。


22.1.3.5. "gettext()" vs. "lgettext()"
--------------------------------------

Python 2.4 からは、 "lgettext()" ファミリが導入されました。この関数の
目的は、現行の GNU gettext 実装によりよく準拠した別の関数を提供するこ
とにあります。翻訳メッセージファイル中で使われているのと同じコードセッ
トを使って文字列をエンコードして返す "gettext()" と違い、これらの関数
は "locale.getpreferredencoding()" の返す優先システムエンコーディング
を使って翻訳メッセージ文字列をエンコードして返します。また、Python 2.4
では、翻訳メッセージ文字列で使われているコードセットを明示的に選べるよ
うにする関数が新たに導入されていることにも注意してください。コードセッ
トを明示的に設定すると、 "lgettext()" でさえ、指定したコードセットで翻
訳メッセージ文字列を返します。これは GNU gettext 実装が期待している仕
様と同じです。


22.1.4. 謝辞
============

以下の人々が、このモジュールのコード、フィードバック、設計に関する助言
、過去の実装、そして有益な経験談による貢献をしてくれました:

* Peter Funk

* James Henstridge

* Juan David Ibáñez Palomar

* Marc-André Lemburg

* Martin von Löwis

* François Pinard

* Barry Warsaw

* Gustavo Niemeyer

-[ 脚注 ]-

[1] 標準でロケールが収められているディレクトリはシステム依存です;
    例え ば、RedHat Linux では "/usr/share/locale" ですが、 Solaris で
    は "/usr/lib/locale" です。 "gettext" モジュールはこうしたシステム
    依 存の標準設定をサポートしません; その代わりに
    "sys.prefix/share/locale" を標準の設定とします。この理由から、常に
    アプリケーションの開始時に絶対パスで明示的に指定して
    "bindtextdomain()" を呼び出すのが最良のやり方ということになります
    。

[2] 上の "bindtextdomain()" に関する脚注を参照してください。

[3] 同様の作業を行う **xpot** と呼ばれるプログラムを François
    Pinard が書いています。このプログラムは彼の po-utils パッケージ の
    一部で す。

[4] **msgfmt.py** は GNU **msgfmt** とバイナリ互換ですが、より単純
    で、 Python だけを使った実装がされています。このプログラムと
    **pygettext.py** があれば、通常 Python プログラムを国際化するため
    に GNU **gettext** パッケージをインストールする必要はありません。

[5] この "N_()" をどうするかは全くの自由です;
    "MarkThisStringForTranslation()" などとしてもかまいません。
