.. _topics-i18n: ====== 国際化 ====== :revision-up-to: 9084 (1.0) Django はコードとテンプレートの双方で国際化をフルサポートしています。このド キュメントでは国際化の仕組みについて説明します。 .. Overview: 概要 ==== 国際化のゴールは、一つの Web アプリケーションが複数の言語でコンテンツや機能 を提供できるようにすることにあります。 Django 開発者は、最小限のフックを Python コードとテンプレートに埋め込むこと で国際化というゴールにたどり着けます。これらのフックは **翻訳文字列 (translation string)** と呼ばれています。翻訳文字列は Django に「このテキストについてエンドユーザの言語に合ったテキストがあるなら、テキ ストを翻訳して出力せよ」と指示します。  Django はこれらのフックに注意して、ユーザの言語設定に合わせて Web アプリケー ションをオンザフライで翻訳します。 Django が行っているのは、本質的には以下の二つの作業です: * 開発者やテンプレートの作者に、アプリケーションのどの部分を翻訳できるか 指定させます。 * 指定したフックを使って、特定のユーザの言語設定に従って Web アプリケー ションを翻訳します。 .. _If you don't need internationalization in your app: 国際化が必要ない場合 ==================== Django の国際化フックはデフォルトで有効になっているので、フレームワークの一 部で i18n がらみのわずかなオーバヘッドが生じています。国際化の機能を使いた くなければ、設定ファイルで :setting:`USE_I18N = False ` を設定し てください。 :setting:`USE_I18N` を ``False`` に設定すると、 Django は国際 化機構をロードしないよう最適化を行います。 この場合、 :setting:`TEMPLATE_CONTEXT_PROCESSORS` からも ``'django.core.context_processors.i18n'`` を外すことになるでしょう。 .. _`If you do need internationalization: three steps`: 国際化が必要な場合: 3 つのステップ =================================== 1. 翻訳対象文字列を Python コードやテンプレートに埋め込みます。 2. サポートしたい言語について、翻訳対象文字列に対応する翻訳を行います。 3. Django の設定でロケールミドルウェアを有効化します。 .. admonition:: 舞台裏では :class: admonition-behind-the-scenes Django の翻訳機構は、 Python に付属の ``gettext`` モジュールを使ってい ます。 .. _`1. How to specify translation strings`: 1. 翻訳文字列の指定方法 ======================== 翻訳文字列 (translation string) は、「このテキストを翻訳対象にする」という 指定を行います。翻訳文字列は Python コードにもテンプレートにも現れます。翻 訳可能な文字列をマークしておくのは作者の役割であり、翻訳システムはマークさ れた文字列しか翻訳対象にしません。 .. _In Python code: Python コード内での指定 ----------------------- .. _Standard translation: 標準的な翻訳 ~~~~~~~~~~~~ 翻訳対象文字列を関数 ``ugettext()`` で指定します。タイプ数を減らすため、 ``ugettext()`` を ``_`` という別名で import するのが慣習的なやり方です。 .. note:: Python の標準ライブラリ ``gettext`` は、グローバルの名前空間に ``_()`` という名前で ``gettext()`` をインストールします。 Django ではこの方法に 従っていませんが、それは以下の理由からです: 1. 国際化文字セット (Unicode) のサポート下では、 ``gettext()`` よりも ``ugettext()`` の方が便利だからです。また、ファイルによっては ``ugettext_lazy()`` をデフォルトの翻訳用メソッドに使った方がよい 場合もあります。グローバル名前空間に ``_()`` がなければ、開発者に 場合に応じて適切な翻訳用メソッドを選ぶ自由を与えられます。 2. アンダースコア文字は、 Python の対話シェルや doctest で書かれたテ スト中では「直前の式の値」を表します。そのため、グローバル名前空間 に ``_()`` をインストールすると、干渉して問題を引き起こします。 ``ugettext()`` を ``_()`` という名前で明示的に import すれば、こ の問題を回避できます。 .. highlightlang:: python 下の例では、 ``"Welcome to my site."`` というテキストを翻訳文字列としてマー クします:: from django.utils.translation import ugettext as _ def my_view(request): output = _("Welcome to my site.") return HttpResponse(output) もちろん、 ``ugettext()`` に別名を付けなくても使えます。従って、下の例は上 の例と全く同じになります:: from django.utils.translation import ugettext def my_view(request): output = ugettext("Welcome to my site.") return HttpResponse(output) 翻訳は計算済みの値に対して行われます。従って、下の例も上の 2 例と同じになり ます:: def my_view(request): words = ['Welcome', 'to', 'my', 'site.'] output = _(' '.join(words)) return HttpResponse(output) 翻訳は変数に対しても使えます。従って、下の例もまた、上の例と同じになります:: def my_view(request): sentence = 'Welcome to my site.' output = _(sentence) return HttpResponse(output) (上の 2 つの例のように変数や計算済みの値を使う場合、 Django の翻訳文字列検 出ユーティリティ ``django-admin.py makemessages`` はこれらの文字列を検出で きないので注意しておきましょう。詳しくは後の ``makemessages`` の節で説明し ます。) ``_()`` や ``ugettext()`` に渡す文字列には、 Pyton の標準の名前付き補完構文 によるプレースホルダを使えます。例えば:: def my_view(request, m, d): output = _('Today is %(month)s, %s(day)s.') % {'month': m, 'day': d} return HttpResponse(output) このテクニックを使うと、言語ごとの翻訳でプレースホルダを並べ変えできるよう になり、例えば、英語の翻訳文が ``"Today is Nobember, 26."`` であるのに対し て、スペイン語では ``"Hoy es 26 de Noviembre."`` であるように、プレースホル ダの位置を翻訳文の前後で移動できます。 この理由から、引数が複数ある場合には、固定引数を使った補完 (``%s`` や ``%d``) ではなく、名前付きの補完 (``%(day)s``) を使ってください。固定引数 による補完を使った場合、プレースホルダの順番によってうまく翻訳できない場合 があります。 .. _Marking strings as no-op: すぐには翻訳しない文字列をマークする ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ すぐには翻訳しない文字列のマークには ``django.utils.translation.ugettext_noop()`` を使って下さい。マークした文字 列は後で変数として使われるときに翻訳されます。 この関数は、ソース言語の中に定数として文字列を置いておきたい場合に使います。 というのも、定数は、例えばデータベース中の文字列のように、システムやユーザ 間で共通な値である一方で、ユーザにメッセージとして提示する最後の段階で翻訳 せねばならない場合があるからです。 .. _lazy-translations: 翻訳を遅延させる ~~~~~~~~~~~~~~~~ 文字列の翻訳を遅延 (lazy) させるには、 ``django.utils.translation.ugettext_lazy()`` を使います。翻訳を遅延させると、 ``ugettext_lazy()`` を呼び出すまで翻訳文字列の値にアクセスしません。 例えば、モデルの ``help_text`` を翻訳する場合に以下のようにします:: from django.utils.translation import ugettext_lazy class MyThing(models.Model): name = models.CharField(help_text=ugettext_lazy('This is the help text')) この例では、 ``ugettext_lazy()`` は実際の翻訳文字列ではなく、文字列への遅延 参照 (lazy reference) を保存します。翻訳自体は文字列をコンテキストで使った 時、例えば admin サイトでテンプレートをレンダリングしたときに初めて実行され ます。 ``ugettext_lazy`` という名前が冗長で嫌なら、以下のようにして ``_`` (アンダー スコア) にエイリアスできます:: from django.utils.translation import ugettext_lazy as _ class MyThing(models.Model): name = models.CharField(help_text=_('This is the help text')) :ref:`Django モデル ` の中では、常に遅延翻訳を使うように してください。フィールド名やテーブル名は翻訳マークをつけておきましょう。 そうしないと、 admin インタフェース上で翻訳されません。フィールド名やテーブ ル名の翻訳マークは、 ``Meta`` クラス内で明示的に ``verbose_name`` や ``verbose_name_plural`` オプションを指定して行います:: from django.utils.translation import ugettext_lazy as _ class MyThing(models.Model): name = models.CharField(_('name'), help_text=_('This is the help text')) class Meta: verbose_name = _('my thing') verbose_name_plural = _('mythings') .. _Pluralization: 複数形化 ~~~~~~~~~~~~~ 複数形のメッセージを指定するには ``django.utils.translation.ungettext()`` を 使います。例えば:: from django.utils.translation import ungettext def hello_world(request, count): page = ungettext('there is %(count)d object', 'there are %(count)d objects', count) % { 'count': count, } return HttpResponse(page) ``ungettext`` は、単数形の翻訳文字列、複数形の翻訳文字列、そしてオブジェクト の数 (翻訳言語に ``count`` という変数で渡されます) という 3 つの引数をとり ます。 .. _In template code: テンプレート内での翻訳 ---------------------- .. highlightlang:: html+django :ref:`Django テンプレート ` 中の翻訳は、二つのテンプレー トタグを使ってPython コードとは少し違った方法で行います。テンプレートで翻訳 用のタグを使えるようにするには、テンプレートの上の方に ``{% load i18n %}`` を入れておきます。 テンプレートタグ ``{% trans %}`` は定数の文字列 (シングルクオートまたはダブ ルクオートで囲まれた文字列) や変数を翻訳します:: {% trans "This is the title." %} {% trans myvar %} ``noop`` オプションを指定すると、値の参照は行われますが、翻訳はしません。 ``noop`` は、将来翻訳が必要なコンテンツを「スタブ」するのに便利です。 {% trans "myvar" noop %} ``{% trans %}`` の中では定数文字列とテンプレート変数を同時に扱えません。翻 訳中で変数 (プレースホルダ) を使いたい場合には、以下の例のように ``{% blocktrans %}`` を使います:: {% blocktrans %}This string will have {{ value }} inside.{% endblocktrans %} テンプレート式を翻訳したい場合、すなわちテンプレートフィルタの出力を翻訳し たい場合には、式をローカルな変数にバインドして、翻訳ブロック中で使えるよう にせねばなりません:: {% blocktrans with value|filter as myvar %} This will have {{ myvar }} inside. {% endblocktrans %} ``blocktrans`` タグの中で複数個の式を束縛したい場合には、 ``and`` を使って 分割します:: {% blocktrans with book|title as book_t and author|title as author_t %} This is {{ book_t }} by {{ author_t }} {% endblocktrans %} 複数形化するには、 ``{% blocktrans %}`` と ``{% endblocktrans %}`` の間に ``{% plural %}`` タグで単数形と複数形の両方の形式を記述します:: {% blocktrans count list|length as counter %} There is only one {{ name }} object. {% plural %} There are {{ counter }} {{ name }} objects. {% endblocktrans %} 内部的には、ブロックおよびインラインの翻訳は全て適切な ``ugettext`` / ``ungettext`` 呼び出しを行います。 ``RequestContext`` は 3 つの翻訳処理固有の変数にアクセスできます: * ``LANGUAGES`` は各言語の言語コードと (現在有効なロケールを使って翻訳 した) 言語名からなるタプルでできた言語のリストです。 * ``LANGUAGE_CODE`` は現在のユーザ設定言語で、文字列です。例: ``en-us`` (後述の "言語設定の検出メカニズム" を参照してください)。 * ``LANGUAGE_BIDI`` は現在の言語の表記方向 (direction) です。 ``True`` ならば、ヘブライ語やアラビア語のように右から左に記述する言語を示し、 ``False`` なら英語、フランス語、ドイツ語のように左から右に記述する言 語を指します。 ``RequestContext`` 拡張を使わなければ、以下の 3 つのタグを使って値を取得でき ます:: {% get_current_language as LANGUAGE_CODE %} {% get_available_languages as LANGUAGES %} {% get_current_language_bidi as LANGUAGE_BIDI %} これらのタグを使うには ``{% load i18n %}`` が必要です。 翻訳フックは定数文字列を使うテンプレートブロック全てでも利用できます。 ``_()`` 構文を使って翻訳文字列を指定してください。例えば:: {% some_special_tag _("Page not found") value|yesno:_("yes,no") %} このばあい、タグとフィルタの両方は翻訳済みの文字列を扱うことになるので、翻 訳の有無について気を配る必要がなくなります。 .. note:: 上の例では、翻訳インフラストラクチャには文字列 ``"yes,no"`` が渡されま す。 ``"yes"`` と ``"no"`` の別々の文字列が渡されるわけではありません。 フィルタが引数の文字列を正しく分割できるように、翻訳済みの文字列にはカ ンマが入っていなければなりません。例えば、ドイツ語の翻訳は、 (カンマを そのまま残して) ``"yes,no"`` を ``"ja,nein"`` に翻訳せねばなりません。 .. _`Django テンプレート`: ../templates_python/ .. _Django templates: ../templates_python/ .. _Working with lazy translation objects: 遅延翻訳オブジェクトを操作する -------------------------------- .. highlightlang:: python モデルやユーティリティ関数では、 ``ugettext_lazy()`` や ``ungettext_lazy()`` を使って文字列をマークすることがよくあります。こうして マークした文字列をコードの他の部分で扱うときには、マークしてできた遅延翻訳 オブジェクトをうっかり文字列に変換してしまわないよう気を付けてください。遅 延翻訳オブジェクトの変換は (ロケールの影響下に入るように) できるだけ遅くせ ねばならないからです。遅延翻訳オブジェクトの変換を遅らせるために、以下の二 つのヘルパ関数があります。 .. _`Joining strings: string_concat()`: 文字列の結合: string_concat() ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 標準の Python 文字列型の join メソッド (``''.join([...])``) は、 遅延翻訳オブジェクトの入ったリストをうまく扱えません。その代わり、 ``django.utils.translation.string_concat()`` を使ってください。このメソッド は、全ての内容を結合し、 *かつ* 文字列中に値が取り込まれるまで実際に変換を 行わないような遅延オブジェクトを生成して返します。例えば:: from django.utils.translation import string_concat ... name = ugettext_lazy(u'John Lennon') instrument = ugettext_lazy(u'guitar') result = string_concat([name, ': ', instrument]) 上のケースでは、 ``result`` 中の遅延翻訳オブジェクトは、 ``result`` 自体を 文字列中で使った場合 (テンプレートのレンダリング時など) にしか文字列に変換 されません。 .. _The allow_lazy() decorator: allow_lazy() デコレータ ~~~~~~~~~~~~~~~~~~~~~~~ Django はたくさんのユーティリティ関数を (とりわけ ``django.utils`` パッケー ジで) 提供しています。これらの関数の多くは文字列を第一引数にとり、文字列に 対して何らかの処理を行います。関数はテンプレートフィルタ内で使われたり、他 のコードで直接呼び出されたりしています。 同様の関数を自分で作成し、翻訳文字列を扱おうとした場合、第一引数が遅延翻訳 オブジェクトの場合に問題に直面することでしょう。この関数はビューの外側 (つ まり、現在のスレッドのロケール設定が的確でないかもしれない場所) で使われる かもしれないので、関数内で遅延翻訳オブジェクトを文字列に変換したくないはず だからです。 こうした場合のために、 ``django.utils.functional.allow_lazy()`` デコレータ を使ってください。このデコレータで関数をラップすると、関数の第一引数に遅延 翻訳オブジェクトを渡した場合、関数の評価を文字列に変換する瞬間まで遅延させ られます。 例を示しましょう:: from django.utils.functional import allow_lazy def fancy_utility_function(s, ...): # Do some conversion on string 's' ... fancy_utility_function = allow_lazy(fancy_utility_function, unicode) ``allow_lazy()`` デコレータは関数名に加えて追加の引数 (``*args``) をとりま す。この引数には、デコレーション対象の関数の戻り値の型 (複数可) を指定しま す。通常は、 ``unicode`` だけを入れておき、関数が必ず Unicode 文字列を返す ようにしておけばよいでしょう。 このデコレータを使えば、適切な文字列を入力として受け取る関数を書いておき、 後で遅延翻訳オブジェクトのサポートを追加できます。 .. _how-to-create-language-files: .. _`2. How to create language files`: 2. 言語ファイルの作成 ====================== 文字列に翻訳用のタグをつけたら、今度は翻訳文自体を書く (または手に入れる) 必要があります。ここでは翻訳文を書く方法について示します。 .. admonition:: ロケールの制約 Django は、 Django 本体に対する翻訳カタログのない言語への地域化をサポー トしていません。ある言語向けの自作のカタログを提供しても、 Django 本体 にその言語のサポートがなければ、カタログは無視されます。自作のアプリケー ションに特定の言語のロケールをサポートさせたいのなら、まずは Django の コア部分に対する最小限の翻訳カタログを作成する必要があるでしょう。また、 その場合、翻訳されたメッセージ (自作のアプリケーション内のカタログ) と 英語のメッセージ (Django 自体の不完全なカタログ) が入り混じった表示になっ てしまうでしょう。くわしくは :ref:`LocaleMiddleware の注意事項 ` を参照して ください。 .. _Message files: メッセージファイル ------------------ 最初のステップは、新たに追加する言語用の **メッセージファイル** の作成です。 メッセージファイルは平文テキストファイルで、言語ごとに作成され、翻訳文字列 全てと、言語ごとの対応する表現が収められています。メッセージファイルの拡張 子は ``.po`` です。 Django には ``django-admin.py makemessages`` というツールが付属しています。 このツールはメッセージファイルの作成や維持を自動化します。 .. admonition:: ベテラン Django ユーザへの注意 以前からある ``bin/make-messages.py`` ツールの機能は、 Django の操作に 一貫性をもたせるために、 ``django-admin.py makemessages`` に移動しまし た。 メッセージファイルの作成や更新を行うには、以下のようにコマンドを実行します:: django-admin.py makemessages -l de ここで、 ``de`` は作成したいメッセージファイルの言語コードです。言語コード はロケール表示の形式にします。例えば、ブラジル系ポルトガル語の場合には ``pt_BR`` で、オーストリアドイツは ``de_AT`` です。 スクリプトは以下の 3 種類の場所のいずれかで実行します: * Django プロジェクトのルートディレクトリ。 * Django アプリケーションのルートディレクトリ。 * ``django`` のルートディレクトリ (Subversion からチェックアウトしたと きのルートではなく、 ``$PYTHONPATH`` にリンクされているか、 ``$PYTHONPATH`` 上のどこかにあるディレクトリです)。この場所で実行する のは、 Django 自体の翻訳カタログを生成するときだけです。 :ref:`contributing-translations` を参照してください。 スクリプトはプロジェクトのソースツリーやアプリケーションのソースツリーを走 査して、翻訳用にマークされた全ての文字列を取り出します。スクリプトは ``/locale/LANG/LC_MESSAGES`` 下にメッセージファイルを作成 (もしくは更新) し ます。 ``de`` の例では、ファイルは ``/locale/de/LC_MESSAGES/django.po`` で す。 デフォルトの設定では、 ``django-admin.py makemessages`` は拡張子 ``.html`` のファイルも検索します。デフォルトの設定をオーバライドしたければ、 ``--extension`` または ``-e`` オプションを使って、拡張子を指定してください:: django-admin.py makemessages -l de -e txt 複数の拡張子を扱いたいのなら、カンマで区切るか、 ``-e`` や ``--extension`` を複数回指定します:: django-admin.py makemessages -l=de -e=html,txt -e xml `JavaScript の翻訳カタログ`_ を生成したいのなら、 ``-e js`` **ではなく** 'djangojs' ドメインを使ってください。 .. _create a JavaScript translation catalog: `Creating JavaScript translation catalogs`_ .. _`JavaScript の翻訳カタログ`: `create a JavaScript translation catalog`_ .. admonition:: gettext がなかったら? ``gettext`` ユーティリティをインストールしていない場合、 ``django-admin.py makemessages`` は空のファイルを作成します。その場合、 ``gettext`` ユーティリティをインストールするか、英語用の空のメッセージ ファイル (``locale/en/LC_MESSAGES/django.po``) をコピーして使って下さい。 .. admonition:: Windows で動かしたいのですが? Windows を使っていて、 ``django-admin compilemessages`` を動作させるため に GNU gettext ユーティリティをインストールたいのなら、 `gettext on Windows`_ を参照してください。 ``.po`` ファイルは素直な形式で書かれています。 ``.po`` ファイルには翻訳メン テナのコンタクト情報のようなわずかなメタデータが入っています。それ以外の大 部分は **メッセージ** のリストです。メッセージは翻訳文字列と特定の言語用の 実際の翻訳テキストです。 例えば、 Django アプリケーションに ``"Welcome to my site."`` というテキスト の翻訳文字列が以下のように入っていたとします:: _("Welcome to my site.") ``django-admin.py makemessages`` を実行すると、以下のようなコード断片を含む ``.po`` ファイルを作成するはずです:: #: path/to/python/module.py:23 msgid "Welcome to my site." msgstr "" 上の内容を簡単に説明しましょう: * ``msgid`` は翻訳文字列で、ソースコードに書かれていたものです。変更し てはなりません。 * ``msgstr`` には各言語の翻訳を入れます。最初は空になっており、変更する のはユーザの責任です。翻訳文字列の周りにクオートを忘れないように注意 してください。 * 便宜上、各メッセージには該当する翻訳文字列のあったファイル名と行番号 が ``msgid`` 行の上の ``#`` ではじまる行に入っています。 長いメッセージは特別なケースとして扱います。 ``msgstr`` (または ``msgid``) の直後の文字列が空文字列の場合、コンテンツ自体はその次の複数行にわたって書 かれているものとみなします。これらの文字列は直接結合されるので、文字列の中 間では末尾にスペースを忘れないようにしましょう。さもないと、空白なしで文字 列がくっついてしまいますよ! .. admonition:: 文字コードセットに注意 PO ファイルをテキストエディタで作成するときには、文字コードセット の行 (``"CHARSET"`` を探して下さい) をまず編集して、これから編集に使う 文字セットにしてください。 ``gettext`` ツールの内部動作の仕組み上、また、 Django のコア部分やアプリケーションで非 ASCII のソース文字列を扱えるよ うにするために、 PO ファイルのエンコーディングは必ず UTF-8 にしてくださ い。 全てのソースコードとテンプレートを新たな翻訳文字列でためし、 **全ての** 言 語用にメッセージファイルを更新するには、以下のようにします:: django-admin.py makemessages -a .. _Compiling message files: メッセージファイルのコンパイル ------------------------------ メッセージファイルを作成して、変更し終えたら ``gettext`` を使ってメッセージ ファイルをより効率的な形式にコンパイルします。作業は ``django-admin.py makemessages`` ユーティリティで行いましょう。 このツールは全ての ``.po`` ファイルをコンパイルして ``.mo`` ファイルを作成 します。 ``.mo`` ファイルはバイナリファイルで、 ``gettext`` で使うために最 適化されています。 ``django-admin.py makemessages`` を実行したのと同じディ レクトリで、以下のように ``django-admin.py compilemessages`` を実行してくだ さい:: django-admin.py compilemessages これで終わりです。もう翻訳を使えるようになっているはずです。 .. admonition:: ベテラン Django ユーザへの注意 以前からある ``bin/compile-messages.py`` ツールの機能は、 Django の操作 に一貫性をもたせるために、 ``django-admin.py compilemessages`` に移動し ました。 .. admonition:: Windows で動かしたいのですが? Windows を使っていて、 ``django-admin compilemessages`` を動作させるため に GNU gettext ユーティリティをインストールたいのなら、 `gettext on Windows`_ を参照してください。 .. _`3. How Django discovers language preference`: 3. 言語設定の検出メカニズム ============================ 翻訳の準備を完了した、あるいは Django 付属の翻訳を使いたいだけなら、あとは アプリケーションで翻訳を有効にするだけです。 背後では、 Django はユーザの使用言語を決めるモデルを備えています。このモデ ルは柔軟で、インストール全体、あるいは特定のユーザ、またはその両方に対して 使用言語を決定できます。 インストール全体での使用言語を設定するには、 :setting:`LANGUAGE_CODE` を設 定します。 Django この設定をデフォルトの翻訳言語、すなわち他の適切な翻訳が ない場合に試みる言語に設定します。 Django をネイティブの言語で動かしたいだけで、かつ自分の言語に対する言語ファ イルをすでに準備しているのなら、 ``LANGUAGE_CODE`` を設定するだけで済みます。 個々のユーザが自分の使いたい言語を選択できるようにするには ``LocaleMiddleware`` を使ってください。 ``LocaleMiddleware`` は、リクエスト に埋め込まれたデータに基づいた言語の選択を可能にし、ユーザごとにコンテンツ をカスタマイズします。 ``LocaleMiddleware`` を使うには、 ``MIDDLEWARE_CLASSES`` 設定に ``'django.middleware.locale.LocaleMiddleware'`` を追加します。ミドルウェア の順番は重要で、以下のガイドラインに従って下さい: * まず、インストール済みのミドルウェアの先頭にくるようにしてください。 * ``LocaleMiddleware`` はセッションを使うので、 ``SessionMiddleware`` の後ろに配置してください。 * ``CacheMiddleware`` を使っているなら、その後ろに ``LocaleMiddleware`` を配置してください。 例えば、 ``MIDDLEWARE_CLASSES`` は以下のようになります:: MIDDLEWARE_CLASSES = ( 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.locale.LocaleMiddleware', 'django.middleware.common.CommonMiddleware', ) (ミドルウェアの詳細は :ref:`ミドルウェアのドキュメント ` を参照してください。) ``LocaleMiddleware`` はユーザの言語設定を以下のようなアルゴリズムで決定しよ うと試みます: * まず、現在のユーザのセッションに ``django_language`` キーがないか探し ます。 * なければ、クッキーを探します。 .. versionchanged:: 1.0 バージョン 0.96 以前の Djangoでは、クッキーの名前は ``django_language`` にハードコードされていました。 1.0 では、クッキー の名前を :setting:`LANGUAGE_COOKIE` で設定します。(クッキーのデフォル ト名は ``django_language`` です。) * なければ、 ``Accept-Language`` HTTP ヘッダを探します。このヘッダはブ ラウザから送信され、サーバに対して順位つきで言語設定を知らせてきます。 Djang はこの設定を順に調べ、利用可能な翻訳のある言語を探します。 * なければ、グローバルに設定された ``LANGUAGE_CODE`` の設定を使います。 .. _locale-middleware-notes: 注意: * 上記のどのステップでも、言語設定は標準の言語名表記法に従った文字列で 書かれているものと想定しています。例えば、ブラジル系ポルトガル語は ``pt-br`` です。 * 基本言語 (base language) が指定されていて、副言語 (sublanguage) が指 定されていない場合、 Django は基本言語の設定を優先します。例えば、ユー ザが ``de-at`` (オーストリアドイツ語) を指定しているのに対して、 Django 側には ``de`` のしかない場合、 Django は ``de`` を使います。 * :setting:`LANGUAGES` 設定にリストアップした言語しか選択できません。 (全ての言語に対する翻訳を提供できないなどの理由で) 言語選択を指定の言 語のサブセットに制限したい場合には、 ``LANGUAGES`` を設定します。例え ば:: LANGUAGES = ( ('de', _('German')), ('en', _('English')), ) この例では、自動生成されるメニューで利用可能な言語をドイツ語:de と 英語:en (および de-ch や en-us のような副言語) に制限しています。 .. _`LANGUAGES 設定`: ../settings/#languages .. _LANGUAGES setting: ../settings/#languages * 上の項で説明したように、カスタムの ``LANGUAGES`` 設定を行った場合、そ の言語を翻訳対象文字列に含めても構いません。ただし、 ``django.utils.translation`` の ``ugettext()`` ではなく、「ダミーの」 ``ugettext()`` でマークしてください。循環 import を防ぐため、 *決して* 設定ファイル中で ``django.utils.translation`` を import しないでくだ さい。 カスタム ``LANGUAGES`` のマークアップは「ダミーの」 ``ugettext()`` 関 数で解決します。以下に設定ファイルでの記述例を示します:: ugettext = lambda s: s LANGUAGES = ( ('de', ugettext('German')), ('en', ugettext('English')), ) このように設定しておいても、 ``django-admin.py makemessages`` は翻訳 文字列を検出して翻訳対象としてマークします。ただし、実行時の翻訳はお こなわれません。したがって、実行時には ``LANGUAGES`` を使うコードを *本当の* ``ugettext()`` でラップしておかねばなりません。 * ``LocaleMiddleware`` で選択できるのは、 Django が基本的な部分の翻訳を 提供している言語だけです。 Django のソースツリーの翻訳セットに入って いない言語の翻訳を提供したければ、まずその言語むけの基本部分の翻訳を 提供する必要があります。例えば、Django はテクニカルメッセージ ID (technical message ID) を使って日付や時刻のフォーマットを解釈するので、 システムを正しく動作させるには少なくともこうした部分の翻訳が必要にな ります。 作業を始めるには、まず英語用の ``.po`` ファイルをコピーするとよいでしょ う。少なくともテクニカルメッセージだけは翻訳します。バリデーション時 のメッセージもやっておくとよいでしょう。 テクニカルメッセージ ID は簡単に区別できます。メッセージ ID は全て大 文字でできているからです。このメッセージ ID は他のメッセージと同じよ うに翻訳してよいものではなく、ローカルの正しい形式を指定せねばなりま せん。例えば、 ``DATETIME_FORMAT`` (あるいは ``DATE_FORMAT`` や ``TIME_FORMAT``) の場合、自分の言語における正しいフォーマット文字列を 指定せねばなりません。フォーマットは ``now`` テンプレートタグで使われ ているフォーマット文字列と同じ文法に従います。 ``LocaleMiddleware`` がユーザ設定を検出すると、その設定に :class:`~django.http.HttpRequest` の ``request.LANGUAGE_CODE`` でアクセスで きます。この値はビューコードで自由に読みだしてかまいません。以下に一例を挙 げます:: def hello_world(request, count): if request.LANGUAGE_CODE == 'de-at': return HttpResponse("You prefer to read Austrian German.") else: return HttpResponse("You prefer to read another language.") 静的な (ミドルウェアを使わない) 翻訳では、言語設定は ``settings.LANGUAGE_CODE`` の値になり、動的な (ミドルウェアを使った) 翻訳で は、言語設定は ``request.LANGUAGE_CODE`` の値になるので注意してください。 .. _settings file: ../settings/ .. _`設定ファイル`: `settings file`_ .. _middleware documentation: ../middleware/ .. _`ミドルウェアのドキュメント`: `middleware documentation`_ .. _session: ../sessions/ .. _`セッション`: session_ .. _request object: ../request_response/#httprequest-objects .. _`リクエストオブジェクト`: `request object`_ .. _translations-in-your-own-projects: .. _Using translations in your own projects: 自作のプロジェクトで翻訳を使う ============================== Django は以下のアルゴリズムに従って翻訳を探します: * まず、現在呼び出されているビューの入っているアプリケーションディレク トリ下に ``locale`` ディレクトリを探します。現在選択されている言語に 対応する翻訳があれば、その翻訳をインストールします。 * 次に、プロジェクトディレクトリ下に ``locale`` ディレクトリを探します。 翻訳があれば、その翻訳をインストールします。 * 最後に、 ``django/conf/locale`` にある Django 付属の翻訳をチェックし ます。 こうすることで、独自の翻訳の入ったアプリケーションを書いたり、基本の翻訳の 内容をプロジェクトパスに置いた翻訳でオーバライドしたりできます。また、複数 の小さなアプリケーションで大きめのプロジェクトを構築するときに、全ての翻訳 を一つのプロジェクト単位のメッセージファイルにまとめておけます。どういう方 法をとるかはユーザ次第です。 .. note:: :ref:`settings-without-django-settings-module` に示したように、 :setting:`DJANGO_SETTINGS_MODULE` を使わずに手動で設定を行った場合、プ ロジェクトディレクトリ内の ``locale`` ディレクトリはチェックされません。 これは Django がプロジェクトディレクトリの場所を調べる術を持たないから です (Django は通常、設定ファイルのある場所を基準に ``locale`` ディレク トリの場所を調べますが、手動で設定を行うと設定ファイルが存在しなくなっ てしまうからです)。 メッセージファイルリポジトリも同じような構成になっています: * ``$APPPATH/locale//LC_MESSAGES/django.(po|mo)`` * ``$PROJECTPATH/locale//LC_MESSAGES/django.(po|mo)`` * 設定ファイルの ``LOCALE_PATHS`` に指定されている全てのパスを指定順に 検索して ``/LC_MESSAGES/django.(po|mo)`` を探します。 * ``$PYTHONPATH/django/conf/locale//LC_MESSAGES/django.(po|mo)`` メッセージファイルの作成には、 Django メッセージファイルと同じ ``django-admin.py makemessages`` ツールを使って下さい。ツールの実行は正しい 場所、すなわち ``conf/locale`` (ソースツリーの場合) か、あるいは ``locale`` (アプリケーションメッセージやプロジェクトメッセージの場合) ディレクトリのあ るディレクトリで行わねばなりません。また、 ``gettext`` の使うバイナリ形式の ``django.mo`` ファイルを生成するには ``django-admin.py compilemessages`` を 使います。 ``django-admin.py compilemessages --settings=path.to.settings`` を実行すれ ば、コンパイラに ``LOCALE_PATHS`` に設定された全てのディレクトリを処理させ られます。 アプリケーションメッセージファイルを発見するメカニズムはやや複雑で、 ``LocaleMiddleware`` が必要になります。従って、このミドルウェアを使わない場 合、 Django メッセージファイルとプロジェクトメッセージファイルだけが処理さ れます。 最後に、翻訳ファイルをどのように構成するかしっかりと考えておくように勧めま す。自分の作ったアプリケーションを他のユーザに配ったり、他のプロジェクトで 利用したりするなら、アプリケーション固有の翻訳が必要になるでしょう。しかし、 アプリケーション固有のメッセージやプロジェクトごとの翻訳は ``makemessages`` にまつわる困った問題を引き起こすことがあります: ``makemessages`` は現在のパス以下の全てのディレクトリを検索してしまうので、 すでにアプリケーションメッセージファイルに入っているメッセージ ID が、プロ ジェクトのメッセージファイルに入ってしまうことがあるのです。 この問題の最も簡単な解決法は、プロジェクトを直接的に構築しない (なおかつ独 自の翻訳を備えている) アプリケーションをプロジェクトツリーの外に配置してお くというものです。こうすれば、プロジェクトレベルで ``django-admin.py make-messages`` を実行しても、自分のプロジェクトに明に関 係する部分の文字列だけを翻訳し、別個に配布されたアプリケーションの文字列を 対象にしなくなります。 .. _The set_language redirect view: ``set_language`` リダイレクトビュー ===================================== 利便性のために、 Django には ``django.views.i18n.set_language`` ビューが定 義されています。このビューはユーザの言語プリファレンスを設定して、遷移前の ページにリダイレクトします。 このビューを有効にするには、以下の行を URLconf に追加します:: (r'^i18n/', include('django.conf.urls.i18n')), (この例では ``/i18n/setlang/`` でビューを使えるようにします) ビューは、リクエストに ``language`` が設定された状態で、 ``POST`` メソッド で呼び出すようになっています。セッションのサポートが有効であれば、ビューは ユーザのセッションに選択した言語を保存します。セッションのサポートがなけれ ば、言語設定を ``django_language``` クッキーに保存します。 (開発版の Django を使っているなら、クッキーの名前は ``LANGUAGE_COOKIE_NAME`` 設定で変更できます。) 選択された言語に設定した後、 Django は以下のアルゴリズムに従ってリダイレク トを行います: * Django は ``POST`` データから ``next`` パラメタを探します。 * ``next`` がないか、空の値なら、 ``Referer`` ヘッダを使って遷移元を決 定しようとします。 * ``Referer`` の値も空の場合、例えばユーザのブラウザがリファラの送信を 抑制している場合には、フォールバックとして、ユーザは ``/`` (サイトの ルート URL) にリダイレクトします。 以下に HTML テンプレートのコード例を示します: .. code-block:: html+django
.. _`Translations and JavaScript`: 翻訳と JavaScript ================= JavaScript に翻訳を追加しようとすると、いくつかの問題に直面します: * JavaScript コードには ``gettext`` 実装へのアクセス手段がありません。 * JavaScript コードには .po や .mo ファイルへのアクセス手段がありません。 というのも、これらのファイルはサーバに置かれているからです。 * JavaScript の翻訳カタログはできるだけ小さくしておかねばなりません。 Django では、これらの問題に対する解決策を組み込みで提供しています。この解決 策は翻訳を JavaScript に渡して、 ``gettext`` などを JavaScript コード内で呼 び出せるようにします。 .. _`The javascript_catalog view`: ``javascript_catalog`` ビュー ------------------------------- 前述の問題に対する解決策は、 ``javascript_catalog`` ビューにあります。この ビューは ``gettext`` インタフェースをまねた関数の入った JavaScript コードと、 翻訳文字列のアレイを送信します。翻訳文字列のアレイは ``info_dict`` や URL の指定に従ってアプリケーションやプロジェクト、Django コア部分から取り出され ます。 例えば以下のようにフックをかけたとしましょう:: js_info_dict = { 'packages': ('your.app.package',), } urlpatterns = patterns('', (r'^jsi18n/$', 'django.views.i18n.javascript_catalog', js_info_dict), ) ``packages`` のタプルに入っている各文字列は Python のドット区切りのパッケー ジ表記 (``INSTALLED_APPS`` で使われている書式と同じ) で、 ``locale`` ディレ クトリの入っているパッケージにします。複数のパッケージを指定した場合、全て のカタログが一つのカタログに統合されます。この仕様は、複数のアプリケーショ ンの文字列を扱うような JavaScript で便利です。 URL パターンにパッケージ名を入れておけば、ビューを動的にできます:: urlpatterns = patterns('', (r'^jsi18n/(?P\S+?)/$', 'django.views.i18n.javascript_catalog'), ) こうしておいて、パッケージ名を '+' で区切ったパッケージ名リストとして指定で きます。これは、複数のアプリケーションからのコードを使っていて、変更が頻繁 に起きている場合、巨大なカタログファイルを毎回プルしなくてすむので便利です。 セキュリティ上の理由から、パッケージ名リストに指定できるのは、 ``django.conf`` か ``INSTALLED_APPS`` 設定に入っているアプリケーションだけ です。 .. _Using the JavaScript translation catalog: JavaScript 翻訳カタログを使う ----------------------------- カタログを使うには、単に以下のようにして動的に生成されたスクリプトをプルし ます:: これはまさに admin がサーバから翻訳を取り出しているのと同じ方法です。カタロ グをロードしたら、JavaScript から標準的な ``gettext`` インタフェースを使っ てアクセスできるようになります:: document.write(gettext('this is to be translated')); ``ngettext`` インタフェースもあります:: var object_cnt = 1 // or 0, or 2, or 3, ... s = ngettext('literal for the singular case', 'literal for the plural case', object_cnt); 文字列補完を行う関数もあります:: function interpolate(fmt, obj, named); ``interpolate`` 関数は、固定引数による補完と名前付き補完の両方をサポートし ています。従って、上のコードは以下のようにも書けます:: s = interpolate(ungettext('this is %s object', 'this are %s objects', 11), [11]); 補完の構文は Python から借りたもので、固定引数と名前つきの文字列補完をサポー トしています: * 固定引数型の補完: ``obj`` には JavaScript の Array オブジェクトが入り ます。 ``interpolate`` は Array の各要素を使って、 ``fmt`` 内のプレー スホルダを順番に置換してゆきます。例えば:: fmts = ngettext('There is %s object. Remaining: %s', 'There are %s objects. Remaining: %s', 11); s = interpolate(fmts, [11, 20]); // s is 'There are 11 objects. Remaining: 20' * 名前つき補完: このモードは、オプションの ``named`` パラメタに ``true`` を指定して選択します。 ``obj`` には JavaScript のオブジェク トか、連想配列が入ります。例えば:: d = { count: 10 total: 50 }; fmts = ngettext('Total: %(total)s, there is %(count)s object', 'there are %(count)s of a total of %(total)s objects', d.count); s = interpolate(fmts, d, true); とはいえ、この文字列補完を派手に使わない方がよいでしょう: 補完機能は JavaScript で動いており、中では何度も正規表現置換を行っています。この処理は Python の文字列補完ほど高速ではないので、本当に必要な場合 (例えば ``ngettext`` を使って適切な複数形表現を実現したい場合) だけにしてください。 .. _Creating JavaScript translation catalogs: JavaScript の翻訳カタログを作成する ----------------------------------- JavaScript の翻訳カタログの作成と更新方法、他の Django の翻訳カタログの場合 と同じで、 ``django-admin.py makemessages`` ツールを使います。ただし、 ``-d djangojs`` パラメタを指定してください。例えば:: django-admin.py makemessages -d djangojs -l de 上の例では、ドイツ語向けの JavaScript の翻訳カタログを作成または更新してい ます。翻訳カタログを更新したら、通常の Django 翻訳カタログと同じように、 ``django-admin.py compilemessages`` を実行してください。 .. _Specialties of Django translation: Django 翻訳の特徴 ================= ``gettext`` について詳しければ、 Django の翻訳機能には以下のような特徴があ ることに気づくでしょう: * 文字列ドメインは ``django`` または ``djangojs`` です。この文字列ドメ インは、共通のメッセージファイルライブラリ (通常は ``/usr/share/locale/`` にあります) にデータを保存している他のプログラ ムと Django のデータを区別するためです。 ``django`` ドメインは、 Python とテンプレート翻訳文字列に使われ、グローバルな翻訳カタログ上に 読み込まれます。 ``djangojs`` は JavaScript だけで使うために、可能な かぎり小さくして分けてあります。 * Django は ``xgettext`` を単体では使いません。 Django では、 ``xgettext`` や ``msgfmt`` を Python ラッパ越しに使います。これは便宜 上の理由によります。 .. _gettext on Windows: Windows で ``gettext`` を使う ============================== この節の操作が必要なのは、 メッセージ ID を抜き出したり、メッセージファイル を (``.po`` に) コンパイルしたいときだけです。翻訳の作業自体はファイルを編 集するだけですが、メッセージファイルを自分で作成したい場合や、変更したメッ セージファイルをテストしたりコンパイルしたい場合には、以下のようにして ``gettext`` ユーティリティを入れる必要があります: * 以下の ZIP ファイルを http://sourceforge.net/projects/gettext から取得します: * ``gettext-runtime-X.bin.woe32.zip`` * ``gettext-tools-X.bin.woe32.zip`` * ``libiconv-X.bin.woe32.zip`` * ダウンロードしたファイルを同じフォルダ (例えば ``C:\ProgramFiles\gettext-utils``) に展開します。 * システム環境変数の PATH を変更します: * ``コントロールパネル > システム > 高度な設定 > 環境変数`` の順に辿 ります。 * ``システム環境変数`` リストで、 ``Path`` を選び、 ``編集`` を押しま す。 * ``変数値`` フィールドの値の末尾に ``;C:\Program Files\gettext-utils\bin`` を追加します。