__('key')是php函数,可在任意php上下文使用;@lang('key')是blade指令,仅限.blade.php文件内,且不支持直接嵌套php表达式;语言键需用:name格式占位符,json文件支持基础翻译但不支持复数等复杂语法。

Blade里用__('key')还是@lang('key')?
两者效果一致,都读当前App::getLocale()对应的语言文件,但调用时机和适用场景不同。__('key')是PHP函数,可在任意PHP上下文(包括控制器、模型、辅助函数)中使用;@lang('key')是Blade指令,仅限.blade.php文件内,且不支持直接嵌套PHP表达式(比如@lang('hello', ['name' => $user->name])会报错)。实际写法应统一用__('key', [...]),避免混淆。
语言键带变量时,为什么{{ __('welcome', ['name' => '张三']) }}不渲染?
常见原因是语言文件里没定义占位符格式。比如resources/lang/zh/messages.php必须写成:
return [
'welcome' => '欢迎 :name 登录系统!',
];而不是'欢迎 {name} 登录系统!'或'欢迎 {{ name }} 登录系统!'——Laravel只认:name这种冒号前缀语法。另外注意:如果键不存在,它不会报错,而是原样输出__('welcome', ...)字符串,容易误以为“生效了”,其实只是fallback到key本身。
切换语言后Blade里__('xxx')还是旧翻译?
根本原因不是Blade缓存,而是App::setLocale()调用太晚。Laravel在服务提供者启动阶段就加载了验证规则、日期格式等组件,它们会缓存locale。必须确保:
- 语言中间件排在
StartSession之后、路由绑定之前 - 中间件里调用
app()->setLocale(session('locale', config('app.locale'))),而非App::setLocale()(后者在Facade未完全初始化时可能无效) - 如果用了Carbon时间差(如
$post->created_at->diffForHumans()),还得在AppServiceProvider::boot()里加Carbon::setLocale(app()->getLocale())
JSON语言文件在Blade里能用吗?
能,但有隐性限制。只要把文件放在resources/lang/zh.json或resources/lang/en.json,__('welcome')就能读取。不过JSON不支持PHP数组的复数语法(如'comment' => '没有评论|有一条评论|[2,*]有 :count 条评论'),遇到复数必须用PHP文件;另外,JSON无法写注释、动态逻辑,维护大量带条件文本的项目时,很快会发现PHP数组更可控。简单提示类文案用JSON没问题,含复数、性别、上下文差异的,别硬扛。











