2010年11月29日月曜日

Kayでの国際化対応

Kayチュートリアルで国際化についての説明がある。

Kayドキュメント 1.8. ゲストブックの実装 - Step 4

手順は説明されているのだが、背景説明が足りないような気がしたので補足メモ書きする。

1.8.1. 国際化を有効にする arrow0302.gif
settings.py で USE_I18N を True に設定します。
USE_I18N = True
I18Nとはプログラムを複数言語に対応させることである。internationalizationもしくはinternationalisationの略で、IとNの間に18文字あるので、I18Nとしている。

同様にL10Nはプログラムを特定地域に対応させることである。これも、localizationの略で、IとNの間に10文字あるのでI10Nとしている。

参考 wiki 国際化と地域化


1.8.2. 国際化のためにメッセージをマークする arrow0302.gif
# -*- coding: utf-8 -*-
# myapp.models
 
from google.appengine.ext import db
from kay.auth.models import GoogleUser
import kay.db
from kay.i18n import lazy_gettext as _
 
# Create your models here.
 
class MyUser(GoogleUser):
  pass
 
class Category(db.Model):
  name = db.StringProperty(required=True, verbose_name=_(u'Name'))
 
  def __unicode__(self):
    return self.name
 
class Comment(db.Model):
  user = kay.db.OwnerProperty()
  category = db.ReferenceProperty(Category, verbose_name=_(u'Category'))
  body = db.StringProperty(required=True, verbose_name=_(u'Your Comment'))
  created = db.DateTimeProperty(auto_now_add=True)
kay.i18n.lazy_gettext を _ として import しています。更にフォー ムに表示するフィールドには verbose_name という引数を渡すようにして、 値を _() の呼び出しで囲んでおきます。
verbose_nameは人間可読なオブジェクト名の単数形、複数形はverbose_name_plural。

参考 Djangoドキュメント varbosa_name

gettextは国際化ライブラリーの構成要素の一つである。ソースの文字列がgettext関数へ渡されるよう、文字列をラップしていくことが必要。
キータイプを省くためgettextには通常、_エイリアスを付ける慣習になっている。

参考 wiki Gettext

ノート
詳しくは説明しせんが、大雑把に言うと models.py や forms.py では lazy_gettext を使用します。views.py の中では gettext を使用 します。
gettextは翻訳関数なのだが、lazy_gettextは遅延翻訳関数と呼ぶそうだ。翻訳のタイミングによって、予期しない翻訳文字列が表示されてしまう可能性がある。
lazy_gettextは文字列にアクセスするタイミングで翻訳するので、予期しない文字列が表示される可能性が減るということのようだ。

参考 Pylons 遅延翻訳

次はテンプレート内部の文字列をマークしましょう。ここでは練習のため二つの方法を試します。 myapp/templates/index.html:
  {% if request.user.is_anonymous() %}     {{ _('login') }}   {% else %}     Hello {{ request.user }}!       {% trans %}logout{% endtrans %}        {% endif %}
Kayにおいてはテンプレートエンジンとして、Jinja2を利用している。
Jinja2での国際化は {% trans %} もしくは _() を利用する。
  1. 使用方法 {% trans %}

    文字列を{% trans %} {% end trans %} で囲む

    {% trans %}Hello {{ user }}!{% endtrans %}

    テンプレート変数を定義して囲むことも可能

    {% trans user=user.username %}Hello {{ user }}!{% endtrans %}

    {% trans book_title=book.title, author=author.name %}
    This is {{ book_title }} by {{ author }}
    {% endtrans %}
    
    複数形文字列を定義することも可能
    {% trans count=list|length %}
    There is {{ count }} {{ name }} object.
    {% pluralize %}
    There are {{ count }} {{ name }} objects.
    {% endtrans %}
    
    ここで {% pluraize %} の次の文字列が複数形文字列
    単数か複数かを判断するのは {% trans %}内に定義している最初の変数

  2. 使用方法 _()

    文字列を_()で囲む
    {{ _('Hello World!') }}
    
    フォーマット・フィルターを利用することにより、変数定義も可能
    {{ _('Hello %(user)s!')|format(user=user.username) }}
    
    _()はgettext関数を定義しているが、-_()でngettext関数が定義されている。
    複数形文字列の定義をする場合は、-_() を利用する。

    参考 ngettext関数 Python ライブラリリファレンス

参考 Jinja2 Jinja Template Designer Documentation i18n


1.8.3. 翻訳を作成する arrow0302.gif
下記のコマンドでマークした文字列を抽出します。
$ python manage.py extract_messages -a
Running on Kay-0.10.0
Extracting from /Users/tmatsuo/work/kay-tutorial/myproject/myapp
myapp/__init__.py
myapp/forms.py
myapp/management.py
myapp/models.py
myapp/urls.py
myapp/views.py
myapp/templates/index.html
All done.
これは POT (Portable Object Template) ファイルを作成する処理。
POTは翻訳関数に渡されたあらゆる文字列を集めたテンプレートファイルとなる。

日本語用の po ファイルを作成します。
$ python manage.py add_translations -a -l ja
Running on Kay-0.10.0
Creating myapp/i18n/ja/LC_MESSAGES/messages.po.
Cant open file. Skipped myapp/i18n/jsmessages.pot.
Created catalog for ja
Cant open file. Skipped /Users/tmatsuo/work/kay-tutorial/myproject/i18n/messages.pot.
Cant open file. Skipped /Users/tmatsuo/work/kay-tutorial/myproject/i18n/jsmessages.pot.
Created catalog for ja
PO (Portable Object) ファイルの作成処理。
POTから各言語用翻訳ファイル(PO)を生成する。
生成したPOファイルを、エディター等で訳語を入力してカタログを完成させる。

上記のように編集した後に、このファイルをコンパイルします。
$ python manage.py compile_translations -a
Running on Kay-0.10.0
Compiling myapp/i18n
Compiling myapp/i18n/ja/LC_MESSAGES/messages.po
All done.
i18n folder missing
これでアプリケーションにアクセスすれば、翻訳文字列を準備した場所では日本語が表示されているはずです。
この処理で、MO (Machine Object) ファイルが生成される。
POを処理して機械可読が容易なバイナリーファイル(MO)にする。

参考 Pylons 国際化とローカライズ