Laravel中如何实现多语言切换_Laravel本地化多语言配置步骤【教程】

12次阅读

运行时多语言切换需将语言标识存于session并在中间件中调用app::setLocale()覆盖默认值,不能仅改config/app.php的locale;文件名须小写,PHP文件须返回数组且无bom前端切换需通过POST接口更新session并刷新页面。

Laravel中如何实现多语言切换_Laravel本地化多语言配置步骤【教程】

直接改 config/app.php 里的 locale 值不能实现运行时多语言切换——它只在应用启动时读取一次,后续请求不会自动更新。

如何让 laravel 支持运行时语言切换

核心是把语言标识存在用户可控制的位置(如 sessioncookie 或 URL 参数),并在每次请求开始前用它覆盖默认 App::setLocale()。Laravel 的本地化系统本身不拒绝动态设置,但需要你主动介入请求生命周期。

  • 推荐将语言存于 session:稳定、无需暴露在 URL 中、支持 POST 请求
  • 避免仅靠 URL 参数(如 ?lang=zh)做唯一依据,否则 API 调用或重定向后容易丢失
  • 务必在 app/http/Middleware/Localization.php(需手动创建)中调用 App::setLocale($locale),且该中间件必须放在 StartSession 之后
  • 不要在控制器里临时改 App::setLocale() 后就以为视图会自动刷新语言——它只影响后续的 __() 调用,且当前请求中已加载的翻译缓存不会重载

lang 文件结构与加载规则

Laravel 按 resources/lang/{locale}/{file}.php 查找翻译,比如 resources/lang/zh/auth.php 对应中文认证提示。注意几个关键点:

  • 文件名必须小写,Auth.phpAUTH.PHP 都不会被加载
  • 嵌套层级不影响加载,resources/lang/en/admin/dashboard.php 是合法路径,引用时用 __('admin/dashboard.welcome')
  • 若使用 __() 查找键 'auth.failed',它会依次查找:resources/lang/{current}/auth.phpresources/lang/en/auth.php(fallback)→ 报错(如果 fallback_locale 也没定义该键)
  • PHP 文件必须返回 Array,不能有 echo/print、不能含 BOM 头,否则整个语言包加载失败且无提示

前端切换语言并持久化到后端

前端点击切换语言,本质是向后端发起一次状态变更请求,而不是单纯改前端变量。常见错误是只改了 URL 参数或 localStorage,却没通知 Laravel 更新 session 中的语言标识。

  • 提供一个 POST 接口,例如 POST /locale,接收 locale=zh,然后执行:
    session(['locale' => $request->locale]);
  • 确保该接口受 web 中间件保护(以启用 session),且 csrf Token 正确传递
  • 前端可配合 axios.post('/locale', {locale: 'ja'}) + 页面 reload,或用 window.location.reload() 确保新 locale 生效
  • 不要依赖 javaScript 动态替换页面文本——这绕过了 Laravel 的翻译机制,无法享受缓存、fallback、参数插值(如 __('welcome', ['name' => $user->name]))等特性

常见报错和静默失效场景

多语言出问题往往没有明显报错,而是文本始终显示英文或空字符串。排查优先看这几处:

  • config/app.phpfallback_locale 设为 'en',但 resources/lang/en/ 下缺少对应文件(如缺 validation.php),会导致 __('validation.required') 返回空字符串而非 key 本身
  • 使用 trans_choice() 时传入非整数(如字符串 "1"),Laravel 不会报错但可能选错复数形式;务必确保第二个参数是 (int)
  • Artisan 命令中语言默认是 en,即使 session 里有 locale —— 因为命令行无 session。需显式调用 App::setLocale('zh')
  • Blade 中写 {{ __('messages.hello') }} 没问题,但若写成 {{ trans('messages.hello') }},而 trans() 是旧版辅助函数(Laravel 9+ 已弃用),可能在某些环境下未定义

真正麻烦的不是配置步骤,而是语言状态在 session、URL、cookie、中间件、缓存之间如何同步——稍有遗漏,就会出现「明明改了 locale,但按钮文字还是英文」这类问题。盯住 App::getLocale() 在请求不同阶段的返回值,比反复检查翻译文件更有效。

text=ZqhQzanResources