Can xgettext be used to extract specific domain strings only?

荒凉一梦 提交于 2019-12-10 10:25:17

问题


(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


回答1:


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!




回答2:


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




回答3:


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.



来源:https://stackoverflow.com/questions/3341829/can-xgettext-be-used-to-extract-specific-domain-strings-only

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!