Laravel：パスワード再発行メールを日本語化する



# 概要
パスワード再発行の手続きを行うと再発行URLを発行してユーザーに送信します。
このメールはそのままの状態だと中身が英語なので、これを日本語化します。

![default_pwreset_mail.png](https://qiita-image-store.s3.amazonaws.com/0/275623/c068b6a8-bc5e-d5bc-8c4b-ea83e5b19655.png)


##▼ 動作確認環境

- PHP 7.1
- Laravel 5.7



# メールの送信設定

前提として、Laravelからメール送信ができるようにしておく必要があります。
すでにできている場合はこの手順はSKIPします。

メールを送信する方法がいくつかあるので、それぞれの方法にあわせて .env を書き換えればOKです。

##▼ メールを送信する方法

- 自分でメールサーバーを稼働させる

- SMTPサーバーを使う（GoogleやYahooなど）

- Amazon SESを使う

- メールの送信はせず、ログファイルに内容を書き込む

- その他サービスを使う
    - [mailcatcher](https://mailcatcher.me/)
    - [Mailgun](https://www.mailgun.com/)など

など。
参考： :link: [Laravelのmailableクラスでメール送信を行う(5.6/5.5/5.4)[導入/入門編]](https://www.ritolab.com/entry/38#aj_7)

##- SMTPを使う（Googleの場合）

GoogleやYahoo!などのSMTPを使う方法です。
ここではGoogleの場合を書きます。


#### ①「安全性の低いアプリの許可」を有効にする
メール送信に使いたいアカウントでgoogleログインし、以下のページで有効化する
https://myaccount.google.com/lesssecureapps

####② .env を修正する

```.env
MAIL_DRIVER=smtp
MAIL_HOST=smtp.gmail.com
MAIL_PORT=587
MAIL_USERNAME=(Googleアカウント)
MAIL_PASSWORD=(Googleのパスワード)
MAIL_ENCRYPTION=tls
MAIL_FROM_ADDRESS=(Gmailアドレス)
MAIL_FROM_NAME=demo-laravel-crud
```



# メールを独自に作成する

##▼ 専用のNotification を作成する

専用のNotificationを作成します。
名前は何でも良いですが、自分で作ったものとわかりやすいようにCustomとつけます。

```
php artisan make:notification CustomResetPassword
```

##▼ CustomResetPassword.php を編集する

```diff:app/Notifications/CustomResetPassword.php

+ use Illuminate\Auth\Notifications\ResetPassword;

class CustomResetPassword extends Notification
{

+   /**
+    * The password reset token.
+    * 
+   /** @var string */
+   public $token;

(略)

    /**
     * Create a new notification instance.
     *
+    * @param  string  $token
     * @return void
     */
    public function __construct($token)
    {
+       $this->token = $token;
    }

(略)

    public function toMail($notifiable)
    {
        return (new MailMessage)
-           ->line('The introduction to the notification.')
-           ->action('Notification Action', url('/'))
-            ->line('Thank you for using our application!');
+           ->from('admin@example.com', config('app.name'))
+           ->subject('パスワード再設定')
+           ->line('下のボタンをクリックしてパスワードを再設定してください。')
+           ->action('パスワード再設定', url(config('app.url').route('password.reset', $this->token, false)))
+           ->line('もし心当たりがない場合は、本メッセージは破棄してください。');
    }


(略)
```

<details><summary>ポイント：`from()`</summary>
<font color="tomato">基本的に.envで設定した`MAIL_FROM_ADDRESS`と`MAIL_FROM_NAME`になるはずですが、個別に設定したい場合に。</font>
</detail>

<details><summary>ポイント：`$token`</summary>
<font color="tomato">パスワード再設定メールを送信する際はトークンを含んだURLを作成する必要があります。</font>
</detail>



##▼ Userモデルを編集する

`App\Notifications\CustomResetPassword` をuseしつつ、
`sendPasswordResetNotification()` というメソッドを追加します。

これにより、Illuminate/Auth/Passwords/CanResetPassword.php (:link: [コード](https://github.com/laravel/framework/blob/5.7/src/Illuminate/Auth/Passwords/CanResetPassword.php))の定義をオーバーライドします。 




```php:app/User.php

use App\Notifications\CustomResetPassword;

    /**
     * パスワード再設定メールの送信
     *
     * @param  string  $token
     * @return void
     */
    public function sendPasswordResetNotification($token)
    {
        $this->notify(new CustomResetPassword($token));
    }
```

参考： :link: readouble.com [リセットメールのカスタマイズ](https://readouble.com/laravel/5.7/ja/passwords.html#password-customization)



##▼ 動作確認

大事なところは日本語化できました。
しかし、まだ英語が残っています。

![resetpassword_mail_modified.png](https://qiita-image-store.s3.amazonaws.com/0/275623/bc165cae-7b2b-176b-b8ad-58e74875de9f.png)

フッターのあたり（If you're having trouble...）はメールのbladeテンプレートごと変更しないと日本語化できないので、それをやっていきます。

##▼ メールテンプレートをpublishする

```
php artisan vendor:publish --tag=laravel-notifications
```

すると、/resources/views/vendor/notifications にemail.blade.phpが生成されます。




##▼ email.blade.php を編集する

- 冒頭のHello!と
- Regards,（アプリ名）と
- フッターの3カ所を直します。

Regardsってしっくりくる日本語がない・・・とか思うところ色々ですが。

```diff:/resources/views/vendor/notifications/email.blade.php

(中略）
- # @lang('Hello!')
+ こんにちは。

（中略）

- @lang('Regards'),<br>{{ config('app.name') }}
+ {{ config('app.name') }}

（中略）

- @lang(
-    "If you’re having trouble clicking the \":actionText\" button, copy and paste the URL below\n".
-   'into your web browser: ',
-  [
-       'actionText' => $actionText
-   ]
- )
+ {{ $actionText }}ボタンが利用できない場合は、以下のURLをコピー＆ペーストしてブラウザから直接アクセスしてください。
[{{ $actionUrl }}]({!! $actionUrl !!})
@endcomponent
@endisset
@endcomponent

```

これで完成。

私はこの時点でエラーが出るようになりメール送信ができなくなったのですが
CSRFが原因だったようです。いったん無効化して再度有効化したら直りました。
(app/Http/kernel.phpの`\App\Http\Middleware\VerifyCsrfToken::class,`を消して再度送信試したら問題なく、その後消した行を元に戻す）



# 多言語化
私は :link: [こちら](https://qiita.com/sutara79/items/fa351a907ae5ba3a9802)  を参考にして多言語化するために、このようにしました。


```php:app/Notifications/CustomResetPassword.php
    public function toMail($notifiable)
    {
        return (new MailMessage)
            ->subject(__('Reset Password'))
            ->line(__('Click button below and reset password.'))
            ->action(__('Reset password'), url(config('app.url').route('password.reset', $this->token, false)))
            ->line(__('If you did not request a password reset, no further action is required.'));
    }
```

```html:/resources/views/vendor/notifications/email.blade.php

@component('mail::message')

{{-- Greeting --}}
@if (! empty($greeting))
# {{ $greeting }}
@else
@if ($level == 'error')
# @lang('Whoops!')
@else
# @lang(__('Hello!'))
@endif
@endif

{{-- Intro Lines --}}
@foreach ($introLines as $line)
{{ $line }}

@endforeach

{{-- Action Button --}}
@isset($actionText)
<?php
    switch ($level) {
        case 'success':
        case 'error':
            $color = $level;
            break;
        default:
            $color = 'primary';
    }
?>
@component('mail::button', ['url' => $actionUrl, 'color' => $color])
{{ $actionText }}
@endcomponent
@endisset

{{-- Outro Lines --}}
@foreach ($outroLines as $line)
{{ $line }}

@endforeach

{{-- Salutation --}}
@if (! empty($salutation))
{{ $salutation }}
@else
{{ config('app.name') }}
@endif

{{-- Subcopy --}}
@isset($actionText)
@component('mail::subcopy')
@lang(__('If you’re having trouble clicking the button above, copy and paste the URL below.'))<br>
@lang(__('into your web browser: '))
[{{ $actionUrl }}]({!! $actionUrl !!})
@endcomponent
@endisset
@endcomponent

```

```diff:ja.json
    "Hello!":"お知らせ",
    "Reset password":"パスワード再設定",
    "Click button below and reset password.": "ボタンをクリックしてパスワードを再設定してください。",
    "If you did not request a password reset, no further action is required.": "このメールに心当たりがない場合は、このまま削除してください。",
    "If you’re having trouble clicking the button above, copy and paste the URL below.":"ボタンがクリックできない場合は、下のURLをコピーしてブラウザのアドレス欄に貼り付け、直接アクセスしてください。",
    "into your web browser: ":"ブラウザでアクセス：",
```

参考： :link: readouble.com [通知の作成](https://readouble.com/laravel/5.7/ja/notifications.html#creating-notifications)


# 参考：

:link: CONSOLE DOT LOG [【Laravel5.6】インストール直後にやること３点](https://blog.capilano-fw.com/?p=289)

:link: Qiita [Laravel5.7: 日本語のパスワードリセット用のメールを送信する](https://qiita.com/sutara79/items/0ea48847f5565aacceea)