Laravelの国際化対応

タグ: Laravel3  

新しく追加された機能のため、ドキュメントに記述されていませんが、LaravelにはURIの最初に言語コードを指定することで、デフォルトの言語を切り換える機能が存在しています。

国際化に対応するためには言語により切り換える文字列をapplication/language/言語コードフォルダーの下に言語ファイルを作成しておきます。キーと文字列の配列です。他のフレームワークでも大抵同様な指定方法ですね。

そして多国語する場所で__('キー')とすることでデフォルト言語が表示されます。別の言語に切り換えるには、__('キー', null, '言語コード')と指定します。

全ての国際化対応文字列を言語コードを含めた形式で記述するのは大変なため、URIの後ろに言語コードを指定した場合、その言語コードをデフォルト言語とする機能が採用されました。

例えばsample.com/ja/homeでしたら、ルートは/home扱いですが、デフォルト言語は日本語に切り替わるため、`__('キー')で、設定してある日本語で表示されるわけです。

この方法を使用するには、application/config/application.phpを開き、languages配列に対応言語を指定してください。指定された言語コードがURIの先頭の場合のみ、デフォルト言語の切り替え機能が動作します。

これはURIが言語により別れるため、SEO的には有利です。それぞれ別言語扱いですから、別ページとして検索エンジンは扱ってくれます。

ただ、この方法は利用者に言語を切り替えさせることが前提ですし、そのためにユーザーに人手間かけさせるため、私の好みではありません。そこで、ブラウザに設定してある表示コードから自動的に切り換える方法を紹介します。

なお、この方法は公開している開発ベースに含まれています。

参照:Laravel3 開発ベースとCRUDサンプル

自動でブラウザ設定言語に切り換える

設定ファイルapplicaton/config/language.phpを追加します。

<?php
/*
 * 多国語対応用設定ファイル
 */
return array(
    'support' => array( 'ja' => '日本語', 'en' => '英語' ),
    'fallback' => 'en', // 対応言語以外がブラウザで指定されていた場合は、英語で表示
);

対応言語は日本語と英語、もし日本語と英語以外にブラウザの表示言語を設定してある場合は、英語を選択します。

続いてapplication/routes.phpのグローバルbeforeフィルターに、言語の切り替えコードを書きましょう。

Route::filter('before',
    function() {
        // クッキー、ブラウザ設定から表示言語を決定する
        $default = Config::get('language.fallback', 'en');

        if ( Cookie::has('language') )
        {
            Config::set('application.language', Cookie::get('language'));
        }
        elseif ( !isset($_SERVER['HTTP_ACCEPT_LANGUAGE']) ) // IEは未設定を許す
        {
            Config::set('application.language', $default);
        }
        else
        {
            // 最初にデフォルト言語をセットしておく
            Config::set('application.language', $default);

            // ブラウザの言語設定を読み込む
            $lang = explode(',', $_SERVER['HTTP_ACCEPT_LANGUAGE']);

            // $langs[言語コード] = プライオリティの形式に変換
            $langs = array( );
            foreach ( $lang as $key => $code_priority ) {
                if ( preg_match('/(.+);q=([0-9\.]+)/', $code_priority, $matched) === 1 )
                {
                    $langs[$matched[1]] = $matched[2];
                }
                else
                {
                    $langs[$code_priority] = '1'; // デフォルト値
                }
            }
            // プライオリティ(配列の値)でソート
            arsort($langs);

            // サポート言語として存在するかチェック
            foreach ( $langs as $code => $priority ) {
                if ( array_key_exists($code, Config::get('language.support')) )
                {
                    Config::set('application.language', $code);
                    break;
                }
            }
        }
    });

このコードは、クッキーに言語コードの指定がある場合は、それを優先とします。一度ユーザーが切り替えたら、選択した言語で表示します。一度も選択されていない場合は、ブラウザに設定してある表示言語をデフォルト言語として設定します。

ついでですから、言語の切り替えルートを紹介しておきます。ただ、クッキーを設定し、リダイレクトするだけです。

/*
 * 英語表示切替
 */
Route::get('set/english',
    array(
        'as' => 'set-english',
        function() {
            Cookie::forever('language', 'en');
            return Redirect::home();
        }
    )
);

/*
 * 日本語表示切替
 */
Route::get('set/japanese',
    array(
        'as' => 'set-japanese',
        function() {
            Cookie::forever('language', 'ja');
            return Redirect::home();
        }
    )
);

本当はリダイレクトはhome()でなく、back()にしたいんですけど、IEの一部では正しく動作しないそうなので、home()にしています。