Laravel 5.6多语言本地化路由分组实现方法咨询
嘿,我来帮你搞定Laravel 5.6里多语言路由分组的问题,针对你提到的前缀路由和域名路由两种场景,我给你详细的可落地实现示例,顺便也提下非前缀参数的处理方式:
一、前缀路由(如 http://website.com/en)
这种方式是最常见的多语言路由方案,通过URL前缀区分语言版本,步骤如下:
1. 先配置支持的语言
打开config/app.php,设置默认语言和 fallback 语言,还可以新增支持的语言列表方便后续验证:
'locale' => 'zh-CN', // 默认语言 'fallback_locale' => 'en', // fallback语言 'available_locales' => ['en', 'zh-CN'], // 支持的语言列表
2. 创建语言处理中间件
生成一个SetLocale中间件来统一处理语言设置:
php artisan make:middleware SetLocale
在app/Http/Middleware/SetLocale.php里编写逻辑:
<?php namespace App\Http\Middleware; use Closure; use Illuminate\Support\Facades\App; class SetLocale { public function handle($request, Closure $next) { // 获取路由中的lang参数,若不存在则用默认语言 $lang = $request->route('lang') ?? config('app.locale'); // 验证语言是否在支持列表中,不在则用fallback语言 $availableLocales = config('app.available_locales'); if (!in_array($lang, $availableLocales)) { $lang = config('app.fallback_locale'); } App::setLocale($lang); return $next($request); } }
然后在app/Http/Kernel.php的$routeMiddleware里注册这个中间件:
protected $routeMiddleware = [ // ... 其他中间件 'setlocale' => \App\Http\Middleware\SetLocale::class, ];
3. 编写前缀路由分组
在routes/web.php里创建带前缀的路由分组,同时处理默认语言的情况:
// 带语言前缀的路由分组 Route::prefix('{lang}')->middleware('setlocale')->group(function () { Route::get('/', function () { return view('welcome'); })->name('home'); // 这里可以添加其他需要本地化的路由,比如: Route::get('/about', 'AboutController@index')->name('about'); }); // 默认语言路由(不带前缀,比如 http://website.com/) Route::middleware('setlocale')->group(function () { Route::get('/', function () { return view('welcome'); })->name('home.default'); // 对应其他默认语言的路由 Route::get('/about', 'AboutController@index')->name('about.default'); });
这样用户访问http://website.com/en就会切换到英文,访问http://website.com/则用默认的中文。
4. 视图中生成本地化路由
在Blade视图里生成带语言前缀的路由:
<a href="{{ route('home', ['lang' => 'en']) }}">English</a> <a href="{{ route('home', ['lang' => 'zh-CN']) }}">中文</a>
二、域名路由(如 http://en.website.com)
这种方式通过子域名区分语言,适合需要独立域名的多语言站点,步骤如下:
1. 复用语言配置和调整中间件
前面配置的config/app.php可以直接复用,只需要修改SetLocale中间件的语言提取逻辑,从域名中获取lang参数:
修改app/Http/Middleware/SetLocale.php的handle方法:
public function handle($request, Closure $next) { // 从域名中获取lang参数 $lang = $request->route('lang') ?? config('app.locale'); $availableLocales = config('app.available_locales'); if (!in_array($lang, $availableLocales)) { $lang = config('app.fallback_locale'); } App::setLocale($lang); return $next($request); }
2. 编写域名路由分组
在routes/web.php里用domain方法创建路由分组:
// 带语言子域名的路由分组 Route::domain('{lang}.website.com')->middleware('setlocale')->group(function () { Route::get('/', function () { return view('welcome'); })->name('home.subdomain'); Route::get('/about', 'AboutController@index')->name('about.subdomain'); }); // 默认域名路由(比如 http://website.com/) Route::domain('website.com')->middleware('setlocale')->group(function () { Route::get('/', function () { return view('welcome'); })->name('home.main'); Route::get('/about', 'AboutController@index')->name('about.main'); });
注意:你需要在服务器配置(比如Nginx)里设置通配符子域名解析,确保*.website.com指向你的Laravel项目。
3. 视图中生成域名路由
在Blade视图里生成子域名路由:
<a href="{{ route('home.subdomain', ['lang' => 'en']) }}">English (en.website.com)</a> <a href="{{ route('home.subdomain', ['lang' => 'zh-CN']) }}">中文 (zh-CN.website.com)</a>
三、非前缀参数的处理方式(如 http://website.com?lang=en)
如果不想用前缀或域名,而是通过查询参数传递语言,只需要调整中间件逻辑,不需要修改路由结构:
修改SetLocale中间件的handle方法:
public function handle($request, Closure $next) { // 从查询参数获取lang,若不存在则用默认语言 $lang = $request->query('lang') ?? config('app.locale'); $availableLocales = config('app.available_locales'); if (!in_array($lang, $availableLocales)) { $lang = config('app.fallback_locale'); } App::setLocale($lang); return $next($request); }
然后给所有路由加上setlocale中间件即可,用户访问http://website.com?lang=en就会切换到英文。
内容的提问来源于stack exchange,提问作者Andreas Hunter

