xampp 默认不启用 gettext 扩展,需确认 phpinfo 中 gettext support => enabled 且函数列表完整;补全匹配架构的 libintl.dll;执行 setlocale、bindtextdomain、textdomain 三步初始化;确保 .mo 文件路径、命名、编码严格符合 gnu 规范。

XAMPP 默认不启用 gettext 扩展,即使你取消了 php.ini 里的注释,也极大概率返回原文——不是代码写错了,而是扩展根本没真正跑起来。
确认 gettext 是否真的加载成功
别信 php.ini 里那行 extension=php_gettext.dll 已取消注释就万事大吉。Windows 下 XAMPP 的 PHP 编译时通常未内置 gettext,即使加载了 DLL,缺依赖也会静默失败。
- 新建
info.php放在htdocs下,内容为<?php phpinfo(); ?>,浏览器访问后搜索gettext support - 必须看到
gettext support => enabled和函数列表(如gettext、dgettext、_)才算通过 - 如果没出现,立刻去查 Apache 错误日志:
xampppachelogserror.log,找类似PHP Warning: PHP Startup: Unable to load dynamic library 'php_gettext.dll'的报错 - Linux/macOS 用户用
php -m | grep gettext快速验证 CLI 模式是否加载;但注意:Apache 可能用另一份php.ini,仍要以phpinfo()显示的Loaded Configuration File路径为准
Windows 下补全 libintl.dll 是关键一步
php_gettext.dll 在 Windows 下严重依赖 libintl.dll,而 XAMPP 安装包几乎从不自带它,或只带旧版(如 0.17),但 PHP 8.1+ 需要 0.19+ 才能让 bindtextdomain() 正常返回路径。
XAMPP 8.0.30 是一款免费、开源的跨平台 Web 服务器集成包,专为快速搭建本地 PHP 开发环境而设计。该版本核心组件包括:Apache 2.4.56、MySQL 8.0.33、PHP 8.0.30、phpMyAdmin 5.2.1 等。它支持 Windows、Linux 和 macOS 系统,可让开发者在个人电脑上轻松模拟服务器环境,无需复杂配置即可运行 WordPress、Thin
- 去 mlocati/gettext-windows 下载匹配你 PHP 架构(x86 或 x64)和版本的
libintl-2.dll - 重命名为
libintl.dll,放进xamppphp目录(和php_gettext.dll同级) - 确保
php.ini中extension_dir指向正确路径,例如:extension_dir = "C: mppphpext" - 重启 Apache 后,运行
var_dump(bindtextdomain('messages', 'C:/myapp/locale'));—— 返回string(15) "C:/myapp/locale"才算通过,返回bool(false)就说明libintl.dll还没到位
调用 gettext 前必须完成三步初始化
即使扩展加载成功,漏掉任意一步,_() 就只是原样返回字符串,不会报错也不会提示。
-
putenv('LC_ALL=zh_CN.UTF-8')或putenv('LANG=zh_CN.UTF-8')—— 设置环境变量,影响setlocale()行为 -
setlocale(LC_ALL, 'zh_CN.UTF-8')—— 必须用系统已安装的 locale 名(Windows 下常用Chinese_China.936或zh_CN.UTF-8,建议先用locale -a查 Linux/macOS,Windows 可试chcp看当前码页) -
bindtextdomain('messages', 'C:/myapp/locale')+textdomain('messages')—— 域名必须和.mo文件名一致,路径末尾不加LC_MESSAGES,那是内部自动拼的
MO 文件路径与命名必须严格符合 GNU 规范
gettext 对目录结构、文件名、编码极其敏感,错一个字符就找不到翻译。
- 正确结构:
locale/zh_CN/LC_MESSAGES/messages.mo(zh_CN是 locale 名,messages是 domain 名) -
.mo文件必须由.po编译生成,不能手写二进制;推荐用msgfmt zh_CN.po -o messages.mo - 确保
.po文件头含"Content-Type: text/plain; charset=UTF-8 ",否则.mo读出来是乱码 - Windows 下路径分隔符用正斜杠
/或双反斜杠\,单反斜杠在 PHP 字符串里会被转义
最容易被忽略的是 locale 名和系统实际支持的不一致——比如代码里写 zh_CN.UTF-8,但 Windows 并没安装这个 locale,setlocale() 就会失败并静默回退到 C locale,后续所有 gettext 调用都无效。建议先用 var_dump(setlocale(LC_ALL, '0')) 确认当前生效的 locale 是什么。










