Laravelで多言語対応いろいろ

Bladeを使った多言語対応に関しては以下に乗ってるのでそれ以外に関して
https://readouble.com/laravel/5.8/ja/localization.html

###言語切替の実装方法

まずroutes/web.phpに切り替え用のリクエストを実装

```diff:routes/web.php
+Route::post('lang/{language}', 'ExampleController@language')->name('language');
```
受け側のコントローラー

```app/Http/ExampleController.php
<?php
namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Session;

class ExampleController extends Controller
{
...
	public function language(Request $request, $language)
	{
		// セッションに言語コードをセット
		Session::put('language',$languqage);
		// ダミーの戻り値
		return ['result'=>'OK'];
	}
}
```

呼び出し側

```js:app.js
let lang = [プルダウンの値などを取得]
let params = new URLSearchParams()
let url = '/lang/'+lang	// ex. /lang/ja | /lang/enなど
window.axios.post(url,params)
	.then((response)=>{
	})
	.catch((error)=>{
	})
```

言語切替の利用側
ミドルウェア

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

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

namespace App\Http\Middleware;

use App;
use Closure;

class Language
{
	public function handle($request, Closure $next)
	{
		// セッションから言語コードを取り出しロケールにセット
		if(session('language'))
		{
			App::setLocale(session('language'));
		}
		return $next($request);
	}
}

```

ミドルウェアの登録

```diff:app/Http/Kernel.php
protected $routeMiddleware = [
...
+	'language' => \App\Http\Middleware\Language::class,
];

```

このミドルウェアは各コントローラーで使うのでapp/Http/Controller.phpに処理を定義して継承先でコールするのが望ましいかと思う
__construct()で呼ばないとバリエーションメッセージなどに適応されないなどがあったためここで処理

```diff:app/Http/Controller.php
class Controller extends BaseController
{
...
+	public function __construct()
+	{
+		$this->middleware('language');
+	}
}
```

各コントローラーには以下の様に追記

```diff:app/Http/Auth/LoginController.php
	public function __construct()
	{
		// 親クラスのコンストラクタをコール
+		parent::__construct();
		$this->middleware('guest')->except('logout');
	}
```

ログイン画面のエラー表示はこんな感じ
英語
![img_20190612le.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/314532/882334b8-b6fb-f615-1e84-0d5a7ad6a349.png)

日本語
![img_20190612lj.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/314532/b1552d4f-7d0c-2b65-7550-4c4262f70030.png)


###PasswordResetやEmailVerifyで送信される文面の多言語化

文面定義ファイルの用意

```resources/lang/en/password_reset.php
<?php
return [
    'greeting' => 'Hello!',
    'salutation' => '',
    'subject' => 'Reset Password Notification',
    'line1' => 'You are receiving this email because we received a password reset request for your account.',
    'line2' => 'This password reset link will expire in :count minutes.',
    'line3' => 'If you did not request a password reset, no further action is required.',
    'action' => 'Reset Password'
];
```

```resources/lang/en/email_verify.php
<?php
return [
    'greeting' => 'Hello!',
    'salutation' => '',
    'subject' => 'Verify Email Address' ,
    'line1' => 'Please click the button below to verify your email address.',
    'line2' => 'If you did not create an account, no further action is required.',
    'action' => 'Verify Email Address'
];
```

```resources/lang/ja/password_reset.php
<?php
return [
    'greeting' => 'ご利用ありがとうございます。',
    'salutation' => '',
    'subject' => 'パスワードリセットリクエストを受け付けました',
    'line1' => 'パスワードリセットのリクエストがありましたのでメッセージを送信しました。',
    'line2' => '本メール発行から :count 分以内に実行しないと上記のリンクは無効となります。',
    'line3' => 'もしこのメールに覚えが無い場合は破棄してください。',
    'action' => 'リセット開始'
];
```

```resources/lang/ja/email_verify.php
<?php
return [
    'greeting' => 'ご登録ありがとうございます。',
    'salutation' => '',
    'subject' => '本登録メール' ,
    'line1' => '以下の認証リンクをクリックして本登録を完了させてください。',
    'line2' => 'もしこのメールに覚えが無い場合は破棄してください。',
    'action' => 'メールアドレスを認証する'
];
```

文面上書きの定義

```terminal
$ php artisan make:notification PasswordResetMultiLang
$ php artisan make:notification EmailVerifyMultiLang
```
ここで自動生成されるコードはNotification継承になってる為元々呼ばれるクラスの継承に差し替えて
toMail()関数のみを上書きする（Notification継承でメソッドを丸々コピーで実装してる人が多いのはなぜだろう？）

<font color="Red">※※※Laravel6.x系ではLang::getFromJson()はLang::get()に変更※※※</font>

```app/Notifications/PasswordResetMultiLang.php
<?php
namespace App\Notifications;

use Illuminate\Auth\Notifications\ResetPassword;
use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Support\Facades\Lang;

class ResetPasswordMultiLang extends ResetPassword
{
    public function toMail($notifiable)
    {
        if (static::$toMailCallback) {
            return call_user_func(static::$toMailCallback, $notifiable, $this->token);
        }
        $mailMessage = new MailMessage;
        $mailMessage->greeting = Lang::getFromJson('password_reset.greeting');
        return $mailMessage
            ->subject(Lang::getFromJson('password_reset.subject'))
            ->line(Lang::getFromJson('password_reset.line1'))
            ->action(Lang::getFromJson('password_reset.action'), url(config('app.url').route('password.reset', ['token' => $this->token, 'email' => $notifiable->getEmailForPasswordReset()], false)))
            ->line(Lang::getFromJson('password_reset.line2', ['count' => config('auth.passwords.users.expire')]))
            ->line(Lang::getFromJson('password_reset.line3'));
    }
}
```

```app/Notifications/EmailVerifyMultiLang.php
<?php
namespace App\Notifications;

use Illuminate\Auth\Notifications\VerifyEmail;
use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Support\Facades\Lang;

class VerifyEmailMultiLang extends VerifyEmail
{
    public function toMail($notifiable)
    {
        $verificationUrl = $this->verificationUrl($notifiable);
        if (static::$toMailCallback) {
            return call_user_func(static::$toMailCallback, $notifiable, $verificationUrl);
        }
        $mailMessage = new MailMessage;
        $mailMessage->greeting = Lang::getFromJson('email_verify.greeting');
        return $mailMessage
            ->subject(Lang::getFromJson('email_verify.subject'))
            ->line(Lang::getFromJson('email_verify.line1'))
            ->action(Lang::getFromJson('email_verify.action'), $verificationUrl)
            ->line(Lang::getFromJson('email_verify.line2'));
    }
}
```

呼び出しの上書き

```diff:app/User.php
<?php
namespace App;
...
+use App\Notifications\ResetPasswordMultiLang;
+use App\Notifications\VerifyEmailMultiLang;

class User extends Authenticatable implements MustVerifyEmailContract
{
    ...
+    public function sendEmailVerificationNotification()
+    {
+        $this->notify(new VerifyEmailMultiLang);
+    }
+    public function sendPasswordResetNotification($token)
+    {
+        $this->notify(new ResetPasswordMultiLang($token));
+    }
}
```
EmailVerifyの有効かに関しては以下を参照
[Laravel：Email Verification（メールアドレスの確認）を使う](https://qiita.com/usaginooheso/items/d965f95191739f9335e8)

####受信メールのイメージ
パスワードリセット
英語
![img_20190612re.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/314532/6acd08c7-b805-0fa0-044a-df453fb28510.png)

日本語
![img_20190612rj.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/314532/fd338c64-341f-3d0b-ce49-9e4c0305f65d.png)

メールアドレス確認
英語
![img_20190612ve.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/314532/1d18d515-6e91-600e-c072-428df0b29f64.png)

日本語
![img_20190612vj.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/314532/ea4bd3d7-efb5-e97a-3273-5017f9463b6a.png)


※上記言語設定ファイルのsalutationの項目を書いて$mailMessage->salutationに値を設定すればRegards, Laravelの部分も変えられるけれど改行とか色々面倒だったのでそのままとした