Localization xgettext只能用于提取特定的域字符串吗?

Localization xgettext只能用于提取特定的域字符串吗?,localization,internationalization,gettext,xgettext,Localization,Internationalization,Gettext,Xgettext,(这一点在网上没有得到回答,真是令人惊讶;过去几年中,有几篇帖子提出了类似的问题,但从未得到回答。让我们希望Stackoverflow的工作人员能够前来救援) 情况: dgettext('menus', 'login link'); dgettext('menus', 'account link'); dgettext('footer', 'copyright notice'); dgettext('footer', 'contact form'); 使用gettext支持应用程序本地化时,有

(这一点在网上没有得到回答,真是令人惊讶;过去几年中,有几篇帖子提出了类似的问题,但从未得到回答。让我们希望Stackoverflow的工作人员能够前来救援)

情况:

dgettext('menus', 'login link');
dgettext('menus', 'account link');
dgettext('footer', 'copyright notice');
dgettext('footer', 'contact form');
使用gettext支持应用程序本地化时,有时需要使用DGettText(“域”、“某些文本字符串”)指定一个“域”。但是,在运行xgettext时,所有用DGettText(…)包装的字符串都会吐出到一个文件中(默认值:messages.po)

给出以下示例:

dgettext('menus', 'login link');
dgettext('menus', 'account link');
dgettext('footer', 'copyright notice');
dgettext('footer', 'contact form');
有什么办法可以结束这一切吗

菜单。po
footer.po

使用诸如xgettext之类的提取器


虽然我相信这应该适用于所有语言,但我发现实现这一点的唯一方法是重新定义gettext函数

例如:

function _menus ($str) {
    return dgettext('menus', $str);
}

function _footer ($_str) {
    return dgettext('footer', $str);
}

_menus('login link');
_menus('account link');
_footer('copyright notice');
_footer('contact form');
否则,您只需运行以下命令:

xgettext [usual options] -k --keyword=_menus:1 -d menus
xgettext [usual options] -k --keyword=_footer:1 -d footer

再见

我不知道如何在不同的文件中放置不同的上下文,但我发现xgettext可以将域名提取到po文件中的msgctxt字段中。对于PHP,默认情况下不会这样做。要启用此功能,请使用例如--keyword=dgettext:1c,2(在poedit中,将“dgettext:1c,2”)添加到关键字列表中

另见:


实现这一点最好通过代码分离或使用上下文消歧来实现

如果您可以将菜单代码与页脚代码分开,那么您可以真正地将它们视为不同的域,并从已知位置相应地提取它们。 如果模块分离是不可能的,并且所有的代码都在一起,那么实际上您应该使用上下文而不是域。e、 g

translate( 'A string', 'myproject', 'some module' ) 
其中,
“myproject”
是您的域,
“某些模块”
消除字符串的歧义

然而,现实并不总是与最佳实践相一致,所以如果你不能按照Asevere的建议重构你的代码(这可能是最好的答案),那么我有一个巨大的技巧可以提供


你可以利用Boris的回答中提到的上下文标志——我们可以重新利用它,但前提是我们不打算使用上下文

我重复一遍只有当您的代码不使用上下文时,此攻击才有效

一些PHP包含两个域(包括两个域中使用的一个字符串)-

这将生成一个
combined.pot
文件,其中包含使用上下文hack的所有字符串。(注意,我们还修复了占位符字符集字段,该字段将中断下一位)

现在,我们可以使用
msggrep
将给定上下文的所有消息过滤到单独的文件中。注意,我们也会丢弃上下文字段,因为我们不使用它

msggrep -J -e foo -o - combined.pot | sed '/^msgctxt/d' > foo.pot
msggrep -J -e bar -o - combined.pot | sed '/^msgctxt/d' > bar.pot

不恰当,但它有效。

嘿,1是什么意思?函数的第一个参数?你在这里混淆了域和上下文-它们是不同的东西,用于稍微不同的目的。上下文消除同一PO文件(即同一域内)中相同字符串的歧义。
msggrep -J -e foo -o - combined.pot | sed '/^msgctxt/d' > foo.pot
msggrep -J -e bar -o - combined.pot | sed '/^msgctxt/d' > bar.pot