Next: , Previous: , Up: gettext   [Contents][Index]

11.2.5 Using contexts for solving ambiguities


As a consequence many people say that the gettext approach is wrong and instead catgets should be used which indeed does not have this problem. But there is a very simple and powerful method to handle this kind of problems with the gettext functions.

Contexts can be added to strings to be translated. A context dependent translation lookup is when a translation for a given string is searched, that is limited to a given context. The translation for the same string in a different context can be different. The different translations of the same string in different contexts can be stored in the in the same MO file, and can be edited by the translator in the same PO file.

The gettext.h include file contains the lookup macros for strings with contexts. They are implemented as thin macros and inline functions over the functions from <libintl.h>.

const char *pgettext (const char *msgctxt, const char *msgid);

In a call of this macro, msgctxt and msgid must be string literals. The macro returns the translation of msgid, restricted to the context given by msgctxt.

The msgctxt string is visible in the PO file to the translator. You should try to make it somehow canonical and never changing. Because every time you change an msgctxt, the translator will have to review the translation of msgid.

Finding a canonical msgctxt string that doesn’t change over time can be hard. But you shouldn’t use the file name or class name containing the pgettext call – because it is a common development task to rename a file or a class, and it shouldn’t cause translator work. Also you shouldn’t use a comment in the form of a complete English sentence as msgctxt – because orthography or grammar changes are often applied to such sentences, and again, it shouldn’t force the translator to do a review.

The ‘p’ in ‘pgettext’ stands for “particular”: pgettext fetches a particular translation of the msgid.

const char *dpgettext (const char *domain_name,
                       const char *msgctxt, const char *msgid);
const char *dcpgettext (const char *domain_name,
                        const char *msgctxt, const char *msgid,
                        int category);

These are generalizations of pgettext. They behave similarly to dgettext and dcgettext, respectively. The domain_name argument defines the translation domain. The category argument allows to use another locale category than LC_MESSAGES.

As as example consider the following fictional situation. A GUI program has a menu bar with the following entries:

| File       | Printer    |                                      |
| Open     | | Select   |
| New      | | Open     |


What distinguishes the two places is the menu path from the menu root to the particular menu entries:


The context is thus the menu path without its last part. So, the calls look like this:

pgettext ("Menu|", "File")
pgettext ("Menu|", "Printer")
pgettext ("Menu|File|", "Open")
pgettext ("Menu|File|", "New")
pgettext ("Menu|Printer|", "Select")
pgettext ("Menu|Printer|", "Open")
pgettext ("Menu|Printer|", "Connect")

Whether or not to use the ‘|’ character at the end of the context is a matter of style.

For more complex cases, where the msgctxt or msgid are not string literals, more general macros are available:

const char *pgettext_expr (const char *msgctxt, const char *msgid);
const char *dpgettext_expr (const char *domain_name,
                            const char *msgctxt, const char *msgid);
const char *dcpgettext_expr (const char *domain_name,
                             const char *msgctxt, const char *msgid,
                             int category);

Here msgctxt and msgid can be arbitrary string-valued expressions. These macros are more general. But in the case that both argument expressions are string literals, the macros without the ‘_expr’ suffix are more efficient.
