質問: お世話になっております。 現在、Laravelで一通りのシステムを開発したあとで、 第一階層のディレクトリに独自の言語のURLを入れたいと思っています。 ``` Route::group(['prefix' => '{lang}'], function () { // <= 追加 // <= 既存のコードたち // <= 既存のコードたち // <= 既存のコードたち }); // <= 追加 ``` その場合は、全クラスのメソッドの引数を変更する必要がありますでしょうか? またそれを回避したいのですが、方法が分かっておらず、ご教示いただけますと幸いです。 よろしくお願いいたします。
回答: 概要 == エラーが出る原因は * ルーティングされるメソッドに `$lang` が定義されていない からではなく * ルーティングリンク生成時に `{lang}` が含まれるほうを利用している * にも関わらず、`["lang" => $lang]` をパラメータに渡していない が原因かと思われます。 実装方針 ==== #### ミドルウェアの作成 ``` class LocaleMiddleware { protected $possibleLocales = ['ja', 'en', 'cn', 'ru']; public function handle(Request $request, Closure $next) { $route = $request->route(); $lang = $route->parameter('lang'); if ($lang !== null) { // デフォルトロケールまたは存在しないロケールならフォールバック if ( $lang === config('app.fallback_locale') || !in_array($lang, $this->possibleLocales, true) ) { return redirect()->route(substr($route->getName(), 5)); } // ロケールの設定 App::setLocale($lang); } return $next($request); } } ``` #### ルーティング定義 ルーティング定義は以下のようになります。 ``` // デフォルト言語 Route::namespace('App\Http\Controllers') ->group(base_path('routes/localized.php')); // 各言語 Route::namespace('App\Http\Controllers') ->middleware(LocaleMiddleware::class) ->prefix('{lang}') ->as('lang.') ->group(base_path('routes/localized.php')); ``` アプリケーションの実際の定義は `routes/localized.php` に書いてください。 #### ヘルパー関数の作成 以下のようなヘルパー関数を適当な場所に定義してください。 ``` function route_i18n(string $name, array $params): string { $params['lang'] += App::getLocale(); return route( $params['lang'] === config('app.fallback_locale') ? $name : "lang.$name", $params ); } ``` `app/helpers.php` を作って composer.json の `autoload` の `files` に書くのがおすすめです。 ``` { "autoload": { "files": ["app/helpers.php"] } } ``` これで `route_i18n` を使って定義するのはどうでしょうか?現在表示しているページの言語にあったルーティングを暗黙的に書けます。言語を切り替えるときもそれを `$params` に渡せば、引数のほうが優先されるので問題ありません。 中身の多言語化に関しては通常どおり `__` 関数を使うだけですね。とても簡単です。