PHP
laravel
laravel5.4

Laravelで言語切替実装した時のメモ(多言語化)

基本はこのページに書いてある事だけで出来ました。簡単!
https://mydnic.be/post/laravel-5-and-his-fcking-non-persistent-app-setlocale

切替言語のconfig作成

言語の略称と表示名の配列。今回は日本語/英語/タイ語に対応。

config/languages.php
   /**
    * 言語切替
    */
  return [
    'en' => 'English',
    'ja' => '日本語',
    'th' => 'ภาษาไทย',    
    ];

言語設定のmiddleware作成

コマンドを実行

$ php artisan make:middleware Language

middlewareファイルを実装

app/Http/Middleware/Language.php
<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Foundation\Application;
use Illuminate\Http\Request;
use Illuminate\Routing\Redirector;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\Session;

class Language
{
    public function handle($request, Closure $next)
    {
        if (Session::has('applocale') AND array_key_exists(Session::get('applocale'), Config::get('languages'))) {
            App::setLocale(Session::get('applocale'));
        }
        else {
            App::setLocale(Config::get('app.fallback_locale'));
        }
        return $next($request);
    }
}

カーネルに追加する。
以下の書き方でroute/web.phpの処理の際に自動適用される。(毎回必ず実行されるため、処理の負荷などを考慮する場合は他の方法を考えた方が良い)

app/Http/Kernel.php
    protected $middlewareGroups = [
        'web' => [
                        //(省略)

            \App\Http\Middleware\Language::class,

                        //(省略)
        ],

言語切替のcontroller作成

コマンドを実行

$ php artisan make:controller LanguageController

切替時に呼び出される処理の作成

app/Http/Controllers/LanguageController.php
namespace App\Http\Controllers;

use Auth;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\Redirect;
use Illuminate\Support\Facades\Session;

class LanguageController extends Controller
{
    /**
     *  言語切り替え処理 
     */
    public function switchLang($lang)
    {
        if (array_key_exists($lang, Config::get('languages'))) {
            Session::put('applocale', $lang);
        }
        return Redirect::back();
    }
}

controllerの呼び出しを定義

引数に言語の略称を持ったGETを受けた際に、言語切替処理を呼ぶ。

routes/web.php
/**
 * 言語切替
 */
Route::get('lang/{lang}', ['as'=>'lang.switch', 'uses'=>'LanguageController@switchLang']);

view側に呼び出し元を作る

以下は、最初のURL先の内容を元に作った例です。今の言語設定がdropdownの初期表示になり、残りの言語を選べる。

views/layouts/nav.blade.php
<!-- 言語切り替え -->
<li class="dropdown" id="nav-lang">
    <a href="#" class="dropdown-toggle" data-toggle="dropdown">
        {{ Config::get('languages')[App::getLocale()] }}
    <span class="caret"></span></a>
    <ul class="dropdown-menu">
        @foreach (Config::get('languages') as $lang => $language)
            @if ($lang != App::getLocale())
                <li>
                    <a href="{{ route('lang.switch', $lang) }}">{{$language}}</a>
                </li>
            @endif
        @endforeach
    </ul>
</li>

実際の言語ファイルを作る

resources/lang以下に「en」,「ja」,「th」を作る。

英語

resources/lang/en/messages.php
<?php

return [

    /*
    |-----------------------------------------------------------------
    | resources/views/nav.blade.php
    |-----------------------------------------------------------------
    */
    'nav_welcome' => 'Welcome, :name',
    'nav_lang' => 'Language:',
    'nav_time' => 'Timezone:',
];

日本語

resources/lang/ja/messages.php
<?php

return [

    /*
    |-----------------------------------------------------------------
    | resources/views/nav.blade.php
    |-----------------------------------------------------------------
    */
    'nav_welcome' => 'ようこそ:nameさん',
    'nav_lang' => '言語:',
    'nav_time' => 'タイムゾーン:',
];

タイ語

resources/lang/th/messages.php
<?php

return [

    /*
    |-----------------------------------------------------------------
    | resources/views/nav.blade.php
    |-----------------------------------------------------------------
    */
    'nav_welcome' => 'ยินดีต้อนรับ, :name',
    'nav_lang' => 'ภาษา:',
    'nav_time' => 'เขตเวลา:',
];

実際のhtmlでの使い方

views/layouts/nav.blade.php
<!--タイムゾーン -->
<p>{{ __('messages.nav_time') }}</p>

<!--ようこそ+(ユーザー名) -->
<p>{{ __('messages.nav_welcome', ['name' => Auth::user()->name]) }}</p>

感想

とてもスムーズに実装できた。middleware便利。
ただ、viewの可読性が著しく下がった。