推荐使用{\_\_('key')},因其为直接调用助手函数、返回翻译字符串,写法简洁且调试友好;{:lang('key')}需经模板引擎解析,多一层处理。注意key须严格匹配语言包键名(大小写敏感),且语法中不可加空格。

模板里用 {__('key')} 还是 {:lang('key')}?
两者都行,但行为有差异:{__('key')} 是助手函数,直接返回翻译后字符串;{:lang('key')} 是标签解析语法,底层也调用 lang(),但多一层模板引擎处理。实际项目中更推荐 {__('key')},写法简洁、调试时容易定位问题。
注意点:
-
{__('key')}中的key必须和语言包数组键名完全一致(大小写敏感) - 如果语言包里定义的是
'HELLO' => '你好',那必须写{__('HELLO')},写{__('hello')}会输出空字符串 - 模板中不能加空格:
{__ ('key')}或{ __( 'key' ) }都无效
控制器里用 L('key') 为什么有时不生效?
L('key') 本质是读取当前语言环境下的变量缓存,不是实时读文件。如果语言包刚改完没清缓存,或语言切换逻辑没触发成功,L() 就会返回空或旧值。
常见原因:
立即学习“PHP免费学习笔记(深入)”;
- 语言包路径不对:必须是
lang/zh-cn/common.php这类结构,且common.php返回数组,不能有输出或报错 - 配置漏了
'lang_switch_on' => true,或者'default_lang'拼错成'defaut_lang' - URL 切换语言时用了错误参数名,默认是
?lang=en-us,如果你改过'lang_detect_var'为'l',却还传lang,就切不动 -
L()在语言初始化前调用——比如在app_begin行为之前就执行了,此时语言环境还没加载
lang() 和 __('') 能否传变量当 key?
可以,但要小心拼接逻辑和注入风险。例如 {__('user_' . $status)} 在模板中会被编译为 PHP 代码,只要 $status 是可信值(如枚举字段),就没问题。
但要注意:
- 模板里不支持复杂表达式:
{__('user_' . $user['level'])}会报错,得先在控制器里拼好再 assign - 控制器中用
L($key)时,确保$key不来自用户输入且已白名单过滤,否则可能绕过语言包读取任意键 - 动态 key 无法被静态扫描工具识别,后期维护时容易漏翻新语言包中的对应项
系统变量 {$Think.lang.key} 为什么有时输出为空?
这个写法依赖 Think 系统变量的 lang 子数组,它只包含当前语言环境下已加载的语言变量。不是所有语言包内容都会自动塞进去,只有被 lang() 或 __('') 实际调用过的 key 才会出现在 $Think.lang 里。
也就是说:{$Think.lang.hello} 要求你至少在某处调过 __('hello') 或 lang('hello'),否则该 key 不在运行时缓存中,模板输出就是空。
所以别把它当“全局语言变量池”来用——它只是个快照,不是语言包镜像。



















