Play! framework 2.0でのi18n関連
Scala Advent Calendar 2012の2日目、のはずだったけど、諸事情によりこちらの 12/5 の記事になりました。
Play! framework 2.0のアプリを国際化する方法についてちょっと書きます。基本はここに書いてある通りだけど、補足とか書いていない事とかハマりポイントとか。
前提・環境
- Play 2.0.4
- 英語・日本語の2か国語に対応
- 英語がデフォルトの言語
メッセージカタログにメッセージを外出し
基本
以下の3ファイルを用意
- conf/messages.en → 英語のメッセージ
- conf/messages.ja → 日本語のメッセージ
- conf/messages → デフォルトのメッセージ
最初の2つは説明不要だと思うので、最後のに関して説明。
デフォルトのメッセージファイル
例えばviewの中で以下のような記述があり、
@Messages("index.welcome", user.name)
ユーザーの言語(これがどうやって定まるかは後述)が"ja"だとすると、messages.ja の以下の行が使われる。
#messages.ja index.welcome={0}さん、ようこそ
仮に、この行がないと、messages の中の対応する行が使われる。
#messages index.welcome=Welcome {0}!
画像
ファイルの配置
メッセージだけ多言語対応すればi18nが完了すると思っちゃだめで、画像内のテキストとかも対応する必要がある。
画像は以下の様な感じでフォルダ分けしておく。
- public/images/common → 言語関係なく使う画像(字のないアイコン、線、背景等)
- public/images/en → 英語用の画像
- public/images/ja → 日本語用の画像
viewからの参照
画像を表示する場合は、基本は後述するCSS(LESS)で対応した方が簡単だけど、view 内で直接 img タグを書きたい場合には以下のようにする。
@(param: some.Type)(implicit lang: Lang) <!-- ↑先頭で implicit parameter として lang を受け取る --> <img src="images/@lang.language/foo.png" />
CSS
プロジェクトの設定
Build.scala は以下のように。
// どの less ファイルをコンパイルするか、みたいな設定 def customLessEntryPoints(base: File): PathFinder = ( (base / "app" / "assets" / "stylesheets" * ("*.less" -- "_*.less")) ) // project 設定に、lessEntryPoints を追加。 val main = PlayProject(appName, appVersion, appDependencies, mainLang = SCALA).settings( // Add your own project settings here lessEntryPoints <<= baseDirectory(customLessEntryPoints), )
これで準備完了。
LESS
LESS便利だね。lessファイルの配置に関して説明。
まずはapp/assets/stylesheets というディレクトリを作成し、その配下に以下のようにファイルを作成。
- en.less
- ja.less
- _common.less (サブディレクトリに入れてもよし)
en.less はこんな感じ。ja.lessも同様に作る。
@lang: en;
@import "_common.less";
_common.less はこんな感じ。
.logo { background: url("/images/@{lang}/logo.png"); }
これで、en.css は以下のように生成される。
.logo { background: url("/images/en/logo.png"); }
LESS便利だね。
LESSのハマりポイント
とにかくエラーメッセージが分かりにくい。
LESSの行末のセミコロンがなかったり(Scalaプログラマーがよくやる間違い)、urlのダブルクォートがなかったりすると意味不明のメッセージが出る。そのメッセージでググると、Play自体のバグだとか、ライブラリのバグだとか色々情報が出てくるけど、実際は簡単なミスだったりする。
ということで、いきなりがっつり書かず、まずは簡単なLESSファイルを書いてある程度仕組みに慣れてから、徐々にやってくと良さそう。
ちなみに、出たエラーはこんなの。
EcmaError: TypeError: Cannot call method "charAt" of undefined (less-1.3.0.js#352)
まとめ
Play 2.0の多言語対応は、基本的な機能は揃っているので、どんどん海外対応のアプリ・サービスを作るといいのでは。