Play Frameworkで多言語対応(i18n)を徹底解説!Twirlテンプレートでの使い方
生徒
「Play Frameworkで作ったWebサイトを、日本語だけじゃなくて英語でも表示したいんです。ページごとにHTMLを分ける必要があるんでしょうか?」
先生
「いいえ、HTMLファイルを分ける必要はありませんよ。Play Frameworkには『i18n』という多言語対応の仕組みがあって、メッセージファイルを用意するだけで表示を切り替えられるんです。」
生徒
「i18n…?難しそうですが、Twirlテンプレート(ビュー)の中で簡単に呼び出せるんですか?」
先生
「使い方はとてもシンプルです。設定方法からビューでの表示方法まで、ステップバイステップで見ていきましょう!」
1. 多言語対応(i18n)の基本概念と準備
Webアプリケーションにおける多言語対応は、一般的に「i18n」と呼ばれます。これは「internationalization(国際化)」の先頭の「i」と末尾の「n」の間に18文字あることに由来しています。Play Frameworkでは、この国際化の仕組みが標準で備わっており、ユーザーのブラウザ設定や特定の言語指定に合わせて、表示するテキストを動的に切り替えることができます。
まず最初に行うべき準備は、プロジェクトの conf/application.conf ファイルで、アプリケーションがサポートする言語を定義することです。
// conf/application.conf の設定例
play.i18n.langs = [ "en", "ja" ]
このように記述することで、英語(en)と日本語(ja)の二ヶ国語をサポートすることをPlay Frameworkに伝えます。この設定を忘れると、いくらメッセージファイルを用意しても正しく認識されないため、必ず最初に確認しましょう。
2. メッセージファイルの作成方法
次に、各言語に対応するテキストを定義する「メッセージファイル」を作成します。これらのファイルはプロジェクトの conf ディレクトリ内に配置します。ファイル名の規則は messages.言語コード となります。
例えば、デフォルトのメッセージファイルとして messages、日本語用として messages.ja、英語用として messages.en を作成します。
conf/messages.ja の内容:
home.title=ホーム画面へようこそ
home.welcome=こんにちは、{0}さん!
login.button=ログイン
conf/messages.en の内容:
home.title=Welcome to Home
home.welcome=Hello, {0}!
login.button=Login
ここで {0} という記述がありますが、これは「プレースホルダ」と呼ばれるものです。ビューから値を渡すことで、動的に名前などを埋め込むことができます。キー(home.titleなど)は共通にして、右側の値だけを各言語で翻訳するのがポイントです。
3. Twirlテンプレートでメッセージを表示する
メッセージファイルの準備ができたら、いよいよTwirlテンプレート(ビュー)でこれらを表示させます。Play Frameworkのビューで多言語メッセージを取得するには、暗黙の引数として MessagesProvider(または Messages オブジェクト)が必要です。
通常、コントローラから MessagesApi を介して渡される情報を利用しますが、Twirl内では非常に簡潔に記述できます。
@* views/index.scala.html *@
@(user: String)(implicit messages: Messages)
<!DOCTYPE html>
<html>
<head>
<title>@messages("home.title")</title>
</head>
<body>
<h1>@messages("home.title")</h1>
<p>@messages("home.welcome", user)</p>
<button class="btn btn-primary">@messages("login.button")</button>
</body>
</html>
@messages("キー名") と書くだけで、現在のユーザーの言語設定に合わせたテキストが自動的に選択されます。引数がある場合は、@messages("home.welcome", user) のように、キーの後に続けて渡すだけです。
4. コントローラからビューへのMessagesの渡し方
ビューで implicit messages: Messages を受け取るためには、コントローラ側で適切に処理を行う必要があります。Java版のPlay Frameworkでは、MessagesApi をインジェクションして使用するのが一般的です。
以下のコードは、現在のリクエストから適切な言語を判断し、ビューに渡すためのコントローラの例です。
package controllers;
import play.mvc.*;
import play.i18n.MessagesApi;
import play.i18n.HttpMessagesApi;
import javax.inject.Inject;
public class HomeController extends Controller {
private final HttpMessagesApi httpMessagesApi;
@Inject
public HomeController(HttpMessagesApi httpMessagesApi) {
this.httpMessagesApi = httpMessagesApi;
}
public Result index(Http.Request request) {
// リクエストに基づいたMessagesオブジェクトを取得
var messages = this.httpMessagesApi.preferred(request);
String userName = "太郎";
// renderメソッドで引数として渡す
return ok(views.html.index.render(userName, messages));
}
}
このコントローラでは、HttpMessagesApi を使ってユーザーの優先言語(ブラウザの Accept-Language ヘッダーなど)に基づいた Messages インスタンスを生成しています。これを render メソッドの引数に含めることで、ビュー側で多言語テキストが表示可能になります。
5. デフォルト言語とフォールバックの仕組み
もし、ユーザーが要求した言語に対応するメッセージファイル(例:フランス語 messages.fr)が存在しない場合はどうなるでしょうか?
Play Frameworkには「フォールバック」という仕組みがあります。
- まず、言語コードと国コードが一致するファイルを探します(例:
ja_JP)。 - 次に見つからない場合は、言語コードのみのファイルを探します(例:
ja)。 - それも見つからない場合は、最も汎用的な
messagesファイル(拡張子なし)の中身を表示します。
このため、共通して使うテキストや、翻訳が間に合っていない言語のための予備として、必ず conf/messages ファイルを作成し、そこにデフォルトの言語(多くの場合は英語など)を記述しておくことが推奨されます。
6. メッセージ内での特殊文字とHTMLエスケープ
メッセージファイルの中でHTMLタグを使いたい場合や、シングルクォートなどの特殊文字を扱いたい場合には注意が必要です。通常、Twirlテンプレートで @messages("...") と記述すると、出力される内容は自動的にHTMLエスケープされます。
もしメッセージファイル内にHTMLを含めてそのまま反映させたい場合は、ビュー側で Html クラスを利用します。
@* HTMLとして出力したい場合 *@
<p>@Html(messages("home.announcement"))</p>
ただし、メッセージファイルに直接HTMLを書くことは、保守性の観点からあまり推奨されません。できるだけテキストのみを定義し、デザインに関するHTMLタグはTwirlテンプレート側に記述するようにしましょう。
また、メッセージファイル内でシングルクォート(')を使いたい場合は、二重にする('')必要があることも覚えておくとトラブルを防げます。
7. 言語の動的切り替え(プログラマチックな変更)
ブラウザの設定に任せるだけでなく、サイト上のボタン(「English」「日本語」など)をクリックして言語を切り替えたい場合もあります。Play Frameworkでは、クッキーを使用してユーザーの言語設定を固定することが可能です。
コントローラで withLang メソッドを使用することで、レスポンスに言語設定を保存するクッキーを含めることができます。
public Result changeLanguage(String langCode, Http.Request request) {
// 新しい言語設定でリダイレクトし、クッキーをセットする
return redirect(routes.HomeController.index())
.withLang(play.i18n.Lang.forCode(langCode), messagesApi);
}
このように実装することで、ユーザーが一度言語を選択すれば、次回以降のアクセスでもその言語が優先的に表示されるようになり、利便性が大幅に向上します。
8. 複雑なメッセージ構造とパラメータの活用
実際の開発では、単純な文字列の置き換えだけでなく、数値や日付のフォーマットも多言語化したい場面が出てきます。メッセージファイルでは、Javaの MessageFormat クラスの構文を利用できるため、高度な記述が可能です。
例えば、項目の個数によってメッセージを出し分けるような「複数形(Plurals)」の制御も工夫次第で実現できます。また、パラメータを複数渡す場合は {0}, {1}, {2} と増やしていくだけです。
# conf/messages.ja
cart.summary={0}個の商品がカートに入っています。合計金額は {1} 円です。
これをビューで呼び出す際は以下のようになります。
<div class="alert alert-info">
@messages("cart.summary", itemCount, totalPrice)
</div>
このように、Twirlテンプレートとメッセージファイルを組み合わせることで、ロジック(Javaコード)、構造(HTML/Twirl)、表示テキスト(Messages)を綺麗に分離することができ、メンテナンス性の高いWebアプリケーションを構築できます。