
本文详解如何在 Laravel 中持久化设置用户语言偏好,解决仅靠路由参数临时切换语言却无法跨请求生效的问题,通过自定义中间件 + Session 存储实现全局、稳定的本地化支持。
本文详解如何在 Laravel 中持久化设置用户语言偏好,解决仅靠路由参数临时切换语言却无法跨请求生效的问题,通过自定义中间件 + Session 存储实现全局、稳定的本地化支持。
在 Laravel 中实现多语言(Localization)时,一个常见误区是:仅在路由闭包中调用 App::setLocale($lang),以为这样就能“切换语言”。但该设置仅对当前 HTTP 请求生命周期有效——一旦视图渲染完成、响应返回,下一次页面访问(哪怕只是刷新)就是全新请求,语言设置即失效。
根本原因在于:Laravel 的本地化配置(如 trans()、__()、验证器提示等)依赖 App::getLocale() 的返回值,而该值默认由 config('app.locale') 决定,且每次请求需显式重置。因此,必须在每个请求开始时动态设置 locale,并确保该设置可被后续所有本地化操作识别。
✅ 正确做法是:将语言偏好持久化存储(如 Session),并通过中间件在每个请求中自动加载并应用。以下是完整实现步骤:
1. 创建语言中间件
运行命令生成中间件:
php artisan make:middleware Language
编辑 app/Http/Middleware/Language.php,在 handle() 方法中检查 Session 并设置 locale:
<?php namespace App\Http\Middleware;
use Closure;
use Illuminate\Support\Facades\App;
use Illuminate\Http\Request;
class Language
{
public function handle(Request $request, Closure $next)
{
if (session()->has('lang')) {
App::setLocale(session()->get('lang'));
}
return $next($request);
}
}
2. 注册中间件到 Web 组
打开 app/Http/Kernel.php,将 Language::class 添加至 $middlewareGroups['web'] 数组末尾(确保在 StartSession::class 之后,否则 Session 不可用):
'web' => [ \App\Http\Middleware\EncryptCookies::class, \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class, \Illuminate\Session\Middleware\StartSession::class, // ← Session 必须已启动 \Illuminate\View\Middleware\ShareErrorsFromSession::class, \App\Http\Middleware\VerifyCsrfToken::class, \Illuminate\Routing\Middleware\SubstituteBindings::class, \App\Http\Middleware\Language::class, // ✅ 添加此处 ],
3. 更新路由逻辑:写入 Session 而非仅设当前请求
修改你的语言切换路由(例如 /en、/zh),将语言代码存入 Session:
use Illuminate\Support\Facades\App;
Route::get('/{lang?}', function ($lang = null) {
// 可选:校验 lang 是否为合法语言代码(如 en/zh/es)
$availableLocales = ['en', 'zh', 'es'];
$lang = in_array($lang, $availableLocales) ? $lang : config('app.fallback_locale');
App::setLocale($lang); // 当前请求立即生效(如渲染首页时翻译内容)
session()->put('lang', $lang); // 持久化,供中间件在后续请求中读取
return view('frontend.home');
})->where('lang', '[a-zA-Z]{2}');
? 提示:建议添加正则约束 ->where('lang', '[a-zA-Z]{2}') 防止非法路径;同时加入白名单校验,避免安全风险或无效 locale 导致异常。
4. 补充建议与注意事项
-
语言切换链接示例(Blade 中):
<a>English</a> | <a>中文</a>
-
避免重复设置:无需在控制器或视图中手动调用
App::setLocale()—— 中间件已统一处理。 -
缓存影响:若启用视图缓存(
php artisan view:cache),确保语言相关视图未被静态化;推荐对多语言内容使用@lang或{{ __('key') }}动态解析。 -
SEO 友好:生产环境建议配合
hreflang标签和多域名/子目录策略(如zh.example.com),本方案作为基础 Session 级切换适用单域名场景。
通过以上三步,Laravel 将在每个请求中自动读取 Session 中的语言偏好并生效,真正实现用户级、跨页面、可持续的语言切换体验。











