翻訳

revision-up-to:17812 (1.4)

概要

Django プロジェクトを翻訳可能にするためには、 Python コードに最小限のフックを入 れなければなりません。このフックは 翻訳文字列 と呼ばれます。翻訳文字列は Django に「もしこのテキストがエンドユーザの言語に翻 訳可能であれば、翻訳すべきだ」ということを教えます。翻訳可能な文字列をマークす ることは開発者の責任です。システムは教えられた文字列だけを翻訳できます。

Django は翻訳文字列を メッセージファイル に抽出するユーティリティを提供 します。このファイルがあるため、翻訳者が対象の言語において翻訳文字列に対応する 文字列を用意することが簡単になります。翻訳者がメッセージファイルの中身を書き終 わったら、それをコンパイルしなければなりません。このプロセスは GNU gettext ツー ルキットに依存しています。

これが済めば Django は、ユーザの言語設定に従い、利用可能な言語へのアプリケーシ ョン翻訳をオンザフライで行えるようになります。

Django の国際化フックはデフォルトで有効になっています。これは、フレームワークの 特定の箇所で小さなオーバーヘッドが存在することを意味します。もし国際化を使わな いなら、 USE_I18N = False を設定ファイルに記述してくださ い。そうすれば Django は国際化機構を読み込まないようにして多少の最適化をします。 'django.core.context_processors.i18n'TEMPLATE_CONTEXT_PROCESSORS から取り除くのも効果があります。

Note

関連する設定として、 Django が書式ローカライズをすべきかを制御する USE_L10N があります。 書式ローカライズ を参照してください。

Python コードでの国際化

標準的な翻訳

翻訳対象文字列を関数 ugettext() で指定します。タイプ数を減らすため、 ugettext()_ という別名で import するのが慣習的なやり方です。

Note

Python の標準ライブラリ gettext は、グローバルの名前空間に _() とい う名前で gettext() をインストールします。 Django ではこの方法に 従って いませんが、それは以下の理由からです:

  1. 国際化文字セット (Unicode) のサポート下では、 gettext() よりも ugettext() の方が便利だからです。また、ファイルによっては ugettext_lazy() をデフォルトの翻訳用メソッドに使った方がよい場合もあ ります。グローバル名前空間に _() がなければ、開発者に 場合に応じて適 切な翻訳用メソッドを選ぶ自由を与えられます。
  2. アンダースコア文字は、 Python の対話シェルや doctest で書かれたテスト中 では「直前の式の値」を表します。そのため、グローバル名前空間に _() をインストールすると、干渉して問題を引き起こします。 ugettext()_() という名前で明示的に import すれば、この問題を回避できます。

下の例では、 "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 %(day)s.') % {'month': m, 'day': d}
    return HttpResponse(output)

このテクニックを使うと、言語ごとの翻訳でプレースホルダを並べ変えできるよう になり、例えば、英語の翻訳文が "Today is Nobember, 26." であるのに対し て、スペイン語では "Hoy es 26 de Noviembre." であるように、プレースホル ダの位置を翻訳文の前後で移動できます。

この理由から、引数が複数ある場合には、固定引数を使った補完 (%s%d) ではなく、名前付きの補完 (%(day)s) を使ってください。固定引数 による補完を使った場合、プレースホルダの順番によってうまく翻訳できない場合 があります。

翻訳者へのコメント

リリースノートを参照してください

翻訳可能文字列について翻訳者にヒントを与えたい場合は、 Translators キ ーワードで始まるコメントを、翻訳可能文字列の直前の行に置きます:

def my_view(request):
    # Translators: This message appears on the home page only
    output = ugettext("Welcome to my site.")

テンプレートでは comment タグで同じことができます:

{% comment %}Translators: This is a text of the base template {% endcomment %}

コメントは .po ファイルの中に入り、ほとんどの翻訳ツールで表示できます。

すぐには翻訳しない文字列をマークする

すぐには翻訳しない文字列のマークには django.utils.translation.ugettext_noop() を使って下さい。マークした文字 列は後で変数として使われるときに翻訳されます。

この関数は、ソース言語の中に定数として文字列を置いておきたい場合に使います。 というのも、定数は、例えばデータベース中の文字列のように、システムやユーザ 間で共通な値である一方で、ユーザにメッセージとして提示する最後の段階で翻訳 せねばならない場合があるからです。

複数形化

複数形のメッセージを指定するには 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
}

この例では、文の中の別の部分のために、ローカライズ可能で、うまくすれば既に翻訳 済みのリテラルを再利用しています。 (モデル Metaverbose_nameverbose_name_plural オプションに含まれています) そのため全体が要素のカーディナリティ (cardinality) をもとに一貫したものになりま す。

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

django-admin.py compilemessages: を実行すると エラーが出ます:

a format specification for argument 'name', as in 'msgstr[0]', doesn't exist in 'msgid'

コンステキストマーカー

リリースノートを参照してください

英語の "May" が月の名前と動詞を指すように、単語が複数の意味を持つことがあ ります。このような単語を翻訳者が異なる文脈で正しく翻訳できるようにするには、 django.utils.translation.pgettext() 関数、または複数形が必要な場合は 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 “”
リリースノートを参照してください

trans および blocktrans テンプレートタグはコンテキストマーカー をサポートするようになりました。

翻訳を遅延させる

文字列の翻訳を遅延させる – 値が呼び出された時ではなく、アクセスされた時に翻訳 するには、 django.utils.translation モジュールで遅延バージョンの翻訳関 数を使ってください。 (名前の末尾に lazy がついているのですぐに見分けられま す)

これらの関数は、実際の翻訳結果ではなく、文字列への遅延参照を保存します。翻訳 自体は、文字列がテンプレートのレンダリングなど文字列コンテキストで使われた時 に行われます。

これが重要なのは、モジュールのロード時にコードパスにこれらの関数の呼び出しが配 置されるような時です。

これはモデル、フォーム、モデルフォームを定義する時に容易に起こりえます。 Django はこれらのフィールドをクラスレベル属性として実装しているからです。この 理由により、そのような場合は遅延翻訳を使っているか確認してください。

モデルフィールドとリレーションでの verbose_namehelp_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 オプションによって、 ForeignKeyManyTomanyFieldOneToOneField の名前をマークすることができます:

from django.utils.translation import ugettext_lazy as _

class MyThing(models.Model):
    kind = models.ForeignKey(ThingKind, related_name='kinds',
                             verbose_name=_('kind'))

verbose_name でするように、小文字の名前を渡す 必要があります。 Django はそれを必要な時に自動でタイトルケースにします。

モデルの verbose name の値

verbose_nameverbose_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<django.utils.functional...>" のように出力されるなら、 そのコードにはバグがあります。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([...])) は遅延翻訳オブジェクトを含むリスト に対してはうまく動きません。代わりに 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 自体が文字列の中で使われた 時 (通常はテンプレートのレンダリング時) にだけ文字列変換されます。

言語のローカル名

get_language_info()
リリースノートを参照してください

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 モジュールです。この情報へのアクセス はテンプレートコードからも可能です。下記を参照してください。

テンプレート内での翻訳

Django テンプレート 中の翻訳は、二つのテンプレー トタグを使ってPython コードとは少し違った方法で行います。テンプレートで翻訳 用のタグを使えるようにするには、テンプレートの上の方に {% load i18n %} を入れておきます。

テンプレートタグ {%  trans %}

テンプレートタグ {% trans %} は定数の文字列 (シングルクオートまたはダブ ルクオートで囲まれた文字列) や変数を翻訳します:

<title>{% trans "This is the title." %}</title>
<title>{% trans myvar %}</title>

noop オプションを指定すると、値の参照は行われますが、翻訳はしません。 noop は、将来翻訳が必要なコンテンツを「スタブ」するのに便利です:

<title>{% trans "myvar" noop %}</title>

内部的には、インラインの翻訳は ugettext() を呼び出します。

{% trans %} の中では定数文字列とテンプレート変数を同時に扱えません。翻 訳中で変数 (プレースホルダ) を使いたい場合には、{% blocktrans %} を使 います。

リリースノートを参照してください

表示せずに翻訳文字列を検索したい場合、次の文法を使ってください:

{% trans "This is the title" as the_title %}

<title>{{ the_title }}</title>
<meta name="description" content="{{ the_title }}">

実用上は、複数の場所で使われたり、他のテンプレートタグやフィルタで使われる 文字列を得るために使うことができます:

{% trans "starting point" as start %}
{% trans "end point" as end %}
{% trans "La Grande Boucle" as race %}

<h1>
  <a href="/" title="{% blocktrans %}Back to '{{ race }}' homepage{% endblocktrans %}">{{ race }}</a>
</h1>
<p>
{% for stage in tour_stages %}
    {% cycle start end %}: {{ stage }}{% if forloop.counter|divisibleby:2 %}<br />{% else %}, {% endif %}
{% endfor %}
</p>
リリースノートを参照してください

{% trans %}context キーワードを使って コンテキストマーカー もサポートします:

{% trans "May" context "month name" %}

blocktrans テンプレートタグ

キーワード引数フォーマットが新しくなりました。

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 %}

リリースノートを参照してください

プロック引数のどれかが解決に失敗した場合、 blocktrans は 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 の呼び出しに変換されるということを心に 留めてください。これは notes regarding ungettext variables の適用と同じことを意味します。

リバース URL 参照は blocktrans の中で実行することはできないので、前もって検 索されて (保存されて) おかなければなりません:

{% url path.to.view arg arg2 as the_url %}
{% blocktrans %}
This is a URL: {{ the_url }}
{% endblocktrans %}
リリースノートを参照してください

{% blocktrans %}context キーワードを使った コンテキストマーカー もサポートします:

{% blocktrans with name=user.username context "greeting" %}Hi {{ name }}{% endblocktrans %}

その他のタグ

Requestcontext は 3 つの翻訳処理用の変数にアクセスします:

  • LANGUAGES はタプルのリストです。最初の要素は 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" に翻訳せねばなりません。

リリースノートを参照してください

提供されるテンプレートタグとフィルタを使って利用可能な言語のいずれかについ ての情報を検索することもできます。単一の言語の情報を得るには {% get_language_info %} タグを使います:

{% get_language_info for LANGUAGE_CODE as lang %}
{% get_language_info for "pl" as lang %}

そのあとで情報にアクセスできます:

Language code: {{ lang.code }}<br />
Name of language: {{ lang.name_local }}<br />
Name in English: {{ lang.name }}<br />
Bi-directional: {{ lang.bidi }}

言語のリストについての情報を検索するなら {% get_language_info_list %} テンプレートタグも使えます。 (例えば :LANGUAGE で指定されたアク ティブな言語についてなど) {% get_language_info_list %} を使った言語セ レクタを表示する例を見たいなら、 set_language リダイレクトビューにつ いてのセクション を参照してください。

LANGUAGES のネストしたタプル形式に加えて、 {% get_language_info_list %} は言語コードの単純なリストもサポートして います。ビューの中で使うなら:

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)

JavaScript コードでの国際化

JavaScript に翻訳を追加しようとすると、いくつかの問題に直面します:

  • JavaScript コードには gettext 実装へのアクセス手段がありません。
  • JavaScript コードには .po や .mo ファイルへのアクセス手段がありません。 というのも、これらのファイルはサーバに置かれているからです。
  • JavaScript の翻訳カタログはできるだけ小さくしておかねばなりません。

Django では、これらの問題に対する解決策を組み込みで提供しています。この解決 策は翻訳を JavaScript に渡して、 gettext などを JavaScript コード内で呼 び出せるようにします。

javascript_catalog ビュー

javascript_catalog(request, domain='djangojs', packages=None)

前述の問題に対する解決策は、 django.views.i18n.javascript_catalog`() ビューにあります。このビューは gettext インタフェースをまねた関数の入っ た JavaScript コードと、翻訳文字列のアレイを送信します。翻訳文字列のアレイは info_dict や URLの指定に従ってアプリケーションやプロジェクト、Django コ ア部分から取り出されます。 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<packages>\S+?)/$', 'django.views.i18n.javascript_catalog'),
)

こうしておいて、パッケージ名を ‘+’ で区切ったパッケージ名リストとして指定で きます。これは、複数のアプリケーションからのコードを使っていて、変更が頻繁 に起きている場合、巨大なカタログファイルを毎回プルしなくてすむので便利です。 セキュリティ上の理由から、パッケージ名リストに指定できるのは、 django.confINSTALLED_APPS 設定に入っているアプリケーションだけ です。

LOCALE_PATHS 設定のパスリストで見つけられる JavaScript 翻訳は常に 含められます。 Python とテンプレートで使われる翻訳の検索順序アルゴリズムの一 貫性を保つため、 LOCALE_PATHS のディレクトリリストは、最初に現れ るものとともに、最も高い優先度を持ちます。

LOCALE_PATHS のディレクトリリストはバージョン 1.3 までは 検索アルゴリズムに含まれていませんでした。

JavaScript 翻訳カタログを使う

カタログを使うには、単に以下のようにして動的に生成されたスクリプトをプルし ます:

.. code-block:: html+django
<script type=”text/javascript” src=”{% url django.views.i18n.javascript_catalog %}”></script>

このコードは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 パターンでの国際化

リリースノートを参照してください

Django は URL パターンでの国際化のために 2 つのメカニズムを提供しています:

  • LocaleMiddleware がリクエスト URL からアク アクティブな言語を判別できるように、 ルート URL パターンに言語プレフィックス をつけます。
  • URL パターン自体を django.utils.translation.ugettext_lazy() 関数を通 して翻訳できるようにします。

Warning

これらの機能のいずれかを使うには、各々のリクエストに対してアクティブな言語 がセットされる必要があります。言い換えると MIDDLEWARE_CLASSES 設定に django.middleware.locale.LocaleMiddleware を含める必要があります。

URL パターンの言語プレフィックス

i18n_patterns(prefix, pattern_description, ...)

この関数はルート URLconf で、通常の django.conf.urls.patterns() 関数の代わりに使うことができます。Django は 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<slug>[\w-]+)/$', 'news.views.category', name='category'),
    url(r'^(?P<slug>[\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

i18n_patterns() はルートの URLconf でしか使え ません。インクルードされた URLconf の中で使うと、 ImproperlyConfigured 例外を送出します。

Warning

自動で追加された言語プレフィックスと衝突しないように、プレフィックスのない URL パターンがないことを確認してください。

URL パターンを翻訳する

URL パターンは 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<slug>[\w-]+)/$'), 'news.views.category', name='category'),
    url(r'^(?P<slug>[\w-]+)/$', 'news.views.details', name='detail'),
)

urlpatterns += i18n_patterns('',
    url(_(r'^about/$'), 'about.view', name='about'),
    url(_(r'^news/$'), include(news_patterns, namespace='news')),
)

翻訳を作成した後には 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 の翻訳は ( i18n_patterns() を使った) 言語コードプレフィッ クスの箇所でのみ使うのがベストです。不注意な URL の翻訳が、翻訳されない URL との衝突を起こすことを避けるためです。

テンプレートでのリバース参照

ローカライズされた URL がテンプレート中でリバース参照される場合、常に現在の言語 が使われます。他の言語の URL にリンクするには、 language テンプレートタグを 使ってください。これはタグに囲まれたセクションで与えられた言語を有効にします:

{% load i18n %}

{% get_available_languages as languages %}

{% trans "View this category in:" %}
{% for lang_code, lang_name in languages %}
    {% language lang_code %}
    <a href="{% url category slug=category.slug %}">{{ lang_name }}</a>
    {% endlanguage %}
{% endfor %}

language タグは引数に言語コードだけが渡されることを期待します。

ローカライズ: 言語ファイルの作成方法

文字列に翻訳用のタグをつけたら、今度は翻訳文自体を書く (または手に入れる) 必要があります。ここでは翻訳文を書く方法について示します。

ロケールの制約

Django は、 Django 本体に対する翻訳カタログのない言語への地域化をサポー トしていません。ある言語向けの自作のカタログを提供しても、 Django 本体 にその言語のサポートがなければ、カタログは無視されます。自作のアプリケー ションに特定の言語のロケールをサポートさせたいのなら、まずは Django の コア部分に対する最小限の翻訳カタログを作成する必要があるでしょう。また、 その場合、翻訳されたメッセージ (自作のアプリケーション内のカタログ) と 英語のメッセージ (Django 自体の不完全なカタログ) が入り混じった表示になっ てしまうでしょう。

Django の英語 .po ファイルをコピーし、少なくともいくつかの 翻訳 文字列 を翻訳することから始めると良いでしょう。

メッセージファイル

最初のステップは、新たに追加する言語用の メッセージファイル の作成です。 メッセージファイルは平文テキストファイルで、言語ごとに作成され、翻訳文字列 全てと、言語ごとの対応する表現が収められています。メッセージファイルの拡張 子は .po です。

Django には django-admin.py makemessages というツール が付属しています。このツールはメッセージファイルの作成や維持を自動化します。

Gettext ユーティリティ

makemessages コマンド (および後で議論する compilemessages) は GNU gettext ツールセットのコマンド: xgettext, msgfmt, msgmerge, msguniq を使います。

リリースノートを参照してください

対応している gettext の最低バージョンは 0.15 です。

メッセージファイルの作成や更新を行うには、以下のようにコマンドを実行します:

django-admin.py makemessages -l de

ここで、 de は作成したいメッセージファイルの言語コードです。言語コードは ロケール表示の形式 にします。例えば、ブラジル系ポルトガル 語の場合には pt_BR で、オーストリアドイツは de_AT です。

スクリプトは以下の 2 種類の場所のいずれかで実行します:

  • Django プロジェクトのルートディレクトリ。
  • Django アプリケーションのルートディレクトリ。

スクリプトはプロジェクトのソースツリーやアプリケーションのソースツリーを走 査して、翻訳用にマークされた全ての文字列を取り出します。スクリプトは /locale/LANG/LC_MESSAGES 下にメッセージファイルを作成 (もしくは更新) し ます。 de の例では、ファイルは /locale/de/LC_MESSAGES/django.po で す。

デフォルトの設定では、 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

JavaScriptソースコードからメッセージファイルを作成する 場合は、 -e js ではなく 特別な ‘djangojs’ ドメインを使わなければなりません。

gettext がなかったら?

gettext ユーティリティをインストールしていない場合、 makemessages は空のファイルを作成します。その場合、 gettext ユーティリティをインストールするか、英語用の空のメッセージファイル ( locale/en/LC_MESSAGES/django.po) をコピーして使って下さい。

Windows で動かしたいのですが?

Windows を使っていて、 makemessages を動作させるため に GNU gettext ユーティリティをインストールしたいのなら、 Windows で gettext を使う を参照してください。

.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) の直後の文字列が空文字列の場合、コンテンツ自体はその次の複数行にわたって書 かれているものとみなします。これらの文字列は直接結合されるので、文字列の中 間では末尾にスペースを忘れないようにしましょう。さもないと、空白なしで文字 列がくっついてしまいますよ!

文字コードセットに注意

PO ファイルをテキストエディタで作成するときには、文字コードセット の行 ("CHARSET" を探して下さい) をまず編集して、これから編集に使う 文字セットにしてください。 gettext ツールの内部動作の仕組み上、また、 Django のコア部分やアプリケーションで非 ASCII のソース文字列を扱えるよ うにするために、 PO ファイルのエンコーディングは必ず UTF-8 にしてくださ い。つまり全員が同じエンコーディングを使うことになります。これは Django が PO ファイルを処理する時に大切なことです。

全てのソースコードとテンプレートを新たな翻訳文字列でためし、 全ての 言 語用にメッセージファイルを更新するには、以下のようにします:

django-admin.py makemessages -a

メッセージファイルのコンパイル

メッセージファイルを作成して、変更し終えたら gettext を使ってメッセージ ファイルをより効率的な形式にコンパイルします。作業は django-admin.py compilemessages ユーティリティで行 いましょう。

このツールは全ての .po ファイルをコンパイルして .mo ファイルを作成 します。 .mo ファイルはバイナリファイルで、 gettext で使うために最 適化されています。 django-admin.py makemessages を実 行したのと同じディレクトリで、以下のように django-admin.py compilemessages を実行してくだ さい:

django-admin.py compilemessages

これで終わりです。もう翻訳を使えるようになっているはずです。

Windows で動かしたいのですが?

Windows を使っていて、 django-admin.py compilemessages を動作させるた めに GNU gettext ユーティリティをインストールたいのなら、 Windows で gettext を使う を参照してください。

.po ファイルのエンコーディングと BOM

Django は BOM (バイトオーダーマーク) なしで UTF-8 でエンコードされたファイル しか扱えません。使っているテキストエディタがデフォルトでファイルの先頭に BOM を追加する場合、設定を変更してください。

JavaScript のソースコードからメッセージファイルを作成する

JavaScript のメッセージファイルの作成と更新方法は、他の Django の翻訳カタログの 場合と同じで、 django-admin.py makemessages ツールを使います。唯一違 うのは、 gettext の用語でドメインとして知られているもの、この場合は djangojs ドメインを明示的に指定しなければならないことです。このように -d djangojs パ ラメタを指定してください:

django-admin.py makemessages -d djangojs -l de

上の例では、ドイツ語向けの JavaScript のメッセージファイルを作成または更新して います。翻訳カタログを更新したら、通常の Django メッセージファイルと同じように、 django-admin.py compilemessages を実行してください。

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 を追加します。

xgettext --version コマンドの結果が 0.15 以上なら、別の場所で入手した gettext バイナリを使ってもかまいません。 もし Windows のコマンドプロンプト で xgettext --version を入力した時に “xgettext.exe でエラーが発生しました。” といったポップアップウィンドウが表示されるなら、Django の翻訳ユーティリティに その gettext パッケージを使わないようにしてください。

雑多な情報

set_language リダイレクトビュー

set_language(request)

Django は便利な django.views.i18n.set_language() ビューを提供しています。 これはユーザの言語を設定し、与えられた URL かデフォルトでは 直前のページに戻る ビューです。

URLconf に次の行を足すとこのビューを有効にできます:

(r'^i18n/', include('django.conf.urls.i18n')),

(この例は /i18n/setlang/ にビューを作っています。)

このビューは language パラメータつきで POST メソッドのリクエストによっ て呼ばれることを想定しています。セッションサポートが有効になっていると選択され た言語がユーザのセッションに保存されます。無効の場合は、 django_language という名前のクッキーに言語設定を保存します。 (この名前は LANGUAGE_COOKIE_NAME 設定で変更できます。)

選ばれた言語を設定したら、 Django はユーザを以下のアルゴリズムでリダイレクトし ます:

  • Django は POST データの next パラメータを探します。
  • なかったり空の場合、 Django は Referrer ヘッダの URL を使おうとします。
  • これも空なら、つまりユーザのブラウザが Referrer ヘッダを抑制している場合 ユーザは / (サイトのルート) にリダイレクトされます。

次に示すのは簡単な HTML テンプレートコードです:

<form action="/i18n/setlang/" method="post">
{% csrf_token %}
<input name="next" type="hidden" value="{{ redirect_to }}" />
<select name="language">
{% get_language_info_list for LANGUAGES as languages %}
{% for language in languages %}
<option value="{{ language.code }}">{{ language.name_local }} ({{ language.code }})</option>
{% endfor %}
</select>
<input type="submit" value="Go" />
</form>

この例では 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’ という値を渡してこの関数を呼ぶと LANGUAGE_CODE やミドルウェアに よる言語設定に関わらず "Willkommen" が返されます。

特別な目的のための関数として django.utils.translation.get_language() は、 現在のスレッドで使われている言語を返します。 django.utils.translation.activate() は現在のスレッドで翻訳カタログをアクテ ィベートします。 django.utils.translation.check_for_language() は指定された 言語 が Django でサポートされているかを調べます。

実装に関する注意点

Django 翻訳の特徴

Django の翻訳機構は Python 標準の gettext モジュールを使います。 gettext について詳しければ、 Django の翻訳機能には以下のような特徴があることに気づくで しょう:

  • 文字列ドメイン (string domain) は django または djangojs です。文字列 ドメインは別のプログラムが共通のメッセージファイルライブラリにデータを保存す る時に区別するために使われます。 django ドメインは Python とテンプレート の翻訳文字列に使われ、グローバルの翻訳カタログにロードされます。 djangojs ドメインは JavaScript の翻訳カタログができるだけ小さくなるように、それだけの ために使われます。
  • Django は xgettext を単体では使いません。 xgettextmsgfmt を Python ラッパを通して使います。これは主に利便性のためです。

言語設定の検出メカニズム

翻訳の準備を完了した、あるいは Django 付属の翻訳を使いたいだけなら、あとは アプリケーションで翻訳を有効にするだけです。

背後では、 Django はユーザの使用言語を決めるモデルを備えています。このモデ ルは柔軟で、インストール全体、あるいは特定のユーザ、またはその両方に対して 使用言語を決定できます。

インストール全体での使用言語を設定するには、 LANGUAGE_CODE を設 定します。 Django はこの設定をデフォルトの翻訳言語、すなわち他の適切な翻訳が ない場合に試みる言語に設定します。

Django をネイティブの言語で動かしたいだけで、かつ自分の言語に対する言語ファ イルをすでに準備しているのなら、 LANGUAGE_CODE を設定するだけで済みます。

個々のユーザが自分の使いたい言語を選択できるようにするには LocaleMiddleware を使ってください。 LocaleMiddleware は、リクエスト に埋め込まれたデータに基づいた言語の選択を可能にし、ユーザごとにコンテンツ をカスタマイズします。

LocaleMiddleware を使うには、 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 middleware documentation.)

(ミドルウェアの詳細は ミドルウェアのドキュメント を参照してください。)

LocaleMiddleware はユーザの言語設定を以下のようなアルゴリズムで決定しよ うと試みます:

リリースノートを参照してください
  • はじめに、リクエストされた URL に言語プレフィックスを探します。これはルート URLconf で i18n_patterns 関数を使った場合だけ行われます。 言語プレフィックスと URL パターンの国際化については URL パターンでの国際化 がもっと詳しいです。

  • 見つからなければ、現在のユーザのセッションに django_language キーがない か探します。

  • なければ、クッキーを探します。

    クッキーの名前は LANGUAGE_COOKIE_NAME 設定の値がセットされます。 (デフォルトの名前は django_language です。)

  • うまく行かなければ、 Accept-Language HTTP ヘッダを見ます。このヘッダは ブラウザから送られ、ユーザの望む言語を優先度順に伝えます。 Django は利用可能 な翻訳が見つかるまで、渡された全ての言語を調べます。

  • それも失敗したら、グローバルな LANGUAGE_CODE 設定を使います。

注意:

  • 上記のどのステップでも、言語設定は標準の言語名表記法に従った文字列で 書かれているものと想定しています。例えば、ブラジル系ポルトガル語は pt-br です。

  • 基本言語 (base language) が指定されていて、副言語 (sublanguage) が指 定されていない場合、 Django は基本言語の設定を優先します。例えば、ユー ザが de-at (オーストリアドイツ語) を指定しているのに対して、 Django 側には de のしかない場合、 Django は de を使います。

  • LANGUAGES 設定にリストアップした言語しか選択できません。 (全ての言語に対する翻訳を提供できないなどの理由で) 言語選択を指定の言 語のサブセットに制限したい場合には、 LANGUAGES を設定します。例え ば:

    LANGUAGES = (
      ('de', _('German')),
      ('en', _('English')),
    )
    

    この例では、自動生成されるメニューで利用可能な言語をドイツ語:de と 英語:en (および de-ch や en-us のような副言語) に制限しています。

  • 上の項で説明したように、カスタムの LANGUAGES 設定を行った場合、そ の言語を翻訳対象文字列に含めても構いません。ただし、 django.utils.translationugettext() ではなく、「ダミーの」 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 のソースツリーの翻訳セットに入って いない言語の翻訳を提供したければ、 ロケールの制約 に説明されているように まずその言語むけの基本部分の翻訳を提供する必要があります。

LocaleMiddleware がユーザ設定を検出すると、その設定に HttpRequestrequest.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 の値になるので注意してください。

Django が翻訳を探す方法

実行時に、 Django はメモリ上に統合されたリテラル - 翻訳のカタログを作ります。 これを実現するために、次に示すアルゴリズムによって翻訳を探します。このアルゴリ ズムは、コンパイルされた メッセージファイル (.mo) を ロードするために複数のファイルパスを調べ、同じリテラルに対して複数の翻訳がある 時の優先度を調べます:

  1. LOCALE_PATHS で設定されたディレクトリのリストが最も優先されます。 このなかでは前に書かれたものが後のものより優先されます。
  2. 次に INSTALLED_APPS に列挙されたアプリケーションに local ディ レクトリがあれば、それを見つけて使います。後のものより先に書かれたものが優先 されます。
  3. 次に、プロジェクトディレクトリ、もっと正確に言うと設定ファイルがあるディレク トリで locale ディレクトリを探します。
  4. 最後に、フォールバックとして Django が提供する基本の djang/conf/locale を使います。

Deprecated since version 1.3: 設定ファイルがあるディレクトリから locale サブディレクトリを探す方法 ( 上の 3) は 1.3 から非推奨になっていて、 Django 1.5 では廃止されます。 代わりに LOCALE_PATHS 設定に locale のようなディレクトリの絶 対ファイルパスを書いてください。

See also

JavaScript ファイルに含まれるリテラルの翻訳文字列は、同様な、しかし特別に用 意されたアルゴリズムによって探します。 詳しくは javascript_catalog ビューのドキュメント を 参照してください。

どの場合でも翻訳を含むディレクトリの名前は de, pt_BR, es_AR といっ た ロケール名 表記にしなければなりません。

こうすることで、独自の翻訳の入ったアプリケーションを書いたり、基本の翻訳の 内容をプロジェクトパスに置いた翻訳でオーバライドしたりできます。また、複数 の小さなアプリケーションで大きめのプロジェクトを構築するときに、全ての翻訳 を一つのプロジェクト単位のメッセージファイルにまとめておけます。どういう方 法をとるかはユーザ次第です。

Note

DJANGO_SETTINGS_MODULE を使わない設定方法 に示したように、 DJANGO_SETTINGS_MODULE を使わずに手動で設定を行った場合、プ ロジェクトディレクトリ内の locale ディレクトリはチェックされません。 これは Django がプロジェクトディレクトリの場所を調べる術を持たないから です (Django は通常、設定ファイルのある場所を基準に locale ディレク トリの場所を調べますが、手動で設定を行うと設定ファイルが存在しなくなっ てしまうからです)。

メッセージファイルリポジトリも同じような構成になっています:

  • 設定ファイルの LOCALE_PATHS に書かれた全てのパスから <language>/LC_MESSAGES/django.(po|mo) を探します。
  • $PROJECTPATH/locale/<language>/LC_MESSAGES/django.(po|mo) を探します。上記のように非推奨です。
  • $APPPATH/locale/<language>/LC_MESSAGES/django.(po|mo)
  • $PYTHONPATH/django/conf/locale/<language>/LC_MESSAGES/django.(po|mo)

メッセージファイルの作成には django-admin.py makemessages を使ってください。 locale/ ディレクトリがあるディレクトリで行わねばなりません。 また、 gettext が使うバイナリ形式の .mo ファイルを作成するには django-admin.py compilemessages を使います。

django-admin.py compilemessages --settings=path.to.settings を実行すれ ば、コンパイラに LOCALE_PATHS に設定された全てのディレクトリを処理させ られます。

最後に、翻訳ファイルをどのように構成するかしっかりと考えておくように勧めま す。自分の作ったアプリケーションを他のユーザに配ったり、他のプロジェクトで 利用したりするなら、アプリケーション固有の翻訳が必要になるでしょう。しかし、 アプリケーション固有のメッセージやプロジェクトごとの翻訳は makemessages にまつわる困った問題を引き起こすことがあります: makemessages は現在のパス以下の全てのディレクトリを検索してしまうので、 すでにアプリケーションメッセージファイルに入っているメッセージ ID が、プロ ジェクトのメッセージファイルに入ってしまうことがあるのです。

この問題の最も簡単な解決法は、プロジェクトを直接的に構築しない (なおかつ独 自の翻訳を備えている) アプリケーションをプロジェクトツリーの外に配置してお くというものです。こうすれば、プロジェクトレベルで django-admin.py make-messages を実行しても、自分 のプロジェクトに明に関係する部分の文字列だけを翻訳し、別個に配布されたアプ リケーションの文字列を対象にしなくなります。