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

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

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

"gettext" モジュールは、 Python のモジュールやアプリケーションの国際化
(I18N, I-nternationalizatio-N) および地域化  (L10N, L-ocalizatio-N) サ
ービスを提供します。 このモジュールは GNU "gettext" メッセージカタログ
の API と、より高水準で Python ファイルに適しているクラス形式の API の
両方をサポートしてます。 以下で述べるインタフェースを使うことで、モジ
ュールやアプリケーションのメッセージをある自然言語で記述しておき、後か
ら提供する翻訳されたメッセージのカタログによって様々な自然言語環境で実
行できます。

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


23.1.1. GNU **gettext** API
===========================

"gettext" モジュールでは、以下の GNU **gettext** API に非常に良く似た
API を提供しています。 この API を使う場合、アプリケーション全体の翻訳
に影響します。 アプリケーションが単一の言語しか扱わず、ユーザのロケー
ルに従って言語が選ばれるのなら、たいていはこの API が求めているもので
す。 Python モジュールを地域化していたり、アプリケーションの実行中に言
語を切り替える必要がある場合は、この API ではなくおそらくクラス形式の
API を使いたくなるでしょう。

gettext.bindtextdomain(domain, localedir=None)

   *domain* をロケールディレクトリ *localedir* に対応付けます。 具体的
   には、 "gettext" は与えられたドメインに対するバイナリ形式の ".mo"
   ファイルを探しに、(Unixでは)
   "localedir/language/LC_MESSAGES/domain.mo" というパスを見に行きます
   。 ここで *language* はそれぞれ環境変数 "LANGUAGE" 、 "LC_ALL" 、
   "LC_MESSAGES" 、 "LANG" の中から検索されます。

   *localedir* が省略されるか "None" の場合、現在 *domain* に対応付け
   られているロケールディレクトリが返されます。 [1]

gettext.bind_textdomain_codeset(domain, codeset=None)

   *domain* を *codeset* に対応付け、 "lgettext()", "ldgettext()",
   "lngettext()", "ldngettext()" 関数が返すバイト文字列のエンコード方
   式を変更します。 *codeset* が省略された場合は、現在 *domain* に対応
   付けられているコードセットを返します。

gettext.textdomain(domain=None)

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

gettext.gettext(message)

   現在のグローバルドメイン、言語、およびロケールディレクトリに基づい
   て、 *message* の地域化された訳文を返します。 通常、この関数はロー
   カルな名前空間にある "_()" という別名を持ちます (下の例を参照してく
   ださい)。

gettext.dgettext(domain, message)

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

gettext.ngettext(singular, plural, n)

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

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

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

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

gettext.lgettext(message)

gettext.ldgettext(domain, message)

gettext.lngettext(singular, plural, n)

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

   それぞれに対応する先頭の "l" が無い関数 ("gettext()", "dgettext()",
   "ngettext()", "dngettext()") と同じですが、エンコーディングが
   "bind_textdomain_codeset()" を使って明示的に設定されていない場合、
   翻訳結果は優先システムエンコーディングでエンコードされたバイト文字
   列として返されます。

   警告:

     これらの関数はエンコードされたバイト列を返すため Python 3 で使う
     のは避けるべきです。 ほとんどの Python アプリケーションでは、人間
     が読むテキストをバイト列ではなく文字列として扱いたいので、
     Unicode 文字列を返す代わりの関数を使う方が良いです。 さらに言うと
     、翻訳文字列にエンコーディング上の問題があった場合、 Unicode 関連
     の予期しない例外を受け取るかもしれません。 このように "l*()" 関数
     は問題や制約を抱えているので、将来の Python バージョンで非推奨と
     なる可能性があります。

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.'))


23.1.2. クラス形式の API
========================

"gettext" モジュールのクラス形式の API は、 GNU **gettext** API よりも
高い柔軟性と利便性を持っています。 Python のアプリケーションやモジュー
ルを地域化するにはこちらを使うことをお勧めします。 "gettext" には、GNU
".mo" 形式のファイルを構文解析する処理の実装と、文字列を返すメソッドを
持つ "翻訳" クラスが定義されています。 この "翻訳" クラスのインスタン
スも、自分自身を組み込み名前空間に関数  "_()" として配置できます。

gettext.find(domain, localedir=None, languages=None, all=False)

   この関数は標準的な ".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=None, languages=None, class_=None, fallback=False, codeset=None)

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

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

   ".mo" ファイルが見つからなかった場合、 *fallback* が偽 (デフォルト
   値) ならこの関数は "OSError" を送出し、 *fallback* が真なら
   "NullTranslations" インスタンスが返されます。

   バージョン 3.3 で変更: 以前は "OSError" ではなく "IOError" が送出さ
   れていました。

gettext.install(domain, localedir=None, codeset=None, names=None)

   "translation()" に *domain* 、 *localedir* 、および *codeset* を渡
   してできる関数 "_()" を Python の組み込み名前空間に組み込みます。

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

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

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

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


23.1.2.1. "NullTranslations" クラス
-----------------------------------

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

class gettext.NullTranslations(fp=None)

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

   _parse(fp)

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

   add_fallback(fallback)

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

   gettext(message)

      フォールバックが設定されている場合、フォールバックの "gettext()"
      に処理を移譲します。 そうでない場合、引数として受け取った
      *message* を返します。 派生クラスで上書きするメソッドです。

   ngettext(singular, plural, n)

      フォールバックが設定されている場合、フォールバックの
      "ngettext()" に処理を移譲します。 そうでない場合、 *n* が 1 なら
      *singular* を返します; それ以外なら *plural* を返します。 派生ク
      ラスで上書きするメソッドです。

   lgettext(message)

   lngettext(singular, plural, n)

      "gettext()" および "ngettext()" と同じですが、エンコーディングが
      "set_output_charset()" で明示的に設定されていない場合、翻訳結果
      は優先システムエンコーディングでエンコードされたバイト文字列とし
      て返されます。 派生クラスで上書きするメソッドです。

      警告:

        これらのメソッドは Python 3 で使うのは避けるべきです。
        "lgettext()" 関数に対する警告を参照してください。

   info()

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

   charset()

      メッセージカタログファイルのエンコーディングを返します。

   output_charset()

      "lgettext()" と "lngettext()" の返り値となる翻訳メッセージで使わ
      れているエンコーディングを返します。

   set_output_charset(charset)

      返り値の翻訳メッセージで使われるエンコーディングを変更します。

   install(names=None)

      このメソッドは "gettext()" を組み込み名前空間にインストールし、
      変数 "_" に束縛します。

      *names* パラメータを与える場合には、 "_()" 以外では組み込み名前
      空間に配置したい関数名を列挙したシーケンスでなければなりません。
      サポートされている名前は "'gettext'" 、 "'ngettext'" 、
      "'lgettext'" 、 "'lngettext'" です。

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

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

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


23.1.2.2. "GNUTranslations" クラス
----------------------------------

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

"GNUTranslations" はまた、翻訳カタログ以外に、オプションのメタデータを
読み込んで解釈します。GNU **gettext** では、空の文字列に対する変換先と
してメタデータを取り込むことが慣習になっています。このメタデータは
**RFC 822** 形式の "key: value" のペアになっており、 "Project-Id-
Version" キーを含んでいなければなりません。キー "Content-Type" があっ
た場合、 "charset" の特性値 (property) は "保護された" "_charset" イン
スタンス変数を初期化するために用いられます。値がない場合には、デフォル
トとして "None" が使われます。エンコードに用いられる文字セットが指定さ
れている場合、カタログから読み出された全てのメッセージ id とメッセージ
文字列は、指定されたエンコードを用いて Unicode に変換され、そうでなけ
れば ASCII エンコーディングとみなされます。

メッセージ id もユニコード文字列として解釈されるので、すべての
"*gettext()" メソッドはメッセージ id をバイト文字列ではなくユニコード
文字列と仮定するでしょう。

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

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

class gettext.GNUTranslations

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

   gettext(message)

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

   ngettext(singular, plural, n)

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

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

      以下に例を示します。:

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

   lgettext(message)

   lngettext(singular, plural, n)

      "gettext()" および "ngettext()" と同じですが、エンコーディングが
      "set_output_charset()" で明示的に設定されていない場合、翻訳結果
      は優先システムエンコーディングでエンコードされたバイト文字列とし
      て返されます。

      警告:

        これらのメソッドは Python 3 で使うのは避けるべきです。
        "lgettext()" 関数に対する警告を参照してください。


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

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


23.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 は使われていないらしく、現在はサポートされ
ていません。


23.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'" はされていません。

飜訳対象の文字列を抽出するツールもあります。 オリジナルの GNU
**gettext** は C と C++ のソースコードしかサポートしませんが、拡張版の
**xgettext** は Python を含めた多くの言語で書かれたコードを読み取り、
飜訳できる文字列を発見します。 Babel は Python の国際化ライブラリで、
飜訳文字列の抽出とメッセージカタログのコンパイルを行う file:*pybabel*
スクリプトがあります。 François Pinard が開発した **xpot** と呼ばれる
プログラムは同じような処理を行え、彼の po-utils package の一部として利
用可能です。

(Python には **pygettext.py** および **msgfmt.py** という名前の pure-
Python 版プログラムもあります; これをインストールしてくれる Python デ
ィストリビューションもあります。 **pygettext.py** は **xgettext** に似
たプログラムですが Python のソースコードしか理解できず、 C や C++ のよ
うな他のプログラミング言語を扱えません。 **pygettext.py** は
**xgettext** と同様のコマンドラインインターフェースをサポートしていま
す; 詳しい使い方については "pygettext.py --help" と実行してください。
**msgfmt.py** は GNU **msgfmt** とバイナリ互換性があります。 この2つの
プログラムがあれば、 GNU **gettext** パッケージを使わずに Python アプ
リケーションを国際化できるでしょう。)

**xgettext** や **pygettext** のようなツールは、メッセージカタログであ
る ".po" ファイルを生成します。 このファイルは人間が判読可能な構造をし
ていて、ソースコード中のマークが着けられた文字列と、その文字列の仮置き
の訳文が一緒に書き込まれています。

生成された ".po" ファイルは翻訳者個々人へ頒布され、サポート対象の各自
然言語への訳文が書き込まれます。 ある言語への飜訳が完了した
"<language-name>.po" ファイルは翻訳者により返送され、 **msgfmt** を使
い機械が読み込みやすい ".mo" バイナリカタログファイルへとコンパイルさ
れます。 この ".mo" が "gettext" モジュールによる実行時の実際の飜訳処
理で使われます。

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


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

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

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

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


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

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

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

   import gettext
   gettext.install('myapplication')

ロケールの辞書を設定する必要がある場合、"install()" 関数に渡すことが出
来ます:

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


23.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()


23.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" 命令を実行するまで) 一時的に上書きす
ることができます。もしそれまでに "_()" をローカルな名前空間に持ってい
たら注意してください。

二つ目の例における "_()" の使い方では、パラメータが文字列リテラルでは
ないので、 **gettext** プログラムが翻訳可能だとは判定されないことに注
意してください。

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

   def N_(message): return message

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

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

この例では、飜訳可能な文字列に "N_()" でマークを付けているために、
"_()" の定義と衝突しません。 しかし、これではメッセージを抽出するプロ
グラムに対して "N_()" でマークされている飜訳可能な文字列を見付けるよう
に教える必要が出てきます。 **xgettext**, **pygettext**, "pybabel
extract", **xpot** は全て、コマンドラインスイッチ "-k" を使ってその機
能をサポートしています。 この例の "N_()" という名前は好きに選べます;
"MarkThisStringForTranslation()" という名前にしてしまっても構いません
。


23.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()" に関する脚注を参照してください。
