==== 翻訳 ==== :revision-up-to: 17812 (1.4) .. module:: django.utils.translation 概要 ==== Django プロジェクトを翻訳可能にするためには、 Python コードに最小限のフックを入 れなければなりません。このフックは :term:`翻訳文字列 ` と呼ばれます。翻訳文字列は Django に「もしこのテキストがエンドユーザの言語に翻 訳可能であれば、翻訳すべきだ」ということを教えます。翻訳可能な文字列をマークす ることは開発者の責任です。システムは教えられた文字列だけを翻訳できます。 Django は翻訳文字列を :term:`メッセージファイル` に抽出するユーティリティを提供 します。このファイルがあるため、翻訳者が対象の言語において翻訳文字列に対応する 文字列を用意することが簡単になります。翻訳者がメッセージファイルの中身を書き終 わったら、それをコンパイルしなければなりません。このプロセスは GNU gettext ツー ルキットに依存しています。 これが済めば Django は、ユーザの言語設定に従い、利用可能な言語へのアプリケーシ ョン翻訳をオンザフライで行えるようになります。 Django の国際化フックはデフォルトで有効になっています。これは、フレームワークの 特定の箇所で小さなオーバーヘッドが存在することを意味します。もし国際化を使わな いなら、 :setting:`USE_I18N = False ` を設定ファイルに記述してくださ い。そうすれば Django は国際化機構を読み込まないようにして多少の最適化をします。 ``'django.core.context_processors.i18n'`` を :setting:`TEMPLATE_CONTEXT_PROCESSORS` から取り除くのも効果があります。 .. note:: 関連する設定として、 Django が書式ローカライズをすべきかを制御する :setting:`USE_L10N` があります。 :doc:`/topics/i18n/formatting` を参照してください。 Python コードでの国際化 ======================= 標準的な翻訳 ------------ 翻訳対象文字列を関数 ``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 の翻訳文字列検 出ユーティリティ :djadmin:`django-admin.py makemessages` は これらの文字列を検出できないので注意しておきましょう。詳しくは後の :djadmin:`makemessages` の節で説明します。) ``_()`` や ``ugettext()`` に渡す文字列には、 Pyton の標準の名前付き補完構文 によるプレースホルダを使えます。例えば:: def my_view(request, m, d): output = _('Today is %(month)s %(day)s.') % {'month': m, 'day': d} return HttpResponse(output) このテクニックを使うと、言語ごとの翻訳でプレースホルダを並べ変えできるよう になり、例えば、英語の翻訳文が ``"Today is Nobember, 26."`` であるのに対し て、スペイン語では ``"Hoy es 26 de Noviembre."`` であるように、プレースホル ダの位置を翻訳文の前後で移動できます。 この理由から、引数が複数ある場合には、固定引数を使った補完 (``%s`` や ``%d``) ではなく、名前付きの補完 (``%(day)s``) を使ってください。固定引数 による補完を使った場合、プレースホルダの順番によってうまく翻訳できない場合 があります。 .. _translator-comments: 翻訳者へのコメント ------------------ .. versionadded:: 1.3 翻訳可能文字列について翻訳者にヒントを与えたい場合は、 ``Translators`` キ ーワードで始まるコメントを、翻訳可能文字列の直前の行に置きます:: def my_view(request): # Translators: This message appears on the home page only output = ugettext("Welcome to my site.") テンプレートでは :ttag:`comment` タグで同じことができます: .. code-block:: html+django {% comment %}Translators: This is a text of the base template {% endcomment %} コメントは ``.po`` ファイルの中に入り、ほとんどの翻訳ツールで表示できます。 すぐには翻訳しない文字列をマークする ------------------------------------ すぐには翻訳しない文字列のマークには ``django.utils.translation.ugettext_noop()`` を使って下さい。マークした文字 列は後で変数として使われるときに翻訳されます。 この関数は、ソース言語の中に定数として文字列を置いておきたい場合に使います。 というのも、定数は、例えばデータベース中の文字列のように、システムやユーザ 間で共通な値である一方で、ユーザにメッセージとして提示する最後の段階で翻訳 せねばならない場合があるからです。 複数形化 -------- 複数形のメッセージを指定するには :func:`django.utils.translation.ungettext()` を使います。 ``ungettext`` は 単数形の翻訳文字列、複数形の翻訳文字列、オブジェクトの数 の 3 つの引数を取ります。 この関数は、 `複数形 `_ の形式が英語よりも多くて複雑な言語へアプリケーションをローカライズする時に使えます。 例えば:: 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) この例ではオブジェクトの数が ``count`` 変数として翻訳文字列に渡されます。 もうちょっと複雑な使用例を見てみましょう:: from django.utils.translation import ungettext count = Report.objects.count() if count == 1: name = Report._meta.verbose_name else: name = Report._meta.verbose_name_plural text = ungettext( 'There is %(count)d %(name)s available.', 'There are %(count)d %(name)s available.', count ) % { 'count': count, 'name': name } この例では、文の中の別の部分のために、ローカライズ可能で、うまくすれば既に翻訳 済みのリテラルを再利用しています。 (モデル ``Meta`` の ``verbose_name`` と ``verbose_name_plural`` オプションに含まれています) そのため全体が要素のカーディナリティ (cardinality) をもとに一貫したものになりま す。 .. _pluralization-var-notes: .. note:: このテクニックを使う場合、全ての推定の変数に単数形を使うようにしてください。 上の例では Python 変数の ``name`` が両方の翻訳文字列で使われていたことに注 意してください。次の例はうまく行きません:: from django.utils.translation import ungettext from myapp.models import Report count = Report.objects.count() d = { 'count': count, 'name': Report._meta.verbose_name, 'plural_name': Report._meta.verbose_name_plural } text = ungettext( 'There is %(count)d %(name)s available.', 'There are %(count)d %(plural_name)s available.', count ) % d :djadmin:`django-admin.py compilemessages `: を実行すると エラーが出ます:: a format specification for argument 'name', as in 'msgstr[0]', doesn't exist in 'msgid' .. _contextual-markers: コンステキストマーカー ---------------------- .. versionadded:: 1.3 英語の ``"May"`` が月の名前と動詞を指すように、単語が複数の意味を持つことがあ ります。このような単語を翻訳者が異なる文脈で正しく翻訳できるようにするには、 :func:`django.utils.translation.pgettext()` 関数、または複数形が必要な場合は :func:`django.utils.translation.npgettext()` 関数を使えます。いずれも、最初の 変数に文脈文字列 (context string) を取ります。 ``.po`` ファイルでは、この文字列は同じ文字列に対する別々のコンテキストマーカ ーとして現れるので、翻訳者はそれぞれに対して別の訳を当てることができます。 例えば:: from django.utils.translation import pgettext month = pgettext("month name", "May") もしくは:: from django.utils.translation import pgettext_lazy class MyThing(models.Model): name = models.CharField(help_text=pgettext_lazy( 'help text for MyThing model', 'This is the help text')) これらは ``.po`` ファイルでは、このように見えます:: .. code-block:: po msgctxt "month name" msgid "May" msgstr "" .. versionadded:: 1.4 :ttag:`trans` および :ttag:`blocktrans` テンプレートタグはコンテキストマーカー をサポートするようになりました。 .. _lazy-translations: 翻訳を遅延させる ---------------- 文字列の翻訳を遅延させる -- 値が呼び出された時ではなく、アクセスされた時に翻訳 するには、 :mod:`django.utils.translation` モジュールで遅延バージョンの翻訳関 数を使ってください。 (名前の末尾に ``lazy`` がついているのですぐに見分けられま す) これらの関数は、実際の翻訳結果ではなく、文字列への遅延参照を保存します。翻訳 自体は、文字列がテンプレートのレンダリングなど文字列コンテキストで使われた時 に行われます。 これが重要なのは、モジュールのロード時にコードパスにこれらの関数の呼び出しが配 置されるような時です。 これはモデル、フォーム、モデルフォームを定義する時に容易に起こりえます。 Django はこれらのフィールドをクラスレベル属性として実装しているからです。この 理由により、そのような場合は遅延翻訳を使っているか確認してください。 モデルフィールドとリレーションでの ``verbose_name`` と ``help_text`` ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 例えば次のモデルで *name* フィールドのヘルプテキストを翻訳するには、以下のよう にします:: from django.utils.translation import ugettext_lazy class MyThing(models.Model): name = models.CharField(help_text=ugettext_lazy('This is the help text')) ``verbose_name`` オプションによって、 ``ForeignKey`` や ``ManyTomanyField`` 、 ``OneToOneField`` の名前をマークすることができます:: from django.utils.translation import ugettext_lazy as _ class MyThing(models.Model): kind = models.ForeignKey(ThingKind, related_name='kinds', verbose_name=_('kind')) :attr:`~django.db.models.Options.verbose_name` でするように、小文字の名前を渡す 必要があります。 Django はそれを必要な時に自動でタイトルケースにします。 モデルの verbose name の値 ~~~~~~~~~~~~~~~~~~~~~~~~~~ :attr:`~django.db.models.Options.verbose_name` と :attr:`~django.db.models.Options.verbose_name_plural` オプションを明示的に指 定することをお勧めします。 モデルのクラス名を見て Django が行う決定は、英語中心でナイーブなフォールバック だからです:: from django.utils.translation import ugettext_lazy class MyThing(models.Model): name = models.CharField(_('name'), help_text=ugettext_lazy('This is the help text')) class Meta: verbose_name = ugettext_lazy('my thing') verbose_name_plural = ugettext_lazy('my things') モデルメソッドの ``short_description`` 属性 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ モデルメソッドに対して ``short_description`` 属性を使って Django と admin サイ トに翻訳を教えることができます:: from django.utils.translation import ugettext_lazy as _ class MyThing(models.Model): kind = models.ForeignKey(ThingKind, related_name='kinds', verbose_name=_('kind')) def is_mouse(self): return self.kind.type == MOUSE_TYPE is_mouse.short_description = _('Is it a mouse?') 遅延翻訳オブジェクトの動作 -------------------------- ``ugettext_lazy()`` の結果はユニコード文字列 ( ``unicode`` 型のオブジェクト) を使う場所ならどこでも使えます。バイト文字列 ( ``str`` オブジェクト) が期待さ れる場所で使うとうまく動きません。通常のPythonの動作と密接にむすびいているた め、バイト文字列の中でユニコード文字列を使うこともできません。例えば:: # This is fine: putting a unicode proxy into a unicode string. u"Hello %s" % ugettext_lazy("people") # This will not work, since you cannot insert a unicode object # into a bytestring (nor can you insert our unicode proxy there) "Hello %s" % ugettext_lazy("people") ``"hello"`` のように出力されるなら、 そのコードにはバグがあります。``ugettext_lazy()`` の結果をバイト文字列に挿入 しようとしているのでしょう。 長い ``ugettext_lazy`` の名前が好きじゃないなら、このように ``_`` (アンダース コア) をエイリアスとして使うことができます:: from django.utils.translation import ugettext_lazy as _ class MyThing(models.Model): name = models.CharField(help_text=_('This is the help text')) ``ugettext_lazy()`` と ``ungettext_lazy()`` をモデルやユーティリティ関数の中 の文字列をマークするのに使うことは、一般的な操作です。コードの中でこれらのオ ブジェクトを使う時は、偶然に文字列に変換されてしまわないか確認するべきです。 できるだけ遅く変換されるべきだからです。これは次に説明するヘルパー関数の使用 を伴います。 文字列の連結: string_concat() ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Python標準の文字列連結 (``''.join([...])``) は遅延翻訳オブジェクトを含むリスト に対してはうまく動きません。代わりに :func:`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`` 自体が文字列の中で使われた 時 (通常はテンプレートのレンダリング時) にだけ文字列変換されます。 言語のローカル名 ---------------- .. function:: get_language_info .. versionadded:: 1.3 ``get_language_info()`` 関数は言語についての詳細な情報を返します:: >>> from django.utils.translation import get_language_info >>> li = get_language_info('de') >>> print li['name'], li['name_local'], li['bidi'] German Deutsch False 辞書の ``name`` および ``name_local`` 属性は、それぞれ、英語での言語名と、その 言語自体での言語名を含みます。 ``bidi`` 属性は両方向 (bi-directional) な言語の 時だけ True になります。 言語情報のソースは ``django.conf.locale`` モジュールです。この情報へのアクセス はテンプレートコードからも可能です。下記を参照してください。 .. _specifying-translation-strings-in-template-code: テンプレート内での翻訳 ====================== .. highlightlang:: html+django :doc:`Django テンプレート ` 中の翻訳は、二つのテンプレー トタグを使ってPython コードとは少し違った方法で行います。テンプレートで翻訳 用のタグを使えるようにするには、テンプレートの上の方に ``{% load i18n %}`` を入れておきます。 .. templatetag:: trans テンプレートタグ ``{% trans %}`` --------------------------------- テンプレートタグ ``{% trans %}`` は定数の文字列 (シングルクオートまたはダブ ルクオートで囲まれた文字列) や変数を翻訳します:: {% trans "This is the title." %} {% trans myvar %} ``noop`` オプションを指定すると、値の参照は行われますが、翻訳はしません。 ``noop`` は、将来翻訳が必要なコンテンツを「スタブ」するのに便利です:: {% trans "myvar" noop %} 内部的には、インラインの翻訳は :func:`~django.utils.translation.ugettext` を呼び出します。 ``{% trans %}`` の中では定数文字列とテンプレート変数を同時に扱えません。翻 訳中で変数 (プレースホルダ) を使いたい場合には、``{% blocktrans %}`` を使 います。 .. versionadded:: 1.4 表示せずに翻訳文字列を検索したい場合、次の文法を使ってください:: {% trans "This is the title" as the_title %} {{ the_title }} 実用上は、複数の場所で使われたり、他のテンプレートタグやフィルタで使われる 文字列を得るために使うことができます:: {% trans "starting point" as start %} {% trans "end point" as end %} {% trans "La Grande Boucle" as race %}

{{ race }}

{% for stage in tour_stages %} {% cycle start end %}: {{ stage }}{% if forloop.counter|divisibleby:2 %}
{% else %}, {% endif %} {% endfor %}

.. versionadded:: 1.4 ``{% trans %}`` は ``context`` キーワードを使って :ref:`コンテキストマーカー` もサポートします: .. code-block:: html+django {% trans "May" context "month name" %} .. templatetag:: blocktrans ``blocktrans`` テンプレートタグ ------------------------------- .. versionchanged:: 1.3 キーワード引数フォーマットが新しくなりました。 :ttag:`trans` タグと反対に、 ``blocktrans`` タグはプレースホルダを使用する ことによってリテラルと変数を含む複雑な文章を扱えます:: {% blocktrans %}This string will have {{ value }} inside.{% endblocktrans %} オブジェクト属性へのアクセスや、テンプレートフィルタの使用などのテンプレート式 を翻訳するには、翻訳ブロックの中でその表現をローカル変数にバインドする必要があ ります。例:: {% blocktrans with amount=article.price %} That will cost $ {{ amount }}. {% endblocktrans %} {% blocktrans with myvar=value|filter %} This will have {{ myvar }} inside. {% endblocktrans %} 一つの ``blocktrans`` タグの中で複数の表現を使うことができます:: {% blocktrans with book_t=book|title author_t=author|title %} This is {{ book_t }} by {{ author_t }} {% endblocktrans %} .. note:: 以前のもっと冗長なフォーマットもまだサポートされています: ``{% blocktrans with book|title as book_t and author|title as author_t %}`` .. versionchanged:: 1.4 プロック引数のどれかが解決に失敗した場合、 blocktrans は :func:`~django.utils.translation.deactivate_all` を使って一時的に現在 有効な言語を無効化し、デフォルト言語にフォールバックします。 このタグは複数形も扱えます: * ``count`` という名前でカウンタの値を定義し、バインドします。この値は 適切な複数形の形式を選択するために使われます。 * ``{% blocktrans %}`` と ``{% endblocktrans %}`` タグの中で、単数形と 複数形の両方の形式を ``{% plural %}`` タグで区切って指定します。 例:: {% blocktrans count counter=list|length %} There is only one {{ name }} object. {% plural %} There are {{ counter }} {{ name }} objects. {% endblocktrans %} もう少し複雑な例:: {% blocktrans with amount=article.price count years=i.length %} That will cost $ {{ amount }} per year. {% plural %} That will cost $ {{ amount }} per {{ years }} years. {% endblocktrans %} カウンタ値に加えて、複数形とローカル変数への値バインドを両方使いたいなら、 ``blocktrans`` は内部的に ``ungettext`` の呼び出しに変換されるということを心に 留めてください。これは :ref:`notes regarding ungettext variables ` の適用と同じことを意味します。 リバース URL 参照は ``blocktrans`` の中で実行することはできないので、前もって検 索されて (保存されて) おかなければなりません:: {% url path.to.view arg arg2 as the_url %} {% blocktrans %} This is a URL: {{ the_url }} {% endblocktrans %} .. versionadded:: 1.4 ``{% blocktrans %}`` は ``context`` キーワードを使った :ref:`コンテキストマーカー` もサポートします: .. code-block:: html+django {% blocktrans with name=user.username context "greeting" %}Hi {{ name }}{% endblocktrans %} .. _template-translation-vars: その他のタグ ------------ ``Requestcontext`` は 3 つの翻訳処理用の変数にアクセスします: * ``LANGUAGES`` はタプルのリストです。最初の要素は :term:`language code` で、二番目は (現在アクティブなロケール に翻訳された) 言語名です。 * ``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"`` に翻訳せねばなりません。 .. versionadded:: 1.3 提供されるテンプレートタグとフィルタを使って利用可能な言語のいずれかについ ての情報を検索することもできます。単一の言語の情報を得るには ``{% get_language_info %}`` タグを使います:: {% get_language_info for LANGUAGE_CODE as lang %} {% get_language_info for "pl" as lang %} そのあとで情報にアクセスできます:: Language code: {{ lang.code }}
Name of language: {{ lang.name_local }}
Name in English: {{ lang.name }}
Bi-directional: {{ lang.bidi }} 言語のリストについての情報を検索するなら ``{% get_language_info_list %}`` テンプレートタグも使えます。 (例えば ::setting:`LANGUAGE` で指定されたアク ティブな言語についてなど) ``{% get_language_info_list %}`` を使った言語セ レクタを表示する例を見たいなら、 :ref:`set_language リダイレクトビューにつ いてのセクション ` を参照してください。 :setting:`LANGUAGES` のネストしたタプル形式に加えて、 ``{% get_language_info_list %}`` は言語コードの単純なリストもサポートして います。ビューの中で使うなら: .. code-block:: python return render_to_response('mytemplate.html', { 'available_languages': ['en', 'es', 'fr'], }, RequestContext(request)) テンプレートの中でこれらの言語をイテレートできます:: {% get_language_info_list for available_languages as langs %} {% for lang in langs %} ... {% endfor %} 簡単にするため、シンプルなフィルタもあります: * ``{{ LANGUAGE_CODE|language_name }}`` ("German") * ``{{ LANGUAGE_CODE|language_name_local }}`` ("Deutsch") * ``{{ LANGUAGE_CODE|bidi }}`` (False) .. _Django templates: ../templates_python/ JavaScript コードでの国際化 =========================== .. highlightlang:: python JavaScript に翻訳を追加しようとすると、いくつかの問題に直面します: * JavaScript コードには ``gettext`` 実装へのアクセス手段がありません。 * JavaScript コードには .po や .mo ファイルへのアクセス手段がありません。 というのも、これらのファイルはサーバに置かれているからです。 * JavaScript の翻訳カタログはできるだけ小さくしておかねばなりません。 Django では、これらの問題に対する解決策を組み込みで提供しています。この解決 策は翻訳を JavaScript に渡して、 ``gettext`` などを JavaScript コード内で呼 び出せるようにします。 .. _javascript_catalog-view: ``javascript_catalog`` ビュー ------------------------------- .. module:: django.views.i18n .. function:: javascript_catalog(request, domain='djangojs', packages=None) 前述の問題に対する解決策は、 :meth:`django.views.i18n.javascript_catalog`` ビューにあります。このビューは ``gettext`` インタフェースをまねた関数の入っ た JavaScript コードと、翻訳文字列のアレイを送信します。翻訳文字列のアレイは ``info_dict`` や URLの指定に従ってアプリケーションやプロジェクト、Django コ ア部分から取り出されます。 :setting:`LOCALE_PATHS` のパスリストも含まれます。 例えば以下のようにフックをかけたとしましょう:: 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 で便利です。 翻訳の優先度は、 ``packages`` 引数で後に現れるパッケージが、最初に現れるもの よりも高くなります。同じリテラルで翻訳が壊れる場合、このことが情報です。 このビューはデフォルトでは ``djangojs`` gettext ドメインを使います。代わりの ``domain`` 引数によって変更できます。 URL パターンにパッケージ名を入れておけば、ビューを動的にできます:: urlpatterns = patterns('', (r'^jsi18n/(?P\S+?)/$', 'django.views.i18n.javascript_catalog'), ) こうしておいて、パッケージ名を '+' で区切ったパッケージ名リストとして指定で きます。これは、複数のアプリケーションからのコードを使っていて、変更が頻繁 に起きている場合、巨大なカタログファイルを毎回プルしなくてすむので便利です。 セキュリティ上の理由から、パッケージ名リストに指定できるのは、 ``django.conf`` か ``INSTALLED_APPS`` 設定に入っているアプリケーションだけ です。 :setting:`LOCALE_PATHS` 設定のパスリストで見つけられる JavaScript 翻訳は常に 含められます。 Python とテンプレートで使われる翻訳の検索順序アルゴリズムの一 貫性を保つため、 :setting:`LOCALE_PATHS` のディレクトリリストは、最初に現れ るものとともに、最も高い優先度を持ちます。 .. versionchanged:: 1.3 :setting:`LOCALE_PATHS` のディレクトリリストはバージョン 1.3 までは 検索アルゴリズムに含まれていませんでした。 JavaScript 翻訳カタログを使う ----------------------------- .. highlightlang:: javascript カタログを使うには、単に以下のようにして動的に生成されたスクリプトをプルし ます:: .. code-block:: html+django このコードはJavaScript カタログビューのURLを探すために、リバース URL 参照を使っ ています。カタログをロードしたら、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); 補完の構文は 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`` を使って適切な複数形表現を実現したい場合) だけにしてください。 .. _url-internationalization: URL パターンでの国際化 ====================== .. versionadded:: 1.4 .. module:: django.conf.urls.i18n Django は URL パターンでの国際化のために 2 つのメカニズムを提供しています: * :class:`~django.middleware.locale.LocaleMiddleware` がリクエスト URL からアク アクティブな言語を判別できるように、 ルート URL パターンに言語プレフィックス をつけます。 * URL パターン自体を :func:`django.utils.translation.ugettext_lazy()` 関数を通 して翻訳できるようにします。 .. warning:: これらの機能のいずれかを使うには、各々のリクエストに対してアクティブな言語 がセットされる必要があります。言い換えると :setting:`MIDDLEWARE_CLASSES` 設定に :class:`django.middleware.locale.LocaleMiddleware` を含める必要があります。 URL パターンの言語プレフィックス -------------------------------- .. function:: i18n_patterns(prefix, pattern_description, ...) この関数はルート URLconf で、通常の :func:`django.conf.urls.patterns` 関数の代わりに使うことができます。Django は :func:`~django.conf.urls.i18n.i18n_patterns` で定義された全ての URL バターンの 先頭に自動で現在アクティブな言語コードを挿入します。例の URL パターン:: from django.conf.urls import patterns, include, url from django.conf.urls.i18n import i18n_patterns urlpatterns = patterns('' url(r'^sitemap\.xml$', 'sitemap.view', name='sitemap_xml'), ) news_patterns = patterns('' url(r'^$', 'news.views.index', name='index'), url(r'^category/(?P[\w-]+)/$', 'news.views.category', name='category'), url(r'^(?P[\w-]+)/$', 'news.views.details', name='detail'), ) urlpatterns += i18n_patterns('', url(r'^about/$', 'about.view', name='about'), url(r'^news/$', include(news_patterns, namespace='news')), ) このように URL バターンが定義されたら、 Django は URL パターンに対して ``i18n_patterns`` 関数により言語プレフィックスを追加します。 from django.core.urlresolvers import reverse from django.utils.translation import activate >>> activate('en') >>> reverse('sitemap_xml') '/sitemap.xml' >>> reverse('news:index') '/en/news/' >>> activate('nl') >>> reverse('news:detail', kwargs={'slug': 'news-slug'}) '/nl/news/news-slug/' .. warning:: :func:`~django.conf.urls.i18n.i18n_patterns` はルートの URLconf でしか使え ません。インクルードされた URLconf の中で使うと、 :exc:`ImproperlyConfigured` 例外を送出します。 .. warning:: 自動で追加された言語プレフィックスと衝突しないように、プレフィックスのない URL パターンがないことを確認してください。 URL パターンを翻訳する ---------------------- URL パターンは :func:`~django.utils.translation.ugettext_lazy` 関数を使って翻訳 可能としてマークすることができます。例えば:: from django.conf.urls import patterns, include, url from django.conf.urls.i18n import i18n_patterns from django.utils.translation import ugettext_lazy as _ urlpatterns = patterns('' url(r'^sitemap\.xml$', 'sitemap.view', name='sitemap_xml'), ) news_patterns = patterns('' url(r'^$', 'news.views.index', name='index'), url(_(r'^category/(?P[\w-]+)/$'), 'news.views.category', name='category'), url(r'^(?P[\w-]+)/$', 'news.views.details', name='detail'), ) urlpatterns += i18n_patterns('', url(_(r'^about/$'), 'about.view', name='about'), url(_(r'^news/$'), include(news_patterns, namespace='news')), ) 翻訳を作成した後には :func:`~django.core.urlresolvers.reverse` 関数はアクティブ な言語でのURLを返します。例えば:: from django.core.urlresolvers import reverse from django.utils.translation import activate >>> activate('en') >>> reverse('news:category', kwargs={'slug': 'recent'}) '/en/news/category/recent/' >>> activate('nl') >>> reverse('news:category', kwargs={'slug': 'recent'}) '/nl/nieuws/categorie/recent/' .. warning:: ほとんどの場合、 URL の翻訳は ( :func:`~django.conf.urls.i18n.i18n_patterns` を使った) 言語コードプレフィッ クスの箇所でのみ使うのがベストです。不注意な URL の翻訳が、翻訳されない URL との衝突を起こすことを避けるためです。 .. _reversing_in_templates: .. templatetag:: language テンプレートでのリバース参照 ---------------------------- ローカライズされた URL がテンプレート中でリバース参照される場合、常に現在の言語 が使われます。他の言語の URL にリンクするには、 ``language`` テンプレートタグを 使ってください。これはタグに囲まれたセクションで与えられた言語を有効にします: .. code-block:: html+django {% load i18n %} {% get_available_languages as languages %} {% trans "View this category in:" %} {% for lang_code, lang_name in languages %} {% language lang_code %} {{ lang_name }} {% endlanguage %} {% endfor %} :ttag:`language` タグは引数に言語コードだけが渡されることを期待します。 .. _how-to-create-language-files: ローカライズ: 言語ファイルの作成方法 ==================================== 文字列に翻訳用のタグをつけたら、今度は翻訳文自体を書く (または手に入れる) 必要があります。ここでは翻訳文を書く方法について示します。 .. _locale-restrictions: .. admonition:: ロケールの制約 Django は、 Django 本体に対する翻訳カタログのない言語への地域化をサポー トしていません。ある言語向けの自作のカタログを提供しても、 Django 本体 にその言語のサポートがなければ、カタログは無視されます。自作のアプリケー ションに特定の言語のロケールをサポートさせたいのなら、まずは Django の コア部分に対する最小限の翻訳カタログを作成する必要があるでしょう。また、 その場合、翻訳されたメッセージ (自作のアプリケーション内のカタログ) と 英語のメッセージ (Django 自体の不完全なカタログ) が入り混じった表示になっ てしまうでしょう。 Django の英語 ``.po`` ファイルをコピーし、少なくともいくつかの :term:`翻訳 文字列 ` を翻訳することから始めると良いでしょう。 メッセージファイル ------------------ 最初のステップは、新たに追加する言語用の :term:`メッセージファイル` の作成です。 メッセージファイルは平文テキストファイルで、言語ごとに作成され、翻訳文字列 全てと、言語ごとの対応する表現が収められています。メッセージファイルの拡張 子は ``.po`` です。 Django には :djadmin:`django-admin.py makemessages` というツール が付属しています。このツールはメッセージファイルの作成や維持を自動化します。 .. admonition:: Gettext ユーティリティ ``makemessages`` コマンド (および後で議論する ``compilemessages``) は GNU gettext ツールセットのコマンド: ``xgettext``, ``msgfmt``, ``msgmerge``, ``msguniq`` を使います。 .. versionchanged:: 1.2 対応している ``gettext`` の最低バージョンは 0.15 です。 メッセージファイルの作成や更新を行うには、以下のようにコマンドを実行します:: django-admin.py makemessages -l de ここで、 ``de`` は作成したいメッセージファイルの言語コードです。言語コードは :term:`ロケール表示の形式` にします。例えば、ブラジル系ポルトガル 語の場合には ``pt_BR`` で、オーストリアドイツは ``de_AT`` です。 スクリプトは以下の 2 種類の場所のいずれかで実行します: * Django プロジェクトのルートディレクトリ。 * Django アプリケーションのルートディレクトリ。 スクリプトはプロジェクトのソースツリーやアプリケーションのソースツリーを走 査して、翻訳用にマークされた全ての文字列を取り出します。スクリプトは ``/locale/LANG/LC_MESSAGES`` 下にメッセージファイルを作成 (もしくは更新) し ます。 ``de`` の例では、ファイルは ``/locale/de/LC_MESSAGES/django.po`` で す。 デフォルトの設定では、 :djadmin:`django-admin.py makemessages` は拡張子 `.html` や `.txt` のファイルも検索します。デフォルトの設定をオーバライドしたけ れば、 ``--extension`` または ``-e`` オプションを使って、拡張子を指定してくださ い:: django-admin.py makemessages -l de -e txt 複数の拡張子を扱いたいのなら、カンマで区切るか、 ``-e`` や ``--extension`` を複数回指定します:: django-admin.py makemessages -l de -e html,txt -e xml .. warning:: :ref:`JavaScriptソースコードからメッセージファイルを作成する ` 場合は、 ``-e js`` **ではなく** 特別な 'djangojs' ドメインを使わなければなりません。 .. admonition:: gettext がなかったら? ``gettext`` ユーティリティをインストールしていない場合、 :djadmin:`makemessages` は空のファイルを作成します。その場合、 ``gettext`` ユーティリティをインストールするか、英語用の空のメッセージファイル ( ``locale/en/LC_MESSAGES/django.po``) をコピーして使って下さい。 .. admonition:: Windows で動かしたいのですが? Windows を使っていて、 :djadmin:`makemessages` を動作させるため に GNU gettext ユーティリティをインストールしたいのなら、 :ref:`gettext_on_windows` を参照してください。 ``.po`` ファイルは素直な形式で書かれています。 ``.po`` ファイルには翻訳メン テナのコンタクト情報のようなわずかなメタデータが入っています。それ以外の大 部分は **メッセージ** のリストです。メッセージは翻訳文字列と特定の言語用の 実際の翻訳テキストです。 例えば、 Django アプリケーションに ``"Welcome to my site."`` というテキスト の翻訳文字列が以下のように入っていたとします:: _("Welcome to my site.") :djadmin:`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 が PO ファイルを処理する時に大切なことです。 全てのソースコードとテンプレートを新たな翻訳文字列でためし、 **全ての** 言 語用にメッセージファイルを更新するには、以下のようにします:: django-admin.py makemessages -a メッセージファイルのコンパイル ------------------------------ メッセージファイルを作成して、変更し終えたら ``gettext`` を使ってメッセージ ファイルをより効率的な形式にコンパイルします。作業は :djadmin:`django-admin.py compilemessages` ユーティリティで行 いましょう。 このツールは全ての ``.po`` ファイルをコンパイルして ``.mo`` ファイルを作成 します。 ``.mo`` ファイルはバイナリファイルで、 ``gettext`` で使うために最 適化されています。 :djadmin:`django-admin.py makemessages ` を実 行したのと同じディレクトリで、以下のように :djadmin:`django-admin.py compilemessages ` を実行してくだ さい:: django-admin.py compilemessages これで終わりです。もう翻訳を使えるようになっているはずです。 .. admonition:: Windows で動かしたいのですが? Windows を使っていて、 :djadmin:`django-admin.py compilemessages ` を動作させるた めに GNU gettext ユーティリティをインストールたいのなら、 :ref:`gettext_on_windows` を参照してください。 .. admonition:: .po ファイルのエンコーディングと BOM Django は BOM (バイトオーダーマーク) なしで UTF-8 でエンコードされたファイル しか扱えません。使っているテキストエディタがデフォルトでファイルの先頭に BOM を追加する場合、設定を変更してください。 .. _creating-message-files-from-js-code: JavaScript のソースコードからメッセージファイルを作成する --------------------------------------------------------- JavaScript のメッセージファイルの作成と更新方法は、他の Django の翻訳カタログの 場合と同じで、 :djadmin:`django-admin.py makemessages` ツールを使います。唯一違 うのは、 gettext の用語でドメインとして知られているもの、この場合は ``djangojs`` ドメインを明示的に指定しなければならないことです。このように ``-d djangojs`` パ ラメタを指定してください:: django-admin.py makemessages -d djangojs -l de 上の例では、ドイツ語向けの JavaScript のメッセージファイルを作成または更新して います。翻訳カタログを更新したら、通常の Django メッセージファイルと同じように、 :djadmin:`django-admin.py compilemessages ` を実行してください。 .. _gettext_on_windows: Windows で ``gettext`` を使う ----------------------------- この節の操作が必要なのは、 メッセージ ID を抜き出したり、メッセージファイル を (``.po`` に) コンパイルしたいときだけです。翻訳の作業自体はファイルを編 集するだけですが、メッセージファイルを自分で作成したい場合や、変更したメッ セージファイルをテストしたりコンパイルしたい場合には、以下のようにして ``gettext`` ユーティリティを入れる必要があります: * 以下の ZIP ファイルを GNOME のサーバ、 http://ftp.gnome.org/pub/gnome/binaries/win32/dependencies/ や ミラーサイト_ からダウンロードします。 * ``gettext-runtime-X.zip`` * ``gettext-tools-X.zip`` ``X`` はバージョン番号で、 ``0.15`` 以上が必要です。 * 両方のファイルの ``bin\`` ディレクトリの中身をどこかのフォルダに展開します ( 仮に ``C:\Program Files\gettext-utils`` とします) * システム環境変数の PATH を変更します: * ``コントロールパネル > システム > 高度な設定 > 環境変数`` の順に辿 ります。 * ``システム環境変数`` リストで、 ``Path`` を選び、 ``編集`` を押しま す。 * ``変数値`` フィールドの値の末尾に ``;C:\Program Files\gettext-utils\bin`` を追加します。 .. _ミラーサイト: http://ftp.gnome.org/pub/GNOME/MIRRORS ``xgettext --version`` コマンドの結果が 0.15 以上なら、別の場所で入手した ``gettext`` バイナリを使ってもかまいません。 もし Windows のコマンドプロンプト で ``xgettext --version`` を入力した時に "xgettext.exe でエラーが発生しました。" といったポップアップウィンドウが表示されるなら、Django の翻訳ユーティリティに その ``gettext`` パッケージを使わないようにしてください。 雑多な情報 ========== .. _set_language-redirect-view: ``set_language`` リダイレクトビュー ----------------------------------- .. highlightlang:: python .. function:: set_language(request) Django は便利な :func:`django.views.i18n.set_language` ビューを提供しています。 これはユーザの言語を設定し、与えられた URL かデフォルトでは 直前のページに戻る ビューです。 URLconf に次の行を足すとこのビューを有効にできます:: (r'^i18n/', include('django.conf.urls.i18n')), (この例は ``/i18n/setlang/`` にビューを作っています。) このビューは ``language`` パラメータつきで ``POST`` メソッドのリクエストによっ て呼ばれることを想定しています。セッションサポートが有効になっていると選択され た言語がユーザのセッションに保存されます。無効の場合は、 ``django_language`` という名前のクッキーに言語設定を保存します。 (この名前は :setting:`LANGUAGE_COOKIE_NAME` 設定で変更できます。) 選ばれた言語を設定したら、 Django はユーザを以下のアルゴリズムでリダイレクトし ます: * Django は ``POST`` データの ``next`` パラメータを探します。 * なかったり空の場合、 Django は ``Referrer`` ヘッダの URL を使おうとします。 * これも空なら、つまりユーザのブラウザが ``Referrer`` ヘッダを抑制している場合 ユーザは ``/`` (サイトのルート) にリダイレクトされます。 次に示すのは簡単な HTML テンプレートコードです: .. code-block:: html+django
{% csrf_token %}
この例では Django は ``redirect_to`` コンテキスト変数からユーザがリダイレクトさ れるページの URL を見つけます。 ビューやテンプレートの外で翻訳を使う ------------------------------------ Django はビューとテンプレートで使うために豊富な国際化ツールセットを提供していま す。 Django 専用のコード以外でもこれを使うことはできます。 Django の翻訳メカニ ズムは任意のテキストを Django がサポートする言語に翻訳するために使うことができ ます (もちろん適切な翻訳カタログがあればですが) 。翻訳カタログをロードし、アク ティベートして、選択した言語にテキストを翻訳することができますが、元の言語に戻 すのを忘れないでください。翻訳カタログのアクティベートはスレッド単位で行われ、 同じスレッドで動くコードに影響するからです。 例えば:: from django.utils import translation def welcome_translated(language): cur_language = translation.get_language() try: translation.activate(language) text = translation.ugettext('welcome') finally: translation.activate(cur_language) return text 'de' という値を渡してこの関数を呼ぶと :setting:`LANGUAGE_CODE` やミドルウェアに よる言語設定に関わらず ``"Willkommen"`` が返されます。 特別な目的のための関数として ``django.utils.translation.get_language()`` は、 現在のスレッドで使われている言語を返します。 ``django.utils.translation.activate()`` は現在のスレッドで翻訳カタログをアクテ ィベートします。 ``django.utils.translation.check_for_language()`` は指定された 言語 が Django でサポートされているかを調べます。 実装に関する注意点 ================== .. _specialties-of-django-i18n: Django 翻訳の特徴 ----------------- Django の翻訳機構は Python 標準の ``gettext`` モジュールを使います。 ``gettext`` について詳しければ、 Django の翻訳機能には以下のような特徴があることに気づくで しょう: * 文字列ドメイン (string domain) は ``django`` または ``djangojs`` です。文字列 ドメインは別のプログラムが共通のメッセージファイルライブラリにデータを保存す る時に区別するために使われます。 ``django`` ドメインは Python とテンプレート の翻訳文字列に使われ、グローバルの翻訳カタログにロードされます。 ``djangojs`` ドメインは JavaScript の翻訳カタログができるだけ小さくなるように、それだけの ために使われます。 * Django は ``xgettext`` を単体では使いません。 ``xgettext`` や ``msgfmt`` を Python ラッパを通して使います。これは主に利便性のためです。 .. _how-django-discovers-language-preference: 言語設定の検出メカニズム ------------------------ 翻訳の準備を完了した、あるいは Django 付属の翻訳を使いたいだけなら、あとは アプリケーションで翻訳を有効にするだけです。 背後では、 Django はユーザの使用言語を決めるモデルを備えています。このモデ ルは柔軟で、インストール全体、あるいは特定のユーザ、またはその両方に対して 使用言語を決定できます。 インストール全体での使用言語を設定するには、 :setting:`LANGUAGE_CODE` を設 定します。 Django はこの設定をデフォルトの翻訳言語、すなわち他の適切な翻訳が ない場合に試みる言語に設定します。 Django をネイティブの言語で動かしたいだけで、かつ自分の言語に対する言語ファ イルをすでに準備しているのなら、 ``LANGUAGE_CODE`` を設定するだけで済みます。 個々のユーザが自分の使いたい言語を選択できるようにするには ``LocaleMiddleware`` を使ってください。 ``LocaleMiddleware`` は、リクエスト に埋め込まれたデータに基づいた言語の選択を可能にし、ユーザごとにコンテンツ をカスタマイズします。 ``LocaleMiddleware`` を使うには、 :setting:`MIDDLEWARE_CLASSES` 設定に ``'django.middleware.locale.LocaleMiddleware'`` を追加します。ミドルウェア の順番は重要で、以下のガイドラインに従って下さい: * まず、インストール済みのミドルウェアの先頭にくるようにしてください。 * ``LocaleMiddleware`` はセッションを使うので、 ``SessionMiddleware`` の後ろに配置してください。 また、``CommonMiddleware`` より前にしてください。 ``CommonMiddleware`` はリクエスト URL を解決するためアクティブな言語を必要と します。 * ``CacheMiddleware`` を使っているなら、その後ろに ``LocaleMiddleware`` を配置してください。 例えば、 ``MIDDLEWARE_CLASSES`` は以下のようになります:: MIDDLEWARE_CLASSES = ( 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.locale.LocaleMiddleware', 'django.middleware.common.CommonMiddleware', ) (For more on middleware, see the :doc:`middleware documentation `.) (ミドルウェアの詳細は :doc:`ミドルウェアのドキュメント ` を参照してください。) ``LocaleMiddleware`` はユーザの言語設定を以下のようなアルゴリズムで決定しよ うと試みます: .. versionchanged:: 1.4 * はじめに、リクエストされた URL に言語プレフィックスを探します。これはルート URLconf で ``i18n_patterns`` 関数を使った場合だけ行われます。 言語プレフィックスと URL パターンの国際化については :ref:`url-internationalization` がもっと詳しいです。 * 見つからなければ、現在のユーザのセッションに ``django_language`` キーがない か探します。 * なければ、クッキーを探します。 クッキーの名前は :setting:`LANGUAGE_COOKIE_NAME` 設定の値がセットされます。 (デフォルトの名前は ``django_language`` です。) * うまく行かなければ、 ``Accept-Language`` HTTP ヘッダを見ます。このヘッダは ブラウザから送られ、ユーザの望む言語を優先度順に伝えます。 Django は利用可能 な翻訳が見つかるまで、渡された全ての言語を調べます。 * それも失敗したら、グローバルな :setting:`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`` 設定を行った場合、そ の言語を翻訳対象文字列に含めても構いません。ただし、 ``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 のソースツリーの翻訳セットに入って いない言語の翻訳を提供したければ、 :ref:`ロケールの制約` に説明されているように まずその言語むけの基本部分の翻訳を提供する必要があります。 ``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`_ .. _how-django-discovers-translations: Django が翻訳を探す方法 ----------------------- 実行時に、 Django はメモリ上に統合されたリテラル - 翻訳のカタログを作ります。 これを実現するために、次に示すアルゴリズムによって翻訳を探します。このアルゴリ ズムは、コンパイルされた :term:`メッセージファイル ` (``.mo``) を ロードするために複数のファイルパスを調べ、同じリテラルに対して複数の翻訳がある 時の優先度を調べます: 1. :setting:`LOCALE_PATHS` で設定されたディレクトリのリストが最も優先されます。 このなかでは前に書かれたものが後のものより優先されます。 2. 次に :setting:`INSTALLED_APPS` に列挙されたアプリケーションに ``local`` ディ レクトリがあれば、それを見つけて使います。後のものより先に書かれたものが優先 されます。 3. 次に、プロジェクトディレクトリ、もっと正確に言うと設定ファイルがあるディレク トリで ``locale`` ディレクトリを探します。 4. 最後に、フォールバックとして Django が提供する基本の ``djang/conf/locale`` を使います。 .. deprecated:: 1.3 設定ファイルがあるディレクトリから ``locale`` サブディレクトリを探す方法 ( 上の 3) は 1.3 から非推奨になっていて、 Django 1.5 では廃止されます。 代わりに :setting:`LOCALE_PATHS` 設定に ``locale`` のようなディレクトリの絶 対ファイルパスを書いてください。 .. seealso:: JavaScript ファイルに含まれるリテラルの翻訳文字列は、同様な、しかし特別に用 意されたアルゴリズムによって探します。 詳しくは :ref:`javascript_catalog ビューのドキュメント ` を 参照してください。 どの場合でも翻訳を含むディレクトリの名前は ``de``, ``pt_BR``, ``es_AR`` といっ た :term:`ロケール名` 表記にしなければなりません。 こうすることで、独自の翻訳の入ったアプリケーションを書いたり、基本の翻訳の 内容をプロジェクトパスに置いた翻訳でオーバライドしたりできます。また、複数 の小さなアプリケーションで大きめのプロジェクトを構築するときに、全ての翻訳 を一つのプロジェクト単位のメッセージファイルにまとめておけます。どういう方 法をとるかはユーザ次第です。 .. note:: :ref:`settings-without-django-settings-module` に示したように、 :setting:`DJANGO_SETTINGS_MODULE` を使わずに手動で設定を行った場合、プ ロジェクトディレクトリ内の ``locale`` ディレクトリはチェックされません。 これは Django がプロジェクトディレクトリの場所を調べる術を持たないから です (Django は通常、設定ファイルのある場所を基準に ``locale`` ディレク トリの場所を調べますが、手動で設定を行うと設定ファイルが存在しなくなっ てしまうからです)。 メッセージファイルリポジトリも同じような構成になっています: * 設定ファイルの :setting:`LOCALE_PATHS` に書かれた全てのパスから ``/LC_MESSAGES/django.(po|mo)`` を探します。 * ``$PROJECTPATH/locale//LC_MESSAGES/django.(po|mo)`` を探します。上記のように非推奨です。 * ``$APPPATH/locale//LC_MESSAGES/django.(po|mo)`` * ``$PYTHONPATH/django/conf/locale//LC_MESSAGES/django.(po|mo)`` メッセージファイルの作成には :djadmin:`django-admin.py makemessages ` を使ってください。 ``locale/`` ディレクトリがあるディレクトリで行わねばなりません。 また、 ``gettext`` が使うバイナリ形式の ``.mo`` ファイルを作成するには :djadmin:`django-admin.py compilemessages ` を使います。 ``django-admin.py compilemessages --settings=path.to.settings`` を実行すれ ば、コンパイラに ``LOCALE_PATHS`` に設定された全てのディレクトリを処理させ られます。 最後に、翻訳ファイルをどのように構成するかしっかりと考えておくように勧めま す。自分の作ったアプリケーションを他のユーザに配ったり、他のプロジェクトで 利用したりするなら、アプリケーション固有の翻訳が必要になるでしょう。しかし、 アプリケーション固有のメッセージやプロジェクトごとの翻訳は ``makemessages`` にまつわる困った問題を引き起こすことがあります: ``makemessages`` は現在のパス以下の全てのディレクトリを検索してしまうので、 すでにアプリケーションメッセージファイルに入っているメッセージ ID が、プロ ジェクトのメッセージファイルに入ってしまうことがあるのです。 この問題の最も簡単な解決法は、プロジェクトを直接的に構築しない (なおかつ独 自の翻訳を備えている) アプリケーションをプロジェクトツリーの外に配置してお くというものです。こうすれば、プロジェクトレベルで :djadmin:`django-admin.py make-messages ` を実行しても、自分 のプロジェクトに明に関係する部分の文字列だけを翻訳し、別個に配布されたアプ リケーションの文字列を対象にしなくなります。