How to assign particular context to --keyword for proper_name?

674 views Asked by At

When using the xgettext tool it is possible to automatically add commenting to assist translators with regards to proper names (as documented).

The documentation suggests to add the following to the command line:

--keyword='proper_name:1,"This is a proper name. See the gettext manual, section Names."'

Which results in proper names being extracted to the .pot file like this:

#. This is a proper name. See the gettext manual, section Names.
#: ../Foo.cpp:18
msgid "Bob"
msgstr ""

The problem with this; is that no particular context has been defined for that string. Here is ideally how the proper name would be extracted:

#. This is a proper name. See the gettext manual, section Names.
#: ../Foo.cpp:18
msgctxt "Proper Name"
msgid "Bob"
msgstr ""

I've tried the following but with no success:

# Hoping that 0 would be the function name 'proper_name'.
--keyword='proper_name:0c,1,"This is a proper name. See the gettext manual, section Names."'

# Hoping that -1 would be the function name 'proper_name'.
--keyword='proper_name:-1c,1,"This is a proper name. See the gettext manual, section Names."'

# Hoping that the string would be used as the context.
--keyword='proper_name:"Proper Name"c,1,"This is a proper name. See the gettext manual, section Names."'

# Hoping that the string would be used as the context.
--keyword='proper_name:c"Proper Name",1,"This is a proper name. See the gettext manual, section Names."'

Is there a way to force a particular msgctxt to be used for all strings extracted with a keyword (such as proper_name from the example above)?

If there is no option to achieve this with xgettext as-is then I considered perhaps using the following:

--keyword='proper_name:1,"<PROPERNAME>"'

Resulting with:

#. <PROPERNAME>
#: ../Foo.cpp:18
msgid "Bob"
msgstr ""

The problem then becomes; how to automatically translate all occurrences of this in the resulting .pot file into the following:

#. This is a proper name. See the gettext manual, section Names.
#: ../Foo.cpp:18
msgctxt "Proper Name"
msgid "Bob"
msgstr ""
1

There are 1 answers

0
Guido Flohr On BEST ANSWER

If you want to extract a message context, it has to be part of the argument list. And the numerical part in "Nc" has to be a positive integer. All your attempts with 0, -1 are fruitless, sorry.

The signature of your function must look like this:

#define PROPER_NAME "Proper Name"
const char *proper_name(const char *ctx, const char *name);

And then call it like this:

proper_name(PROPER_NAME, "Bob");

That repeats PROPER_NAME all over the code, but it's the only way to get it into the message context.

Maybe file a feature request?

There is also a hack that achieves the same without changing your source code. I assume that you're using C and the standard Makefile (but you can do the same in other languages):

Copy the file POTFILES to POTFILES-proper-names and add a line ./proper_names.pot to POTFILES.in.

Then you have to create proper_names.pot:

xgettext --files-from=POTFILES-proper-names \
         --keyword='' \
         --keyword='proper_names:1:"Your comment ..."' \
         --output=proper_names.pox

This will now only contain the entries that were maked with "proper_names()". Now add the context:

msg-add-content proper_names.pox "Proper Name" >proper_names.pot
rm proper_names.pot

Unfortunately, there is no program called "msg-add-content". Grab one of the zillion po-parsers out there, and write one yourself (or take mine at the end of this post).

Now, update your PACKAGE.pot as usual. Since "proper_names.pox" is an input file for the main xgettext run, all your extracted proper names with the context added, are added to your pot file (and their context will be used).

Short of another script for adding a message context to all your entries in a .pot file, use this one:

#! /usr/bin/env perl

use strict;

use Locale::PO;

die "usage: $0 POFILE CONTEXT" unless @ARGV == 2;

my ($input, $context) = @ARGV;

my $entries = Locale::PO->load_file_asarray($input) or die "$input: failure";
foreach my $entry (@$entries) {
    $entry->msgctxt($context) unless '""' eq $entry->msgid;
    print $entry->dump;
}

You have to install the Perl library "Locale::PO" for it, either with "sudo cpan install Locale::PO" or use the pre-built version that your vendor may have.