【Laravel】多言語切り替え機能の実装

備忘録、第四弾。

前回書いた[「【Vue.js】vue-i18nを使って多言語化」](https://qiita.com/shin_moto/items/505ae84e9a37601e05ee)の続き。
Laravelで切り替え機能を実装してみた。

参考：
https://mydnic.be/post/laravel-5-and-his-fcking-non-persistent-app-setlocale

## 実装

まずは使用する言語を配列で用意します。

```php:config/languages.php
<?php

return [
    'ja' => '日本語',
    'en' => 'English',
    'cn' => '簡体字',
    'tw' => '繁体字',
];

?>
```

次に言語切り替え処理を書くコントローラーを用意します。

```
$ php artisan make:controller LanguageController
```

```php:LanguageController.php
class LanguageController extends Controller
{
    public function switchLang($lang)
    {
        //用意した言語配列に引数で渡したlangがある時、
        //セッションにkey(applocale)：value($lang)を保存する
        if (array_key_exists($lang, Config::get('languages'))) {
            Session::put('applocale', $lang);
        }
        return Redirect::back();
    }
}
```



middlewareを作成します。

```
$ php artisan make:middleware Language
```

`setlocale()`はロケール情報を設定するメソッドです。

```Middleware/Language.php
class Language
{
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    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);
    }
}
```

新しいミドルウェアを追加したら、カーネルへの追加も忘れずに。

```Kernel.php
protected $middlewareGroups = [
        'web' => [
            \App\Http\Middleware\EncryptCookies::class,
            \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
            \Illuminate\Session\Middleware\StartSession::class,
            // \Illuminate\Session\Middleware\AuthenticateSession::class,
            \Illuminate\View\Middleware\ShareErrorsFromSession::class,
            \App\Http\Middleware\VerifyCsrfToken::class,
            \Illuminate\Routing\Middleware\SubstituteBindings::class,
            \App\Http\Middleware\Language::class,
        ],
```

ルーティングを設定します。

```web.php
Route::get('lang/{lang}', ['as'=>'lang.switch', 'uses'=>'LanguageController@switchLang']);
```

ナビバーにドロップダウンを仕込みます。

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

動かして見るとこんな感じ
![スクリーンショット 2020-09-04 23.10.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531606/a19ed88e-3ee2-300d-e782-0619eca2424d.png)
ドロップダウン
![スクリーンショット 2020-09-04 23.11.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531606/3dffbd1d-949c-b044-0c6c-b09e32871e6a.png)
Englishを選んでみましょう
![スクリーンショット 2020-09-04 23.11.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531606/011bd261-4576-4676-8132-ee965cc2b34a.png)
上手く切り替わりました！