1.2系の多言語対応メモ(2)

前回の記事の続きです。

指定した言語の翻訳が存在しない場合は引数の値(msgid)がそのまま表示される

指定した言語のlocaleのフォルダやpoファイルがない、対訳が存在しない等の場合、__()関数の第1引数の値(msgid)そのものが表示されます。

なので、引数のメッセージには意味の通る文章を必ず入れるのがベストです。

__()関数以外にも翻訳関数が存在する

cake\basics.phpを覗くと、__()関数以外にも

  • __d()
  • __c()
  • __n()
  • __dn()
  • __dc()
  • __dcn()

といった翻訳関数が存在します。

これらの関数名には意味があり、関数名にdが含まれる関数は「ドメインの指定」、cが含まれる関数は「カテゴリーの指定」、nが含まれる関数は「複数形への対処の指定」が出来るようになっています。

例えば、__d()は「ドメインの指定が出来る翻訳関数」、__dc()は「ドメインとカテゴリの指定が出来る翻訳関数」といったようにd,c,nの組み合わせで関数名が作られています。


ドメインの指定とは

ドメインとはファイル名のdefault.poの拡張子を除いた値に該当します。

例として、

__d('sample', 'This is a message');

とすると、指定言語のフォルダのsample.poファイルからmsgidが'This is a message'の対訳を取得します。

カテゴリの指定とは

カテゴリーとはpoファイルまでのパスがapp\locale\jpn\LC_MESSAGES\default.poだとすると、"LC_MESSAGES"部分の値に該当します。

カテゴリーは0〜6の値で指定することが出来、それぞれは

LC_CTYPE     0
LC_NUMERIC   1
LC_TIME      2
LC_COLLATE   3
LC_MONETARY  4
LC_MESSAGES  5 ←デフォルト値
LC_ALL       6

という意味になります。

例として、

__c('xxx', 1);

とすると、指定言語のフォルダの"LC_NUMERIC"フォルダから対訳を取得するようになります。


ただ、実際にメッセージ(LC_MESSAGES)以外のカテゴリーを指定した場合、日付の形式や通貨の表示などをどのように実装するのか、どうすればちゃんと動作するのかまでは検証できていません。

複数形への対処の指定とは

日本語ではあまり意識しない単数形と複数形の違い、例えば日本語で「〜個のファイルが削除されました。」というのは個数に関係なく同じ表現ですが、英語では「1 files was removed.」「2 files were removed.」と単数形と複数形では表現が異なります。

例として、英語のpoファイルの中に

"Plural-Forms: nplurals=2; plural=(n!=1);"
msgid '%d file was removed.'
msgid_plural '%d files were removed.'
msgstr[0] '%d file was removed.'
msgstr[1] '%d files were removed.'

という設定をして

__n('%d file was removed.', '%d files were removed.', n);

とした場合、第3引数のnの値が1の場合はmsgstr[0]の'%d file was removed.'、1以外の場合はmsgstr[1]の'%d files were removed.'が使われます。

細かい説明は省略しますが、参考にしたサイトのリンクを貼っておきます。参考サイトはRubyでのgettextの話ですが、Plural-Formsの設定内容等は同じ考えなので参考になります。

参考サイト:http://www.yotabanana.com/hiki/ja/ruby-gettext-howto.html#GetText.n_%28msgid%2C+msgid_plural%2C+n%29%A4%CE%BB%C8%A4%A4%CA%FD

翻訳リソースはバイナリ形式のmoファイルでもいける

通常、国際化といえばgettextを使用してpoファイルの作成⇒バイナリ形式のmoファイルの作成⇒プログラムからはmoファイルを使用といった手順が標準のようですが、CakePHPではpoファイルからの翻訳が可能です。

では、CakePHPではmoファイルが使えないのかというとそうではないようで、moファイルがあればmoファイルの翻訳を見にいくようになっています。

例えば

__('hoge'); 

としたとき、default.moが存在すれば、default.poではなくdefault.moから翻訳を取り出します。


moファイルはバイナリ形式なので、テキスト形式のpoファイルに比べてパフォーマンスが良さそうですね。

気が向いた時にベンチマークでも取ってみようと思います。