Edited for better examples:
A friends' birthday reminder widget
This requires dcgettext()
or dcngettext()
, because it should use the LC_TIME
category rather than LC_MESSAGES
category (for the one localized string, "It's %s's birthday today!
"), because users would expect the LC_TIME
environment variable to control the language of the widget, the same way it does for e.g. the date
command.
A restaurant bill splitter widget
To make it easier to understand and split bills in other countries (especially countries where you can barely understand the bill), this would use LC_MONETARY
category for the bill fields, so that the users can select the currency by changing the LC_MONETARY
environment variable.
Let's assume the widget is intended for traveling users, or is perhaps supported by a simple server backend, which stores descriptions and numeric amounts, but no monetary units. Each bill is a simple dataset, containing locale, total amount, description string, and a list of participants, each participant specified by a string and a number. Sum of the numbers should always be at least the total amount, the extra be the tip.
The user interface (menus, options etc.) are localized as normal using the LC_MESSAGES
category, but each bills locale overriding the LC_NUMERIC
and LC_MONETARY
locale categories, and the application-specific strings in the widget -- "total
", "tip
" and so on -- using the LC_MONETARY
category in the localization file. (Therefore the code would have dcgettext(NULL,"Total",LC_MONETARY)
, `dcgettext(NULL,"Tip",LC_MONETARY) and so on.)
When creating a new bill, you can implement the locale selection by simply switching to the desired locale in LC_MONETARY
and/or LC_NUMERIC
category.
The reason you would want to do this is simple: you could have an user interface that shows the typical bill according to the local localization (per restaurant locale), while the rest of the user interface, especially tool tips, hints, help et cetera, is still in the main locale/language (as determined by LC_MESSAGES
).
Regardless of whether the widget was a graphical Qt/GTK+ or a command-line one, it could always use the normal environment variables to define its initial locale (LC_MESSAGES
for user interface, LC_MONETARY
and LC_NUMERIC
for the new bill).
Most programmers would likely use a configuration file or manager or registry key to store the locale, but since it is trivially available, well standardized, why duplicate the functionality? Moreover, a user could create aliases or shortcuts that simply set a different initial locale (for the two categories), and could have multiple instances of the widget open, using different billing locales, for example for comparison or understanding the bill.
gettext(msgid)
is equivalent to dgettext(NULL,msgid)
is equivalent to dcgettext(NULL,msgid,LC_MESSAGES)
.
In fact, in current GNU gettext, gettext(msgid)
is a wrapper around dcgettext(NULL,msgid,LC_MESSAGES)
, and dgettext(domain,msgid)
is a wrapper around
dcgettext(domain,msgid,LC_MESSAGES)
.
The category parameter to dcgettext()
allows you to select which category is used to determine the locale. For example, if you used dcgettext(NULL, "FOO", LC_MONETARY)
, then the LC_MONETARY
category would be used to determine the actual locale to use. Because the C library provides the category-specific functions like strftime()
(uses the LC_TIME
category) and strcoll()
(uses the LC_COLLATE
category), most applications only explicitly use the LC_MESSAGES
category. (They do, however, use the other categories via the C library functions.)
The user can control the locale for each category via environment variables.
For the GNU C library, the environment variables are interpreted as follows:
If LC_ALL
is not empty, it defines the locale for all categories.
Otherwise:
If LC_CATEGORY
is not empty, it defines the locale for category CATEGORY
.
Otherwise:
If LANG
is not empty, it defines the locale.
Otherwise:
The locale is C/POSIX.
In other words, LANGUAGE
is ignored, and LANG
is only used if both LC_ALL
and the relevant LC_category
environment variables are empty or undefined.
In my experience, other OSes with gettext or similar localization support, have the same environment variable support pattern -- LC_ALL
being the override, LC_category
being the specific setting, with LANG
(and possibly LANGUAGE
) as defaults if nothing else is set.
It is very useful to use a mixed-locale environment, where LC_ALL
is undefined or empty, some of the LC_
environment variables are defined to a specific locale, with others undefined or empty or C
, possibly with a default LANG
defined just to be sure.
I personally sometimes use
LC_ALL= \
LC_TIME=C \
LC_NUMERIC=C \
LC_CTYPE=C \
LC_MESSAGES=C \
LC_COLLATE=fi_FI.utf8 ls -laF --color=auto
as an alias for ll
. It lists the files and directories in the specified directory, using the C/POSIX locale for everything except string collation (string sort order), which uses Finnish rules. That gives me the output sorted according to typical Finnish rules, but everything is in C/POSIX locale.
I might switch to a LC_TIME
locale that used ISO 8601 dates, or perhaps a human-friendly version of ISO 8601 (YYYY-MM-DD HH:MM:SS.ttt TZ). Just haven't yet cared enough to look for one or write one myself.
Questions?