必须同步解决扩展文件缺失、系统locale不兼容、MO路径不规范三类硬性门槛,否则翻译永远返回原文:补全php_gettext.dll并启用扩展;Windows下用Chinese_China.65001等原生locale名;bindtextdomain须用绝对路径且目录结构为locale/zh_CN/LC_MESSAGES/messages.mo。

要在 PHP 环境中真正启用 gettext 多语言支持,不能只改 php.ini 或写个 _() 就完事。Windows 下用 phpEnv 时,必须同步解决扩展文件缺失、系统 locale 不兼容、MO 路径不规范这三类硬性门槛,否则翻译永远返回原文。
补全 php_gettext.dll 并启用扩展
phpEnv 自带的 PHP 版本(如 8.1/8.2 VC15 x64)默认不含 php_gettext.dll。光在 php.ini 里取消注释 extension=gettext 没用——文件不存在,扩展根本加载不了。
- 进入 phpEnv 对应 PHP 目录,例如
C:\phpEnv\php\php-8.2.12-Win32-vs16-x64\ext\ - 检查是否存在
php_gettext.dll;若无,去 windows.php.net 下载同版本、TS(Thread Safe)、x64 的 ZIP 包,从中提取该 DLL 放入上述ext目录 - 在 phpEnv 的“PHP 配置”界面勾选
php_gettext.dll,保存并重启 Apache/Nginx - 命令行执行
php -m | findstr gettext,有输出才表示扩展已就位
设置 Windows 原生 locale 名称
Linux 的 zh_CN.UTF-8 在 Windows 上会直接失败。PHP 的 setlocale() 是调用系统 API,必须用 Windows 控制面板里真实存在的 locale 字符串。
- 中文简体推荐用:
Chinese_China.65001(UTF-8)或Chinese_China.936(GBK) - 英文美国用:
English_United States.1252 - 务必先测试:
var_dump(setlocale(LC_ALL, 'Chinese_China.65001'));,返回false表示系统未安装该 locale - 未安装时,需进 Windows “控制面板 → 区域 → 管理 → 更改系统区域设置”,勾选对应语言并重启
-
putenv("LANG=zh_CN")在 Windows 下基本无效,可跳过
绑定绝对路径并校验 MO 文件结构
相对路径(如 "./locale")在 Web 和 CLI 下行为不一致,极易导致 gettext 找不到文件而静默 fallback 到原文。
立即学习“PHP免费学习笔记(深入)”;
- 使用绝对路径:
bindtextdomain("messages", __DIR__ . "/locale"); - 目录结构必须严格为:
locale/zh_CN/LC_MESSAGES/messages.mo(注意:LC_MESSAGES 必须全大写,小写会被忽略) - 确保
messages.mo文件非空:可用msgunfmt messages.mo反编译验证内容 - 调用顺序不能错:先
setlocale(),再bindtextdomain(),最后textdomain("messages")
每次请求都重初始化语言上下文
gettext 没有自动感知 session 或 URL 参数变更的能力。切换语言后,如果不重新执行初始化,后续所有 _() 仍沿用旧 locale 上下文。
- 把初始化逻辑封装成函数,例如:
function setup_i18n($locale) { setlocale(LC_ALL, $locale); bindtextdomain("messages", __DIR__ . "/locale"); textdomain("messages"); } - 在每个请求入口(如
index.php或中间件)中调用它,传入当前用户选择的语言标识 - 避免在模板里反复调用
setlocale(),它开销大且多次调用可能被系统忽略



















