前回に作成したLaravelの日本語のリポジトリ(Laravel 5.5)。今回はその作成の仕方を説明します。ほとんどは、Laravel 5.4のときと同じですが、いくつか違いがあります。
コマンドの実行
まずは、以下のcomposerのコマンドを実行します。
composer create-project --prefer-dist laravel/laravel larajapan "5.5.*"
上で使用されているコマンドの引数は、
--prefer-dist laravel/laravel
https://packagist.org/packages/laravel/laravelからパッケージをダウンロードすることを指示します。
larajapan
パッケージのダウンロード先。その名前でディレクトリを作成します。このディレクトリ名は、先のコマンドラインで違う名前を指定可能であるし、実行完了してから改名も可能です。
5.5.*
パッケージのバージョンを指定。ここでは、laravelの5.5を使用します。マイナーバージョンを指定したいなら、5.5.40のように指定します。
実行すると、パッケージに含まれるファイル、さらにパッケージが依存するパッケージのファイルが多数ダウンロードされ少々時間がかかります。
最終的には、実行したディレクトリのもとにlarajapanのディレクトリが作成され、ダウンロードされたファイルが収納されます。
larajapan ├── app/ ├── bootstrap/ ├── config/ ├── database/ ├── public/ ├── resources/ ├── routes/ ├── storage/ ├── tests/ ├── vendor/ ├── artisan ├── composer.json ├── composer.lock ├── package.json ├── phpunit.xml ├── readme.md ├── server.php └── webpack.mix.js
次に、ユーザー認証のためのファイル作成を以下の実行で行います。
php artisan make:auth
この実行により、resources/viewsのディレクトリにおいて、すでにインストールされている以下のコントローラで使用されるbladeファイルが作成されます。
app/Http/Controllers ├── Auth/ │ ├── ForgotPasswordController.php(パスワードのリセットのリンク送信画面) │ ├── LoginController.php(ログイン画面) │ ├── RegisterController.php(会員登録画面) │ └── ResetPasswordController.php(パスワードリセット画面) ├── Controller.php └── HomeController.php(ログイン後のホーム画面)
最後に以下のコマンドを実行して、先のパスワードのリセットのリンク送信画面から発行されるEメールで使用されるHTMLのテンプレートを作成作成します。
php artisan vendor:publish
5.4と違って、上の実行は以下のような選択が出てきますが、0を選択してすべてをインストールします。
Which provider or tag's files would you like to publish?: [0] Publish files from all providers and tags listed below [1] Provider: Fideloper\Proxy\TrustedProxyServiceProvider [2] Provider: Illuminate\Mail\MailServiceProvider [3] Provider: Illuminate\Notifications\NotificationServiceProvider [4] Provider: Illuminate\Pagination\PaginationServiceProvider [5] Provider: Laravel\Tinker\TinkerServiceProvider [6] Tag: laravel-mail [7] Tag: laravel-notifications [8] Tag: laravel-pagination > 0 Copied Directory [/vendor/laravel/framework/src/Illuminate/Notifications/resources/views] To [/resources/views/vendor/notifications] Copied Directory [/vendor/laravel/framework/src/Illuminate/Pagination/resources/views] To [/resources/views/vendor/pagination] Copied File [/vendor/fideloper/proxy/config/trustedproxy.php] To [/config/trustedproxy.php] Copied Directory [/vendor/laravel/framework/src/Illuminate/Mail/resources/views] To [/resources/views/vendor/mail] Copied File [/vendor/laravel/tinker/config/tinker.php] To [/config/tinker.php] Publishing complete.
日本語化
さて、ここからが日本語化の作業です。
まず、config/app.phpの編集から。
                                                                                                                                                                                                                                                                                                                                                   
...
    'timezone' => 'UTC',                                                                                                                                                                                                                                                                                                               
                                                                                                                                                                                              
    'locale' => 'en',
...
を
                                                                                                                                                                                                                                                                                                                                                   
...
    'timezone' => 'Asia/Tokyo',                                                                                                                                                                                                                                                                                                               
                                                                                                                                                                                              
    'locale' => 'ja',
...
と変えて保存します。
timezone
これは、通常、プログラム内の日時設定のタイムゾーンとして使用されるもので、PHPの以下の関数で使用されます。
ここで設定すれば、後はLaravelが面倒みてくれます。
日本時間の場合は、Aisa/Tokyoの設定だけで十分。
locale
resources/langで言語のファイルが以下のように存在します。これらは、Laravelのプロジェクトでバリデーションのエラーメッセージなどを定義しています。
resources/lang
└── en/
    ├── auth.php
    ├── pagination.php
    ├── passwords.php
    └── validation.php
デフォルトの設定では、英語のenのディレクトリしかありません。日本語の翻訳を作成するには、上で設定したjaと同じ名前のディレクトリをそこに作成します。以下の実行でディレクトリごとコピーしてください。
$ cp -pr en ja
バリデーションに関しては、見米氏のバリデーション(1)Validatorファサードのextend を参照してください。
今回は、新しく追加されたバリデーションの以下のエントリーもあります。
after_or_equal
before_or_equal
次は、ユーザー認証画面などで使用されるブレードファイルの翻訳です。
私のLaravelの日本語レポジトリでは、以下は、すべて翻訳してあります。
resources/views ├── auth │ ├── login.blade.php │ ├── passwords │ │ ├── email.blade.php │ │ └── reset.blade.php │ └── register.blade.php ├── errors │ └── 404.blade.php ├── home.blade.php ├── layouts │ └── app.blade.php ├── vendor │ ├── mail │ │ ├── html │ │ │ ├── button.blade.php │ │ │ ├── footer.blade.php │ │ │ ├── header.blade.php │ │ │ ├── layout.blade.php │ │ │ ├── message.blade.php │ │ │ ├── panel.blade.php │ │ │ ├── promotion │ │ │ │ └── button.blade.php │ │ │ ├── promotion.blade.php │ │ │ ├── subcopy.blade.php │ │ │ ├── table.blade.php │ │ │ └── themes │ │ │ └── default.css │ │ └── markdown │ │ ├── button.blade.php │ │ ├── footer.blade.php │ │ ├── header.blade.php │ │ ├── layout.blade.php │ │ ├── message.blade.php │ │ ├── panel.blade.php │ │ ├── promotion │ │ │ └── button.blade.php │ │ ├── promotion.blade.php │ │ ├── subcopy.blade.php │ │ └── table.blade.php │ ├── notifications │ │ └── email.blade.php │ └── pagination │ ├── bootstrap-4.blade.php │ ├── default.blade.php │ ├── semantic-ui.blade.php │ ├── simple-bootstrap-4.blade.php │ └── simple-default.blade.php └── welcome.blade.php
5.4と比べて異なるのは、paginationにsemantic-ui.blade.phpが追加されています。errorsのフォルダーは例として追加しました。
パスワードリセットで送信されるEメールの翻訳
ここまで来ても、残念ながら、パスワードを忘れたときに送信される、パスワードリセットを含むEメールの内容がまだ翻訳されていません。なぜなら、本文がハードコードされているからです。
これはちょっと頭をひねりましたが、多分以下が最小の変更で対応できると思います。
まず、
vendor/laravel/framework/src/Illuminate/AuthのディレクトリからResetPassword.phpとCanResetPassword.phpのファイルを以下の場所にコピーします。
app/Auth
├── Notifications/
│   └── ResetPassword.php
└── Passwords/
    └── CanResetPassword.php
次に、以下のようにファイルを編集します。app/User.phpのファイルも変更必要です。
namespace App\Auth\Notifications;                                                                                                                                                             
                                                                                                                                                                                              
use Illuminate\Notifications\Notification;                                                                                                                                                    
use Illuminate\Notifications\Messages\MailMessage;                                                                                                                                            
                                                                                                                                                                                              
class ResetPassword extends Notification                                                                                                                                                      
{                  
...
    /**                                                                                                                                                                                       
     * Build the mail representation of the notification.                                                                                                                                     
     *                                                                                                                                                                                        
     * @param  mixed  $notifiable                                                                                                                                                             
     * @return \Illuminate\Notifications\Messages\MailMessage                                                                                                                                 
     */                                                                                                                                                                                       
    public function toMail($notifiable)                                                                                                                                                       
    {    
        return (new MailMessage)
            ->subject('パスワードリセット')
          ->greeting('パスワードリセット')
            ->line('パスワードリセットリンクの送信のリクエストがありました。')
            ->action('リセットパスワード', url(config('app.url').route('password.reset', $this->token, false)))
            ->line('リクエストされていなかったら、無視してください。');                                                                                                          
    }     
}
namespace App\Auth\Passwords;                                                                                                                                                                 
                                                                                                                                                                                              
use App\Auth\Notifications\ResetPassword as ResetPasswordNotification;                                                                                                                        
                                                                                                                                                                                              
trait CanResetPassword                                                                                                                                                                        
{                                                                                                                                                                                             
    /**                                                                                                                                                                                       
     * Get the e-mail address where password reset links are sent.                                                                                                                            
     *                                                                                                                                                                                        
     * @return string                                                                                                                                                                         
     */                                                                                                                                                                                       
    public function getEmailForPasswordReset()                                                                                                                                                
    {                                                                                                                                                                                         
        return $this->email;                                                                                                                                                                  
    }                                                                                                                                                                                         
                                                                                                                                                                                              
    /**                                                                                                                                                                                       
     * Send the password reset notification.                                                                                                                                                  
     *                                                                                                                                                                                        
     * @param  string  $token                                                                                                                                                                 
     * @return void                                                                                                                                                                           
     */                                                                                                                                                                                       
    public function sendPasswordResetNotification($token)                                                                                                                                     
    {                                                                                                                                                                                         
        $this->notify(new ResetPasswordNotification($token));                                                                                                                                 
    }                                                                                                                                                                                         
}                                                                                                                                                                                             
         
                                                                                                                                                                                              
namespace App;                                                                                                                                                                                
                                                                                                                                                                                              
use Illuminate\Notifications\Notifiable;                                                                                                                                                      
use Illuminate\Foundation\Auth\User as Authenticatable;                                                                                                                                       
use App\Auth\Passwords\CanResetPassword;                                                                                                                                                      
                                                                                                                                                                                              
class User extends Authenticatable                                                                                                                                                            
{                                                                                                                                                                                             
    use Notifiable;                                                                                                                                                                           
    use CanResetPassword;                                                                                                                                                                     
...                         
認証のroutesの設定
日本語化とは関係ないですが、私がこうした方がわかりやすいと思ったことです。
オリジナルのroutes.phpは、
Route::get('/', function () {
    return view('welcome');
});
Auth::routes();
Route::get('/home', 'HomeController@index');
とシンプルですが、Auth::routes()で認証のrouteが隠されてしまって不透明。
ということで、私のLaravelの日本語レポジトリでは、以下のように編集しました。
// 以下は、Auth::routes()の中身を移したもの。将来において変更が可能なように                                                                                                                   
                                                                                                                                                                                              
// Authentication Routes...
Route::get('login', 'Auth\LoginController@showLoginForm')->name('login');
Route::post('login', 'Auth\LoginController@login');
Route::post('logout', 'Auth\LoginController@logout')->name('logout');
// Registration Routes...
Route::get('register', 'Auth\RegisterController@showRegistrationForm')->name('register');
Route::post('register', 'Auth\RegisterController@register');
// Password Reset Routes...
Route::get('password/reset', 'Auth\ForgotPasswordController@showLinkRequestForm')->name('password.request');
Route::post('password/email', 'Auth\ForgotPasswordController@sendResetLinkEmail')->name('password.email');
Route::get('password/reset/{token}', 'Auth\ResetPasswordController@showResetForm')->name('password.reset');
Route::post('password/reset', 'Auth\ResetPasswordController@reset');                                                                                                                
                                                                                                                                                                                              
Route::get('/home', 'HomeController@index');  
Debugbar
このバージョンから、開発に非常に有用なDebugbarがdevの環境だけにインストールできるようになりました。プロダクションの環境にインストールする必要はありません。
以下の実行により、composer.jsonが編集されvendorのディレクトリにライブラリがインストールされます。
$ composer require barryvdh/laravel-debugbar --dev
また、Laravel 5.5のauto-discoveryの機能により、以前のようにconfig/app.phpで設定の必要もありません。
しかし、今までコード内で、debug()を使用していてそれを残しておくと、プロダクションにおいて関数未定義のエラーが出ます。防ぐには、以下のように、bootstrap/app.phpで空の関数を定義しておきます。
/*
|--------------------------------------------------------------------------
| Create The Application
|--------------------------------------------------------------------------
|
| The first thing we will do is create a new Laravel application instance
| which serves as the "glue" for all the components of Laravel, and is
| the IoC container for the system binding all of the various parts.
|
*/
$app = new Illuminate\Foundation\Application(
    realpath(__DIR__.'/../')
);
// no-dev でエラーにならないように定義
if (!function_exists('debug')) {
    function debug($value)
    {
    }
}
..
その他
インストールにおいて経験した問題として、
php artisan migrate
を実行したときに、以下のエラーとなりました。
     [Illuminate\Database\QueryException]
    SQLSTATE[42000]: Syntax error or access violation: 1071 Specified key was too long; max key length is 767 bytes (SQL: alter table users add unique users_email_unique(email))
    [PDOException]
    SQLSTATE[42000]: Syntax error or access violation: 1071 Specified key was too long; max key length is 767 bytes 
これは、使用しているデータベースがMariaDBで10.2.2のバージョンより古いか、あるいはMySQLで5.7.7より古いときに起こるエラーです。Laravelは5.4より、絵文字対応のutf8mb4のエンコーディングがデフォルトとなりました。
古いバージョンを使用する場合(大半がそうでは?)は、以下の変更が必要となります。日本語のレポにはこの変更が含まれています。
namespace App\Providers;                                                                                                                                                                                           
                                                                                                                                                                                                                   
use Illuminate\Support\ServiceProvider;                                                                                                                                                                            
use Illuminate\Support\Facades\Schema;                                                                                                                                                                             
                                                                                                                                                                                                                   
class AppServiceProvider extends ServiceProvider                                                                                                                                                                   
{                                                                                                                                                                                                                  
    /**                                                                                                                                                                                                            
     * Bootstrap any application services.                                                                                                                                                                         
     *                                                                                                                                                                                                             
     * @return void                                                                                                                                                                                                
     */                                                                                                                                                                                                            
    public function boot()                                                                                                                                                                                         
    {                                                                                                                                                                                                              
        Schema::defaultStringLength(191);                                                                                                                                                                          
    }                                                                                                                                                                                                              
                                                                                                                                                                                                                   
    /**                                                                                                                                                                                                            
     * Register any application services.                                                                                                                                                                          
     *                                                                                                                                                                                                             
     * @return void                                                                                                                                                                                                
     */                                                                                                                                                                                                            
    public function register()                                                                                                                                                                                     
    {                                                                                                                                                                                                              
        //                                                                                                                                                                                                         
    }                                                                                                                                                                                                              
}   
メルマガ購読の申し込みはこちらから。        
        