PHP多语言国际化与本地化需分离语言内容与代码逻辑,分层处理界面翻译及日期、数字、货币格式适配;推荐gettext扩展(中大型项目)、数组语言包(小型项目)和intl扩展(格式化)三者协同实现。

PHP实现多语言国际化(i18n)与本地化(l10n),关键在于把语言内容和代码逻辑分开,再按用户实际环境动态加载对应资源。不是简单替换文字,而是分层处理:界面文本翻译 + 日期/数字/货币等格式适配。
用 gettext 扩展做专业级翻译
这是最成熟、被广泛采用的方案,适合中大型项目,支持复数、上下文、协作翻译流程。
- 确认扩展已启用:运行
php -m | grep gettext,Web 环境还要检查 Apache/Nginx 使用的 php.ini 是否一致 - 系统需安装对应 locale(如
locale -a | grep zh_CN.utf8),没的话要生成:sudo locale-gen zh_CN.UTF-8 - 目录结构必须严格:比如
./locale/zh_CN/LC_MESSAGES/messages.mo,其中messages是文本域名,zh_CN是 locale 名 - PHP 中只设翻译相关 locale:
setlocale(LC_MESSAGES, 'zh_CN.UTF-8'),避免用LC_ALL影响数字/日期格式 - 绑定路径用绝对路径:
bindtextdomain('messages', __DIR__ . '/locale'),再调用textdomain('messages') - 所有待翻译字符串用
_()或gettext()包裹,例如echo _("Login");
用数组语言包快速启动
适合小型项目、原型或共享主机(无需扩展),轻量灵活,但不支持复数、上下文等高级特性。
- 在
lang/下建文件,如lang/zh.php返回数组:return ['login' => '登录', 'welcome' => '欢迎']; - 根据 URL 参数(
?lang=zh)、Accept-Language头或 Session 确定当前语言码 - 动态加载:
$lang = require 'lang/' . $locale . '.php';,然后用$lang['login']取值 - 可加简单插值支持,比如
str_replace('{name}', $user, $lang['hello'])
用 intl 扩展处理本地化格式
专用于日期、时间、数字、货币、复数等文化敏感格式,不替代翻译,而是补足 gettext 的短板。
立即学习“PHP免费学习笔记(深入)”;
- 检查
intl是否启用:phpinfo()查看 “Internationalization support” - 日期格式化:
$fmt = new IntlDateFormatter('zh_CN', IntlDateFormatter::FULL, IntlDateFormatter::NONE); echo $fmt->format(time()); - 数字格式:
$num = new NumberFormatter('de_DE', NumberFormatter::DECIMAL); echo $num->format(1234.56); // → 1.234,56 - 带参数的翻译(需配合语言数组):
$fmt = new MessageFormatter('en_US', "You have {count, plural, one{# message} other{# messages}}"); echo $fmt->format(['count' => 3]);
语言切换与状态管理
用户语言偏好不能靠全局变量硬存,得有明确来源和生命周期控制。
- 优先级建议:URL 参数 > Cookie > Session > Accept-Language > 默认语言(如
en) - 切换时更新 Session 和 Cookie,保证后续请求延续性:
$_SESSION['locale'] = $lang; setcookie('locale', $lang, time()+3600*24*30); - 每次请求入口处统一初始化:
setlocale(LC_MESSAGES, getAppLocale());,不要依赖上一次残留状态 - 前端可同步语言信息,比如把当前 locale 注入 HTML 的
lang属性或 JS 全局变量,方便前端 i18n 库使用



















