xgettext 能否仅用于提取特定域字符串?

发布于 2024-09-11 17:26:58 字数 611 浏览 10 评论 0原文

(真的很惊讶这个问题在网上没有任何地方得到解答;过去几年有几篇帖子提出了类似的问题,但从未得到解答。希望 Stackoverflow 工作人员能够前来救援)

情况:

当使用 gettext 支持应用程序本地化时,有时希望使用 dgettext('domain', 'some text string') 指定一个“域”。然而,当运行xgettext时,所有用 dgettext(...) 包裹的字符串都会被吐出到一个文件中(默认:messages.po)。

给出以下示例:

dgettext('menus', 'login link');
dgettext('menus', 'account link');
dgettext('footer', 'copyright notice');
dgettext('footer', 'contact form');

有什么方法可以得到

menus.po
footer.po

使用 xgettext 等提取器?

需要 PHP 响应,尽管我相信这应该适用于所有语言

(Really surprised this isn't answered anywhere online; couple posts over the past few years with a similar question, but never answered. Let's hope the Stackoverflow crew can come to the rescue)

Situation:

When using gettext to support application localization, one sometimes wishes to specify a 'domain' with dgettext('domain', 'some text string'). However, when running xgettext, all strings wrapped with dgettext(...) are spit out into one file (default: messages.po).

Given the following example:

dgettext('menus', 'login link');
dgettext('menus', 'account link');
dgettext('footer', 'copyright notice');
dgettext('footer', 'contact form');

is there any way to end up with

menus.po
footer.po

using an extractor such as xgettext?

PHP response desired, although I believe this should be applicable across all languages

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

静水深流 2024-09-18 17:26:58

我发现做到这一点的唯一方法是重新定义 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

再见!

The only way I've found to do this is to redefine gettext functions...

example:

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');

else, you only have to run following commands:

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

Bye!

风尘浪孓 2024-09-18 17:26:58

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

另请参阅:

http://developer.gnome.org/glib/2.28/glib- I18N.html

https:// www.gnu.org/savannah-checkouts/gnu/gettext/manual/html_node/xgettext-Inspiration.html

I do not know how to put different contexts in different files, but I did find that xgettext can extract the domain names into msgctxt fields in the po file. For PHP this is not done by default. To enable this, use for example --keyword=dgettext:1c,2 (in poedit, add "dgettext:1c,2") to the keyword list.

See also:

http://developer.gnome.org/glib/2.28/glib-I18N.html

https://www.gnu.org/savannah-checkouts/gnu/gettext/manual/html_node/xgettext-Invocation.html

余厌 2024-09-18 17:26:58

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

如果您可以将菜单代码与页脚代码分开,那么您可以真正将它们视为不同的域,并从已知位置相应地提取它们。

如果模块化分离是不可能的并且所有代码都在一起,那么您实际上应该使用上下文而不是域。例如

translate( 'A string', 'myproject', 'some module' ) 

,其中 "myproject" 是您的域,"some module" 消除字符串的歧义。

然而,现实并不总是与最佳实践相符,因此,如果您无法按照 Asevere 的建议重构代码(这可能是最好的答案),那么我可以提供大量的 hack。


您可以利用鲍里斯的答案中提到的上下文标志 - 我们可以重新调整它的用途,但前提是我们不打算使用上下文。

我再说一遍。 只有当您的代码不使用上下文时,此技巧才有效

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

<?php // test.php
dgettext( 'abc', 'foo' );
dgettext( 'abc', 'bar' );
dgettext( 'xyz', 'bar' );

我们可以作弊,并采用域参数,就好像我们打算将其作为消息上下文(msgctxt 字段)一样。从命令行提取:

xgettext -LPHP --keyword=dgettext:1,2c -o - test.php \
         | sed 's/CHARSET/utf-8/' \
         > combined.pot

这会生成一个 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

不正确,但它有效。

Achieving this is best done through either code separation or the use of context disambiguation.

If you can separate your menu code from your footer code, then you can truly consider them different domains and extract them accordingly from known locations.

If modular separation is impossible and all the code lives together, then really you should be using context instead of domains. e.g.

translate( 'A string', 'myproject', 'some module' ) 

Where "myproject" is your domain and "some module" disambiguates the string.

However, reality doesn't always align with best practice, so if you can't refactor your code as Asevere suggests (and that is probably the best answer) then I have a massive hack to offer.


You could exploit the context flag mentioned in Boris's answer - We can repurpose this but only if we're not otherwise going to be using contexts.

I'll repeat that. This hack will only work if your code is not using contexts.

Some PHP holding two domains (including one string used in both) -

<?php // test.php
dgettext( 'abc', 'foo' );
dgettext( 'abc', 'bar' );
dgettext( 'xyz', 'bar' );

We can cheat, and take the domain argument as if we intended it to be the message context (msgctxt field). Extracting from the command line:

xgettext -LPHP --keyword=dgettext:1,2c -o - test.php \
         | sed 's/CHARSET/utf-8/' \
         > combined.pot

This generates a combined.pot file containing all the strings with our context hack. (note we also fixed the placeholder character set field which would break the next bit)

We can now filter out all messages of a given context into separate files using msggrep. Note we also trash the context field as we're not using it.

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

Improper, but it works.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文