在建立多語系的系統時,常見透過 subdomain 與 first segment 方式來做為多國區分

例如: subdomain: tw.adon988.com, first segment: www.adon988.com/tw/

在 laravel 的 router 如果要建立 first segment 方式的 router ,官方的範例如下:

<?php 
Route::get('welcome/{locale}', function ($locale) {
    if (! in_array($locale, ['en', 'es', 'fr'])) {
        abort(400);
    }

    App::setLocale($locale);

    //
});

按照這方式定義 router 後,則結構會是以下樣式:

<?php 
Route::get('/{locale}/contact', xxxxx);
Route::get('/{locale}/about', xxxxx);
Route::get('/{locale}/user', xxxxx);

如何透過 router group 與 Middleware 將多語系包再一起

我們希望將 {locale} 獨立以 group 方式一次定義,在 group 裡可以分別定義出 router,以下說明作法:

首先,建立 Locale 的 Middleware

php artisan make:middleware Locale

調整 Middleware 判斷 local,在這裡我們判斷第一個 segment 預設定義多語系

locale 是預設的語系

locales 是我們支援的語系

(在這裡已經先把設定寫在 config.app )

<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;
use App;
class Locale
{
    /**
     * Handle localization
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle(Request $request, Closure $next)
    {

        $segment = $request->segment(1)??config('app.locale');

        if(!in_array($segment, config('app.locales'))){

            App::abort(404);

        }

        app()->setLocale($segment);
        
        return $next($request);
    }
}

接著,基礎的動作,把 Middleware 註冊在 app/Http/Kernel.php

protected $routeMiddleware = [
        ...
        'locale' => \App\Http\Middleware\Locale::class,
    ];

在 router 就可以將預設 prefix locale 透過 middleware 來判斷語系參數,並且 group 來管理。

Router web.php 格式如下

<?php 
Route::prefix('{locale?}')->middleware('locale')->group(function() {
    Route::get('/', [ArticlesController::class, 'index'])->name('home_lang');
});

接著,說明設定 config ,在 config/app.php 設定 locale 參數,

這裏,把參數透過 env 來管理

<?php return [
..
    'locale' => env('LOCALE', 'tw'),
    'locales' => explode(',', env('LOCALES', 'tw, cn, en')),
...

完成後,在 .env 加上參數即可

# localization
LOCALE='tw'
LOCALES='tw,cn,en'