Can xgettext be used to extract specific domain strings only?
Asked Answered
L

3

3

(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

Linn answered 27/7, 2010 at 8:26 Comment(0)
D
2

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!

Documentation answered 18/3, 2011 at 15:39 Comment(1)
Hey, what the :1 mean ? First argument of the function ?Gritty
M
1

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

Mender answered 8/5, 2012 at 15:18 Comment(1)
You're confusing domains and contexts here - they are different things, serving slightly different purposes. Contexts disambiguate otherwise identical strings within the same PO file (i.e., within the same domain).Bobbee
B
1

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.

Berkin answered 1/4, 2015 at 14:31 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.