前回に作成した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の以下の関数で使用されます。

date_default_timezone_set()

ここで設定すれば、後は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.phpCanResetPassword.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()                                                                                                                                                                                     
    {                                                                                                                                                                                                              
        //                                                                                                                                                                                                         
    }                                                                                                                                                                                                              
}   
メルマガ購読の申し込みはこちらから。

By khino