正确设置需在 .env 中设 app_locale=zh、app_fallback_locale=en,运行 php artisan config:clear;翻译文件置于 resources/lang/zh/ 目录下,命名如 auth.php;动态切换应在 web 中间件中通过 setuserlocale 统一设置。

怎么在 Laravel 中正确设置 APP_LOCALE 和 APP_FALLBACK_LOCALE
Laravel 的多语言不是靠写死语言代码或手动切换实现的,核心是环境配置和请求上下文的联动。必须确保 .env 里这两个值存在且合法,否则所有 __()、@lang 都会退回到英文(或报错),哪怕翻译文件全都有。
常见错误现象:__('welcome') 始终返回键名而不是翻译内容;浏览器语言是 zh-CN,但页面还是显示英文。
-
APP_LOCALE=zh_CN是错的 —— Laravel 只认zh或zh-CN(推荐用短格式zh,避免大小写/分隔符问题) -
APP_FALLBACK_LOCALE=en必须设,否则缺失翻译时直接返回空字符串,而不是兜底英文 - 改完
.env后要运行php artisan config:clear,Laravel 不会自动重载环境变量
翻译文件放哪?命名和结构为什么不能乱
Laravel 按 resources/lang/{locale}/{file}.php 查找翻译,路径和命名一旦出错,就等于没写。它不报错,只是静默失败。
使用场景:你想在 Blade 中用 {{ __('auth.failed') }},那对应文件必须是 resources/lang/en/auth.php,且数组键为 'failed' => 'These credentials do not match our records.'。
- 语言目录名必须小写,比如
zh,不能是ZH或zh-cn(除非你显式注册了该 locale) - 文件名可以是
auth.php、validation.php,也可以是自定义的common.php,但必须是 PHP 返回数组 - 嵌套层级不影响查找,
__('auth.login.title')要求auth.php里有'login' => ['title' => '...']
如何让语言随用户选择动态切换而不依赖 URL 或 Cookie 手动处理
靠改 App::setLocale() 是可行的,但容易漏掉请求生命周期中的关键节点,比如验证器、邮件生成、队列任务 —— 它们可能在另一个进程中执行,不共享当前请求的 locale 设置。
真正可靠的方式是把语言偏好存进用户 session 或数据库,并在中间件中统一设置:
- 在
app/Http/Middleware/SetUserLocale.php中调用app()->setLocale($request->user()?->locale ?? config('app.fallback_locale')) - 务必在
Kernel.php的$middlewareGroups['web']中把它放在StartSession::class之后、其他业务中间件之前 - 不要在控制器里反复调用
setLocale(),尤其别在模型事件或通知类里硬编码 —— 这会导致异步任务语言错乱
__() 函数不生效?检查这三处硬编码陷阱
最常被忽略的是:翻译函数本身没问题,但调用它的上下文已经脱离了 Laravel 的本地化机制。
常见错误现象:命令行运行 php artisan make:mail WelcomeMail,邮件里 __('hello') 显示键名;或者 Vue 组件里通过 API 拿到的文案仍是英文。
- Artisan 命令默认 locale 是
en,需在handle()开头加app()->setLocale(session('locale') ?? config('app.locale')) - API 接口不走 web 中间件组,不会触发 locale 中间件,得在控制器构造函数或方法开头手动 set
- 前端 JS 里的文案不能依赖后端
__(),要通过接口返回已翻译的字符串,或用lang.js+ JSON 包加载
复杂点在于:locale 是请求级状态,不是全局变量。任何脱离 HTTP 生命周期的操作(队列、命令、测试、Swoole 长连接),都得自己接管语言上下文。没人替你记着用户刚才选的是中文。











