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

CakePHPの1.2系から多言語機能が充実しています。

多言語対応の方法としては、翻訳テキストを使う方法(gettextを利用する場合と同等の方法)とDBを使う方法の2種類がありますが、今回の話は前者のほう。

まず失敗談

Bakeryのコチラの記事によると、コンソール機能を使ってソース(*.php,*ctp)の中で __() 関数を使っている箇所を元にpotファイルを作成する方法があるようだったので、この記事のstep3の通り、

> cake extract

とコマンドを入力するとエラーとなって、結局原因が分からないままpoファイルの作成はpoedit(翻訳用のエディタ)に任せて、その場を凌いだのがつい2日前。

そんな時にタイミングよくCakePHP1.2の簡単国際化: CakePHP のおいしい食べ方の記事がアップされていて謎が解消しました。

Bakeryの記事は古い情報だったようで、実際はcake/consoleフォルダに降りて

> cake i18n

と打てばよかったようです。


←確かに利用可能なコンソール機能の表示にはに"extract"なんて無かったので単なる凡ミスorz

上記の記事では

  • コンソールからpotファイル(テンプレートファイル)の作成方法
  • Configureの設定による言語の指定方法
  • 新たに翻訳文字列が追加された場合に、potファイルの再作成とpoeditを使って差分を管理する方法

等が紹介されていて、とても参考になりました。


この記事に掲載されている以外のことで、調べて分かったことを以下にメモします。

コア部分を含めた翻訳をするには

[03/02追記]コア部分の翻訳ファイルは存在しました。詳しくは1.2系の多言語対応メモ(3) - Writing Some Codeを参照して下さい。

cake本体で使われているメッセージの多くも__()関数を使って表示されているので、それらも含めたpotファイルを作成したい時の方法。

まず、←のようにCakePHPのルートフォルダにlocaleというフォルダを作ります。

そしてi18nのコンソール機能で対象のパスを指定する時に、このルートフォルダのパスを指定して実行することによって、作成したlocaleフォルダの下にコア部分とアプリ部分の両方を含めたpotファイルが作成されます。

以下、実行手順のサンプル。

>cake i18n

Welcome to CakePHP v1.2.0.6311 beta Console
---------------------------------------------------------------
What is the full path you would like to extract?
Example: C:\cake12\cake\myapp
[Q]uit
[Q] > C:\cake12
What is the full path you would like to output?
Example: C:\cake12\locale
[Q]uit
[C:\cake12\locale] >
I18n Shell
---------------------------------------------------------------
[E]xtract POT file from sources
[I]nitialize i18n database table
[H]elp
[Q]uit
What would you like to do? (E/I/H/Q)
> E


いずれコア部分の翻訳ファイルは本家で配布されるようになるんでしょうかね?

Config.languageの値とlocaleのフォルダ名の相関について

自分で特定の言語を指定したい場合には

Configure::write('Config.language', 'ja');

といったように指定することが出来て、この時に使われる翻訳ファイルは

app\locale\jpn\LC_MESSAGES\default.po 

となります。

上記の例では日本語を指定する場合ですが、Config.languageの値は"ja"で、localeのフォルダ名は"jpn"であり、双方が同じ名前では無いことに気付きます。

この相関が分からないとConfig.languageに何を設定すれば良いのか、localeのフォルダ名はどうすれば良いのかか分かりません。

これをどうやって調べるかというと、L10nクラス(cake\lisbs\l10n.php)の2つの配列変数$__l10nMap、$__l10nCatalogから調べます。


大雑把ですが要約すると、


  • Config.languageに設定できる値は$__l10nMapの配列のkey、もしくは$__l10nCatalogの配列のkeyの値
  • localeのフォルダ名の決定方法は
    • Config.languageに設定した値が$__l10nMapのkeyの場合、$__l10nMapの指定keyから取り出される値を再度keyにして、$__l10nCatalogから取り出した配列のlocaleの値がフォルダ名となる
    • Config.languageに設定した値が$__l10nCatalogのkeyの場合、$__l10nCatalogからそのkeyで取り出さる配列のlocaleの値がフォルダ名となる。


となります。

また、$__l10nCatalogから指定したkeyで取り出された配列のlocaleFallbackの値はlocaleの代替フォルダとして動くことも確認しました。(localeの値のフォルダが存在しない、またはそのlocaleの値のフォルダの下にdefault.poファイルが存在しない場合に代替される)


文章では伝わりにくいと思うので、サンプルとして抜粋した$__l10nMap、$__l10nCatalogを使って説明します。

<?php
// 抜粋した$__l10nMap 
var $__l10nMap = array(
	/* Afrikaans */ 'afr' => 'af',
	/* English */ 'eng' => 'en',
	/* Zulu */ 'zul' => 'zu');
// 抜粋した$__l10nCatalog 							
var $__l10nCatalog = array(
	'af' => array('language' => 'Afrikaans', 'locale' => 'afr', 'localeFallback' => 'afr', 'charset' => 'utf-8'),
	'en' => array('language' => 'English', 'locale' => 'eng', 'localeFallback' => 'eng', 'charset' => 'utf-8'),
	'en-au' => array('language' => 'English (Australian)', 'locale' => 'en_au', 'localeFallback' => 'eng', 'charset' => 'utf-8'),
	'zu' => array('language' => 'Zulu', 'locale' => 'zul', 'localeFallback' => 'zul', 'charset' => 'utf-8'));
?>

ここで下の2つの設定

Configure::write('Config.language', 'eng');
Configure::write('Config.language', 'en');

この2つの設定は同じ意味で、上は$__l10nMapのkeyにヒットし、下は$__l10nCatalogのkeyにヒットするケースで、localeの値は両方'eng'となり、翻訳ファイルの場所は共に

app\locale\eng\LC_MESSAGES\default.po 

となります。


次に

Configure::write('Config.language', 'en-au');

と設定した場合、localeの値は'en_au'となり、翻訳ファイルの場所は

app\locale\en_au\LC_MESSAGES\default.po 

となります。

ここで、もし

app\locale\en_au\

app\locale\en_au\LC_MESSAGES\default.po 

が存在しない場合、'localeFallback'に設定されている代替値'eng'がlocaleの値となり、翻訳ファイルの場所は

app\locale\eng\LC_MESSAGES\default.po 

となります。

長くなってきたので、

続きは次回にします。