【Laravel7でユーザー認証_2】ユーザー認証を日本語化

# はじめに
[【Laravel7でユーザー認証_1】基本のき](https://qiita.com/crosawassant/items/bf3982666b6333bcb8c8) の手順で、ユーザー認証（ユーザー登録・ログイン）ができるサイトが完成しましたが、デフォルトでは英語なので、日本語化する手順をまとめます。

# 環境
XAMPP環境でLaravelが使えるように設定してあります。

- Windows10 Pro 64bit
- PHP 7.3.18
- Laravel 7.12.0
- MariaDB 10.1.32

#Laravelプロジェクトの日本語化
ロケールやタイムゾーンの設定を行います。

## タイムゾーン
```diff:config/app.php
-'timezone' => 'UTC',
+'timezone' => 'Asia/Tokyo',
```

## ロケール
```diff:config/app.php
-'locale' => 'en',
+'locale' => 'ja',
```

```diff:config/app.php
-'faker_locale' => 'en_US',
+'faker_locale' => 'ja_JP',
```
※faker_localeはダミーデータ用のロケール

【注意】ここで、同じように「en」となっている `'fallback_locale' => 'en',` も直したくなりますが、`fallback_locale` は「言語フォルダに対応するロケールの言語がない場合に使用される言語」の設定なので、「en」のままにしておきます。

#日本語の言語ファイルをインストール
Laravel公式サイトから、日本語の言語ファイルをインストールします。
プロジェクトのルートディレクトリで、以下のコマンドを順番に実行します。

```:インストーラのダウンロード
$ php -r "copy('https://readouble.com/laravel/7.x/ja/install-ja-lang-files.php', 'install-ja-lang.php');"
```

```:インストーラを実行
$ php -f install-ja-lang.php
```

```:インストーラを削除
$ php -r "unlink('install-ja-lang.php');"
```

実行すると、`/resources/lang/ja` というディレクトリができます。
中身は`auth.php`、`passwords.php`、`pagination.php`、`validation.php`の4ファイルです。

このうち、`passwords.php`について一部不足している分を追加します。

```resources/lang/ja/password.php
return [
    'reset' => 'パスワードをリセットしました。',
    'sent' => 'パスワードリセットメールを送信しました。',
    'token' => 'このパスワードリセットトークンは無効です。',
    'user' => 'メールアドレスに一致するユーザーは存在していません。', //ここだけダブルクォートが気持ち悪いのでシングルクウォートに変更
    'throttled' => 'しばらく待ってから再度お試しください。', //追加
];
```

その他のファイルについても、内容を確認して好みの日本語の表現に変更できます。
例えば、```pagination.php```では「&laquo; 前」という表現になっていますが、「&laquo; 前へ」とした方がわかりやすそうです。

なお、コマンドラインでうまくインストールできない場合は、手動で各ファイルを作成しても大丈夫です。それぞれの内容は、Laravel公式サイトから確認できます。
- https://readouble.com/laravel/7.x/ja/auth-php.html
- https://readouble.com/laravel/7.x/ja/passwords-php.html
- https://readouble.com/laravel/7.x/ja/pagination-php.html
- https://readouble.com/laravel/7.x/ja/validation-php.html


#Viewの日本語化

日本語の言語ファイルが準備されているのはバリデーション部分のみなので、ログイン画面や登録画面の表示は英語のままです。

登録画面（http://127.0.0.1:8000/register） のviewを見てみると、

```html:/resources/views/auth/register.blade.php
<div class="card-header">{{ __('Register') }}</div>
```

このように、`{{__('Register')}}`となっている部分が、閲覧画面上では「Register」と表示されています。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/262236/2ccb405d-6673-dc53-99d7-e67140c423fe.png" width="600">


ここを直接

```html:/resources/views/auth/register.blade.php
<div class="card-header">ユーザー登録</div>
```

としてしまうのも手っ取り早く簡単ですが、view内で`__()`という翻訳キーが指定してある部分は、言語ファイルを用意すれば指定の言語に変換されます。

`/resources/lang/` の中に、`ja.json` を作成し、**キー: 翻訳文字列** の形式でキーに対応する翻訳内容を記載します。

```/resources/lang/ja.json
{
    "Register": "ユーザー登録"
}
```

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/262236/d4f7dfee-a6d3-3943-80ef-f4b636232ee6.png" width="600">

`ja.json`で指定したことで、同じ「Register」というキーを使っている登録ボタン部分やヘッダのメニュー部分も日本語に翻訳されました。

名前やメールアドレスなども、同じようにja.jsonに追記することで日本語化されていきます。
2つ以上のキーを登録する場合は、それぞれの組み合わせをカンマで区切って指定します。
ログイン画面やホーム画面など、現在存在しているすべてのviewを確認しながらキーを追加していくと、最終的には以下のようになります。

```/resources/lang/ja.json
{
    "Register": "ユーザー登録",
    "Name": "氏名",
    "E-Mail Address": "メールアドレス",
    "Password": "パスワード",
    "Confirm Password": "パスワード (確認用)",
    "Login": "ログイン",
    "Logout": "ログアウト",
    "Remember Me": "ログインしたままにする",
    "Forgot Your Password?": "パスワードを忘れた方はこちら",
    "Reset Password": "パスワード再設定",
    "Send Password Reset Link": "パスワード再設定用のリンクを送る",
    "Verify Your Email Address": "メールアドレス認証を行ってください",
    "A fresh verification link has been sent to your email address.": "ユーザー登録の確認メールを送信しました。",
    "Before proceeding, please check your email for a verification link.": "メールに記載されているリンクをクリックして、登録手続きを完了してください。",
    "If you did not receive the email,": "メールが届かない場合、",
    "click here to request another.": "こちらをクリックして再送信してください。",
    "Please confirm your password before continuing.": "続行するにはパスワードを入力してください。"
}
```

## エラーになってしまったら

`ja.json`を編集後、
>Facade\Ignition\Exceptions\ViewException
Translation file [C:\xampp\htdocs\project\resources\lang/ja.json] contains an invalid JSON structure. (View: C:\xampp\htdocs\project\resources\views\auth\passwords\email.blade.php)

このようなエラーになってしまったら、以下を確認してみてください。

- `ja.json`の最後のキーの行末にカンマがついていないか（ }で閉じる直前はカンマ不要）
- コロンやダブルクォーテーションが全角になっていないか
- 全角スペースが混入していないか 
- 各キーや文字列を、ダブルクォーテーションで囲んでいるか

## welcome画面が英語のままなのを修正

LoginやRegistのキーを`ja.json`に登録しても、welcome画面（http://127.0.0.1:8000/ ）は日本語になりません。
`welcome.blade.php`を見てみると、LoginやRegisterという文字が直接書かれているので、`{{__('Login')}}`、`{{__('Register')}}` という翻訳文字列を取得するヘルパ関数に変更します。

```html:/view/welcome.blade.php
            @if (Route::has('login'))
                <div class="top-right links">
                    @auth
                        <a href="{{ url('/home') }}">Home</a>
                    @else
                        <a href="{{ route('login') }}">{{__('Login')}}</a>

                        @if (Route::has('register'))
                            <a href="{{ route('register') }}">{{__('Register')}}</a>
                        @endif
                    @endauth
                </div>
            @endif
```

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/262236/caac5d53-2220-cecb-2ec9-e66f138f40db.png" width="600">

#バリデーション属性名の日本語化

バリデーションエラーになると「emailには、有効なメールアドレスを指定してください。」のように、バリデーション属性名が英語で表示されてしまいます。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/262236/2b799419-bdb4-3e64-710c-ba51eeeba165.png" width="600"> 

`resources/lang/ja/validation.php` の最下部にあるカスタムバリデーション属性名を追加します。

```diff:resources/lang/ja/validation.php

    /*
    |--------------------------------------------------------------------------
    | カスタムバリデーション属性名
    |--------------------------------------------------------------------------
    |
    | 以下の言語行は、例えば"email"の代わりに「メールアドレス」のように、
    | 読み手にフレンドリーな表現でプレースホルダーを置き換えるために指定する
    | 言語行です。これはメッセージをよりきれいに表示するために役に立ちます。
    |
    */

    'attributes' => [
+      "name" => "氏名",
+      "email" => "メールアドレス",
+      "password" => "パスワード",
+      "password_confirmation" => "パスワード(確認用)",
    ],
```

# 自動送信メールの日本語化

パスワードの再設定メールが英語のままなので、日本語化します。

`vendor/laravel/framework/src/Illuminate/Auth/Notifications/ResetPassword.php` を確認すると、メールのタイトルや本文の一部は以下のように指定されています。

```vendor/laravel/framework/src/Illuminate/Auth/Notifications/ResetPassword.php
        return (new MailMessage)
            ->subject(Lang::get('Reset Password Notification'))
            ->line(Lang::get('You are receiving this email because we received a password reset request for your account.'))
            ->action(Lang::get('Reset Password'), $url)
            ->line(Lang::get('This password reset link will expire in :count minutes.', ['count' => config('auth.passwords.'.config('auth.defaults.passwords').'.expire')]))
            ->line(Lang::get('If you did not request a password reset, no further action is required.'));
```

`Lang::get()` で指定されている文字列を、言語ファイルに追加します。

```diff:resources/lang/ja.json
-    "Please confirm your password before continuing.": "続行するにはパスワードを入力してください。"
+    "Please confirm your password before continuing.": "続行するにはパスワードを入力してください。",
+    "Reset Password Notification": "パスワード再設定手続きのご案内",
+    "You are receiving this email because we received a password reset request for your account.": "パスワード再設定のリクエストを受け付けました。",
+    "This password reset link will expire in :count minutes.": "このメールをお送りしてから :count 分以上経過すると、パスワード再設定リンクが無効になります。",
+    "If you did not request a password reset, no further action is required.": "このメールに心当たりがない場合や、パスワードの再設定が不要な場合は、メールを破棄してください。"
  }
```

この状態だと、まだ本文の一部に Hello! や Regards, が残ってしまっています。
この部分は、 `vendor/laravel/framework/src/Illuminate/Notifications/resources/views/email.blade.php` 内に@langで指定されています。

```vendor/laravel/framework/src/Illuminate/Notifications/resources/views/email.blade.php
@component('mail::message')
{{-- Greeting --}}
@if (! empty($greeting))
# {{ $greeting }}
@else
@if ($level === 'error')
# @lang('Whoops!')
@else
# @lang('Hello!')
@endif
@endif
```

@Langで指定されている文字列を、`ja.json` に追加します。

```diff:resources/lang/ja.json
-    "If you did not request a password reset, no further action is required.": "このメールに心当たりがない場合や、パスワードの再設定が不要な場合は、メールを破棄してください。"
+    "If you did not request a password reset, no further action is required.": "このメールに心当たりがない場合や、パスワードの再設定が不要な場合は、メールを破棄してください。",
+    "Whoops!": "エラー",
+    "Hello!": "こんにちは!",
+    "Regards": "よろしくお願いします",
+    "If you’re having trouble clicking the \":actionText\" button, copy and paste the URL below\ninto your web browser:": "\":actionText\"ボタンをクリックできない場合は、以下のURLをコピーして、ブラウザのアドレスバーに貼り付けてアクセスしてください。"
  }
```

これで、パスワード再設定のメールも日本語化できました。

##不自然な日本語の削除

実際にパスワード再設定のメールを見てみると、「Hello!」や「Regards」は無理矢理翻訳した感があります。特に、Regardsに至っては最後の半角カンマが残ってしまって不自然です。
メールテンプレートを変更することで、不自然な日本語部分が削除できます。

コマンドで、`vendor/laravel/framework/src/Illuminate/Notifications/resources/views/email.blade.php` を `/resources/views/vendor/notifications` に複製します。

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

複製した `email.blade.php` を編集します。

```diff:/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

（略）
  @if (! empty($salutation))
  {{ $salutation }}
  @else
- @lang('Regards'),<br>
  {{ config('app.name') }}
  @endif

```

#参考サイト
- [Laravelの言語を日本語に変更](https://qiita.com/mitashun/items/160784ce352cf529f853)
- [ログイン認証機能の日本語化（laravel6）](https://laraweb.net/tutorial/6949/)
- [Laravel：パスワード再発行メールを日本語化する](https://qiita.com/usaginooheso/items/9d61361d449a521a5854)