如何在PHP gettext中同时使用多个textdomain与加载多份mo文件?
我懂你遇到的问题了——你想让多个模块各自使用独立的MO翻译文件,但连续调用textdomain()后只有最后一个生效,这是因为textdomain()是用来设置全局默认文本域的,每次调用都会覆盖之前的设置。下面给你几个实用的解决方案:
解决方案1:直接使用dgettext()指定文本域
不需要依赖全局的textdomain设置,每次翻译时明确指定要使用的文本域即可。这个方法是最直接且可靠的:
首先保留你的绑定代码(这一步是告诉gettext每个文本域对应的MO文件路径):
$lang = 'en_US'; putenv('LC_ALL=' . $lang); setlocale(LC_ALL, $lang); // 绑定两个文本域对应的翻译文件路径 bindtextdomain('module', ROOT . 'Language'); bindtextdomain('default', ROOT . 'Language'); // 这里不需要再调用textdomain()设置全局默认了
然后翻译时,用dgettext()代替默认的_()函数,第一个参数传入文本域名:
// 翻译module模块的文本 echo dgettext('module', 'Hello from Module'); // 翻译default模块的文本 echo dgettext('default', 'Hello from Default');
解决方案2:封装自定义翻译函数
为了让代码更简洁易读,可以封装一个自己的翻译函数,内部调用dgettext():
function __domain($domain, $string) { return dgettext($domain, $string); } // 使用起来更直观 echo __domain('module', 'Module-specific text'); echo __domain('default', 'General app text');
如果需要支持复数翻译,也可以封装ngettext()的版本:
function __domain_plural($domain, $singular, $plural, $count) { return ngettext($domain, $singular, $plural, $count); }
解决方案3:临时切换全局文本域(不推荐)
如果你确实需要临时使用默认的_()函数,可以先保存当前的文本域,切换后翻译,再切回去。但这个方法容易出错(比如忘记恢复原文本域),所以只适合特殊场景:
// 保存当前默认文本域(初始可能是默认值) $originalDomain = textdomain(null); // 切换到module文本域,翻译内容 textdomain('module'); echo _('Module text'); // 切回原来的文本域 textdomain($originalDomain); // 切换到default文本域,翻译内容 textdomain('default'); echo _('Default text'); // 记得切回原域 textdomain($originalDomain);
额外注意事项
- 检查MO文件路径:确保
bindtextdomain指定的目录结构正确。比如ROOT . 'Language'下应该有这样的层级:Language/ └── en_US/ └── LC_MESSAGES/ ├── module.mo └── default.mo - 验证语言环境:确认服务器系统支持你设置的
$lang(比如en_US),可以用echo setlocale(LC_ALL, 0);查看当前生效的locale是否正确。
内容的提问来源于stack exchange,提问作者Göksel Tığlı
相关产品推荐
相关产品推荐

