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
があります。 書式ローカライズ
を参照してください。
翻訳対象文字列を関数 ugettext()
で指定します。タイプ数を減らすため、
ugettext()
を _
という別名で import するのが慣習的なやり方です。
Note
Python の標準ライブラリ gettext
は、グローバルの名前空間に _()
とい
う名前で gettext()
をインストールします。 Django ではこの方法に 従って
いませんが、それは以下の理由からです:
gettext()
よりも
ugettext()
の方が便利だからです。また、ファイルによっては
ugettext_lazy()
をデフォルトの翻訳用メソッドに使った方がよい場合もあ
ります。グローバル名前空間に _()
がなければ、開発者に 場合に応じて適
切な翻訳用メソッドを選ぶ自由を与えられます。_()
をインストールすると、干渉して問題を引き起こします。 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
}
この例では、文の中の別の部分のために、ローカライズ可能で、うまくすれば既に翻訳
済みのリテラルを再利用しています。 (モデル Meta
の
verbose_name
と verbose_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_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'))
verbose_name
でするように、小文字の名前を渡す
必要があります。 Django はそれを必要な時に自動でタイトルケースにします。
verbose_name
と
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<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()
をモデルやユーティリティ関数の中
の文字列をマークするのに使うことは、一般的な操作です。コードの中でこれらのオ
ブジェクトを使う時は、偶然に文字列に変換されてしまわないか確認するべきです。
できるだけ遅く変換されるべきだからです。これは次に説明するヘルパー関数の使用
を伴います。
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 に翻訳を追加しようとすると、いくつかの問題に直面します:
gettext
実装へのアクセス手段がありません。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.conf
か INSTALLED_APPS
設定に入っているアプリケーションだけ
です。
LOCALE_PATHS
設定のパスリストで見つけられる JavaScript 翻訳は常に
含められます。 Python とテンプレートで使われる翻訳の検索順序アルゴリズムの一
貫性を保つため、 LOCALE_PATHS
のディレクトリリストは、最初に現れ
るものとともに、最も高い優先度を持ちます。
LOCALE_PATHS
のディレクトリリストはバージョン 1.3 までは
検索アルゴリズムに含まれていませんでした。カタログを使うには、単に以下のようにして動的に生成されたスクリプトをプルし ます:
.. 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
を使って適切な複数形表現を実現したい場合) だけにしてください。
リリースノートを参照してください
Django は URL パターンでの国際化のために 2 つのメカニズムを提供しています:
LocaleMiddleware
がリクエスト URL からアク
アクティブな言語を判別できるように、 ルート URL パターンに言語プレフィックス
をつけます。django.utils.translation.ugettext_lazy()
関数を通
して翻訳できるようにします。Warning
これらの機能のいずれかを使うには、各々のリクエストに対してアクティブな言語
がセットされる必要があります。言い換えると
MIDDLEWARE_CLASSES
設定に
django.middleware.locale.LocaleMiddleware
を含める必要があります。
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 パターンは 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 種類の場所のいずれかで実行します:
スクリプトはプロジェクトのソースツリーやアプリケーションのソースツリーを走
査して、翻訳用にマークされた全ての文字列を取り出します。スクリプトは
/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 のメッセージファイルの作成と更新方法は、他の Django の翻訳カタログの
場合と同じで、 django-admin.py makemessages
ツールを使います。唯一違
うのは、 gettext の用語でドメインとして知られているもの、この場合は djangojs
ドメインを明示的に指定しなければならないことです。このように -d djangojs
パ
ラメタを指定してください:
django-admin.py makemessages -d djangojs -l de
上の例では、ドイツ語向けの JavaScript のメッセージファイルを作成または更新して
います。翻訳カタログを更新したら、通常の Django メッセージファイルと同じように、
django-admin.py compilemessages
を実行してください。
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 はユーザを以下のアルゴリズムでリダイレクトし ます:
POST
データの next
パラメータを探します。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 の翻訳機構は Python 標準の gettext
モジュールを使います。 gettext
について詳しければ、 Django の翻訳機能には以下のような特徴があることに気づくで
しょう:
django
または djangojs
です。文字列
ドメインは別のプログラムが共通のメッセージファイルライブラリにデータを保存す
る時に区別するために使われます。 django
ドメインは Python とテンプレート
の翻訳文字列に使われ、グローバルの翻訳カタログにロードされます。 djangojs
ドメインは JavaScript の翻訳カタログができるだけ小さくなるように、それだけの
ために使われます。xgettext
を単体では使いません。 xgettext
や msgfmt
を
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.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 のソースツリーの翻訳セットに入って
いない言語の翻訳を提供したければ、
ロケールの制約 に説明されているように
まずその言語むけの基本部分の翻訳を提供する必要があります。
LocaleMiddleware
がユーザ設定を検出すると、その設定に
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
の値になるので注意してください。
実行時に、 Django はメモリ上に統合されたリテラル - 翻訳のカタログを作ります。
これを実現するために、次に示すアルゴリズムによって翻訳を探します。このアルゴリ
ズムは、コンパイルされた メッセージファイル (.mo
) を
ロードするために複数のファイルパスを調べ、同じリテラルに対して複数の翻訳がある
時の優先度を調べます:
LOCALE_PATHS
で設定されたディレクトリのリストが最も優先されます。
このなかでは前に書かれたものが後のものより優先されます。INSTALLED_APPS
に列挙されたアプリケーションに local
ディ
レクトリがあれば、それを見つけて使います。後のものより先に書かれたものが優先
されます。locale
ディレクトリを探します。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
を実行しても、自分
のプロジェクトに明に関係する部分の文字列だけを翻訳し、別個に配布されたアプ
リケーションの文字列を対象にしなくなります。
Oct 26, 2017