gettext: Contexts
1
1 11.2.5 Using contexts for solving ambiguities
1 ---------------------------------------------
1
1 One place where the ‘gettext’ functions, if used normally, have big
1 problems is within programs with graphical user interfaces (GUIs). The
1 problem is that many of the strings which have to be translated are very
1 short. They have to appear in pull-down menus which restricts the
1 length. But strings which are not containing entire sentences or at
1 least large fragments of a sentence may appear in more than one
1 situation in the program but might have different translations. This is
1 especially true for the one-word strings which are frequently used in
1 GUI programs.
1
1 As a consequence many people say that the ‘gettext’ approach is wrong
1 and instead ‘catgets’ should be used which indeed does not have this
1 problem. But there is a very simple and powerful method to handle this
1 kind of problems with the ‘gettext’ functions.
1
1 Contexts can be added to strings to be translated. A context
1 dependent translation lookup is when a translation for a given string is
1 searched, that is limited to a given context. The translation for the
1 same string in a different context can be different. The different
1 translations of the same string in different contexts can be stored in
1 the in the same MO file, and can be edited by the translator in the same
1 PO file.
1
1 The ‘gettext.h’ include file contains the lookup macros for strings
1 with contexts. They are implemented as thin macros and inline functions
1 over the functions from ‘<libintl.h>’.
1
1 const char *pgettext (const char *msgctxt, const char *msgid);
1
1 In a call of this macro, MSGCTXT and MSGID must be string literals.
1 The macro returns the translation of MSGID, restricted to the context
1 given by MSGCTXT.
1
1 The MSGCTXT string is visible in the PO file to the translator. You
1 should try to make it somehow canonical and never changing. Because
1 every time you change an MSGCTXT, the translator will have to review the
1 translation of MSGID.
1
1 Finding a canonical MSGCTXT string that doesn’t change over time can
1 be hard. But you shouldn’t use the file name or class name containing
1 the ‘pgettext’ call – because it is a common development task to rename
1 a file or a class, and it shouldn’t cause translator work. Also you
1 shouldn’t use a comment in the form of a complete English sentence as
1 MSGCTXT – because orthography or grammar changes are often applied to
1 such sentences, and again, it shouldn’t force the translator to do a
1 review.
1
1 The ‘p’ in ‘pgettext’ stands for “particular”: ‘pgettext’ fetches a
1 particular translation of the MSGID.
1
1 const char *dpgettext (const char *domain_name,
1 const char *msgctxt, const char *msgid);
1 const char *dcpgettext (const char *domain_name,
1 const char *msgctxt, const char *msgid,
1 int category);
1
1 These are generalizations of ‘pgettext’. They behave similarly to
1 ‘dgettext’ and ‘dcgettext’, respectively. The DOMAIN_NAME argument
1 defines the translation domain. The CATEGORY argument allows to use
1 another locale category than ‘LC_MESSAGES’.
1
1 As as example consider the following fictional situation. A GUI
1 program has a menu bar with the following entries:
1
1 +------------+------------+--------------------------------------+
1 | File | Printer | |
1 +------------+------------+--------------------------------------+
1 | Open | | Select |
1 | New | | Open |
1 +----------+ | Connect |
1 +----------+
1
1 To have the strings ‘File’, ‘Printer’, ‘Open’, ‘New’, ‘Select’, and
1 ‘Connect’ translated there has to be at some point in the code a call to
1 a function of the ‘gettext’ family. But in two places the string passed
1 into the function would be ‘Open’. The translations might not be the
1 same and therefore we are in the dilemma described above.
1
1 What distinguishes the two places is the menu path from the menu root
1 to the particular menu entries:
1
1 Menu|File
1 Menu|Printer
1 Menu|File|Open
1 Menu|File|New
1 Menu|Printer|Select
1 Menu|Printer|Open
1 Menu|Printer|Connect
1
1 The context is thus the menu path without its last part. So, the
1 calls look like this:
1
1 pgettext ("Menu|", "File")
1 pgettext ("Menu|", "Printer")
1 pgettext ("Menu|File|", "Open")
1 pgettext ("Menu|File|", "New")
1 pgettext ("Menu|Printer|", "Select")
1 pgettext ("Menu|Printer|", "Open")
1 pgettext ("Menu|Printer|", "Connect")
1
1 Whether or not to use the ‘|’ character at the end of the context is
1 a matter of style.
1
1 For more complex cases, where the MSGCTXT or MSGID are not string
1 literals, more general macros are available:
1
1 const char *pgettext_expr (const char *msgctxt, const char *msgid);
1 const char *dpgettext_expr (const char *domain_name,
1 const char *msgctxt, const char *msgid);
1 const char *dcpgettext_expr (const char *domain_name,
1 const char *msgctxt, const char *msgid,
1 int category);
1
1 Here MSGCTXT and MSGID can be arbitrary string-valued expressions.
1 These macros are more general. But in the case that both argument
1 expressions are string literals, the macros without the ‘_expr’ suffix
1 are more efficient.
1