Laravel多页面多语言路由:实现URL参数式全局语言切换
没问题!要让所有子页面都能通过?lang=en这类URL参数实现语言切换,完全可以用单一路由+全局中间件+辅助函数的组合来搞定,不用给每个页面单独写路由。下面是具体步骤:
1. 新增通用语言切换路由
首先在routes/web.php里加一个通用的语言切换路由,它负责接收语言参数、设置应用语言,然后跳回当前页面(自动带上语言参数):
Route::get('/switch-lang', function (\Illuminate\Http\Request $request) { // 验证传入的语言是否在配置的允许列表里 $allowedLangs = config('app.locales'); // 假设你在config/app.php里配置了locales数组,比如['en', 'zh-CN'] $lang = $request->query('lang'); if (in_array($lang, $allowedLangs)) { // 设置应用语言 app()->setLocale($lang); // 把语言存在会话里,方便后续请求读取 session()->put('locale', $lang); } // 跳回之前的页面,并且自动带上lang参数 return redirect()->back()->withInput($request->query()); })->name('switch.lang');
2. 全局中间件自动同步语言设置
接下来创建一个全局中间件,让所有请求都自动检测URL里的lang参数,或者读取会话里的语言设置,确保应用语言始终同步:
先生成中间件:
php artisan make:middleware SetLocale
然后在app/Http/Middleware/SetLocale.php里写逻辑:
<?php namespace App\Http\Middleware; use Closure; use Illuminate\Http\Request; class SetLocale { public function handle(Request $request, Closure $next) { // 优先取URL里的lang参数 if ($request->has('lang') && in_array($request->lang, config('app.locales'))) { app()->setLocale($request->lang); session()->put('locale', $request->lang); } // 其次取会话里的语言 elseif (session()->has('locale')) { app()->setLocale(session('locale')); } // 最后用默认语言 else { app()->setLocale(config('app.fallback_locale')); } return $next($request); } }
记得把这个中间件加到app/Http/Kernel.php的$middleware数组里,让它全局生效:
protected $middleware = [ // ...其他中间件 \App\Http\Middleware\SetLocale::class, ];
3. 修改下拉菜单的链接生成逻辑
现在要让你的下拉菜单里的每个选项,点击后跳转到当前页面+对应lang参数。可以写一个辅助函数来简化带语言参数的URL生成:
在app/helpers.php里新增辅助函数(如果没有这个文件,自己创建一个,然后在composer.json的autoload里加上"files": ["app/helpers.php"],之后跑composer dump-autoload):
<?php function locale_url($locale) { // 获取当前请求的URL参数 $queryParams = request()->query(); // 替换或添加lang参数 $queryParams['lang'] = $locale; // 生成带参数的当前页面URL return url()->current() . '?' . http_build_query($queryParams); }
然后在你的Blade视图里,下拉菜单的选项就可以这么写:
<select onchange="window.location.href = this.value"> <option value="{{ locale_url('en') }}" {{ app()->getLocale() == 'en' ? 'selected' : '' }}>English</option> <option value="{{ locale_url('zh-CN') }}" {{ app()->getLocale() == 'zh-CN' ? 'selected' : '' }}>中文</option> </select>
这样用户切换语言时,就会跳转到当前页面并带上?lang=xx参数,完全符合你要的/dashboard?lang=en这类格式。
4. 补充:统一默认语言的URL格式
如果用户直接访问不带lang参数的页面,中间件会自动用默认语言,也可以在视图里给默认语言的链接加上参数,确保URL统一。比如导航栏的链接可以用route('dashboard', ['lang' => app()->getLocale()])这样的方式生成。
这样一套下来,所有子页面都能通过单一路由实现语言切换,并且URL始终带语言参数,完美解决你的需求!
内容的提问来源于stack exchange,提问作者Rhaman

