Build multi-language support into your Linux application with catgets
Translator
To make programs useful to a worldwide audience, you need to build in support for multiple languages. Catgets is a tool that helps you reach beyond your mother tongue.
One way that programmers can help others use their software is to add multi-language support. I'm not talking about programming languages; I mean spoken languages. For example, you may have written your open source program to print information and error messages in English, but what if your user speaks only Spanish? Does your open source program also "speak" Spanish? What about German, French, Italian, and all the other languages spoken around the world?
To make programs truly useful, programmers should support internationalization. An easy way to do that is with the catgets library [1], the original Unix method for a program to retrieve messages and other strings in the user's preferred spoken language. The GNU library also includes a similar function called gettext, which uses a different lookup method. Whereas catgets uses three values to look up a message (the catalog, the message set, and the message number), gettext uses the message itself as the lookup value.
Catgets provides an interface to fetch strings from a special file called a catalog [2] that contains all the messages your program needs to print. The basic usage is to open the catalog, fetch messages from the catalog and print them, and then close the catalog.
Opening and Closing a Catalog
Before you can use a message catalog, you first need to open it. The catopen()
function opens a message catalog and returns a catalog descriptor, which is similar to a file pointer. You'll use this descriptor when you retrieve messages later using catgets()
. The function call to catgets()
asks for the filename of a message catalog, plus a flag that indicates if catgets()
should use the current language locale value. If the flag is set to NL_CAT_LOCALE
, then catgets()
will use the current language locale, which you might set with setlocale()
. Otherwise, catgets()
will use the value from the LANG
environment variable.
#include <nl_types.h> nl_catd catopen(const char *catalog,int flag);
The catalog
indicates the message catalog you want to open. If this contains a path, then catopen()
will open that file. If not, then catopen()
will look for the message catalog file in the directories specified with the NLSPATH
environment variable.
Programs can open multiple catalogs at once, such as one catalog for error messages, another for debugging information, and so on. Each new message catalog requires a separate call to catopen()
to open the catalog and get a descriptor. But most programs typically use just one message catalog file and divide the messages into message sets. I recommend using just one message catalog unless your program is really big and needs to organize a lot of different messages.
For example, to open a message catalog file called hello.cat
, you would use catopen()
as follows:
nl_catd cat; cat = catopen("./hello.cat",NL_CAT_LOCALE);
The catopen()
function returns the catalog descriptor as type nl_catd
, or -1
to indicate an error.
When you don't need the message catalog anymore, you can close it with the catclose()
function:
#include <nl_types.h> int catclose(nl_catd cat);
Fetching Messages with catgets
To print a message to the user in the user's preferred spoken language, you first need to retrieve a string from the catalog. The catgets()
function looks up the message from the database using three telltales: the catalog, the message set, and the message number within the message set. catgets()
then returns a pointer to the string from the catalog, as follows:
#include <nl_types.h> char *catgets(nl_catd cat, int set,int num, const char *message);
If catgets()
can't find the message number in the message set in the message catalog, it returns a default string. By using a string as one of the function arguments, your program will always have a fallback message to print. This also makes your code more readable, because your catgets()
call contains the string it needs to look up.
For instance, let's say your program needs to print the string "Hello" to the user. To look up this message from the catalog, you need to know two things: what is the message set this message is defined in, and what is the message number in the message set. If "Hello" is the first string in the second message set, you might use catgets()
as follows to retrieve the string from the catalog and print it:
char msg; msg = catgets(cat, 2, 1, "Hello"); puts(msg);
Creating a Message Catalog
A message catalog is a kind of database file that contains all the messages for your program. But you don't create the binary file by hand. Instead, you write a plain text file using a custom syntax and a few special markers, and then use a program to convert the text file into a catalog database file. In this way, the catalog text file is basically the "source code" for your catalog database file.
In the source file, keywords start with a dollar sign. For example, $set
defines the start of a new message set, such as $set 2
for the second message set.
A dollar sign followed immediately by a space or tab indicates a comment. Translators might use these comments to make note of who last updated the file, and what each string is supposed to mean. Blank lines are ignored.
To demonstrate how to define a message catalog file, I'll define a message catalog for a sample program. For fun, I'll define a few program messages in a made-up language, Klingon, so that you can easily recognize if the program is correctly looking up messages from the catalog or printing the "fallback" messages from the call to the catgets()
function. You might create a message catalog that defines a few strings such as Yes and No, and any other messages a program might need to print such as greeting the user and asking important questions (Listing 1).
Listing 1
A sample message catalog
When the file is complete, you can turn it into a message catalog with the gencat
command [3]. For example, the following command converts the input file hello.klingon
into a catalog file called hello.cat
:
$ gencat -o hello.cat hello.klingon
Buy this article as PDF
(incl. VAT)
Buy Linux Magazine
Subscribe to our Linux Newsletters
Find Linux and Open Source Jobs
Subscribe to our ADMIN Newsletters
Support Our Work
Linux Magazine content is made possible with support from readers like you. Please consider contributing when you’ve found an article to be beneficial.
News
-
Latest Cinnamon Desktop Releases with a Bold New Look
Just in time for the holidays, the developer of the Cinnamon desktop has shipped a new release to help spice up your eggnog with new features and a new look.
-
Armbian 24.11 Released with Expanded Hardware Support
If you've been waiting for Armbian to support OrangePi 5 Max and Radxa ROCK 5B+, the wait is over.
-
SUSE Renames Several Products for Better Name Recognition
SUSE has been a very powerful player in the European market, but it knows it must branch out to gain serious traction. Will a name change do the trick?
-
ESET Discovers New Linux Malware
WolfsBane is an all-in-one malware that has hit the Linux operating system and includes a dropper, a launcher, and a backdoor.
-
New Linux Kernel Patch Allows Forcing a CPU Mitigation
Even when CPU mitigations can consume precious CPU cycles, it might not be a bad idea to allow users to enable them, even if your machine isn't vulnerable.
-
Red Hat Enterprise Linux 9.5 Released
Notify your friends, loved ones, and colleagues that the latest version of RHEL is available with plenty of enhancements.
-
Linux Sees Massive Performance Increase from a Single Line of Code
With one line of code, Intel was able to increase the performance of the Linux kernel by 4,000 percent.
-
Fedora KDE Approved as an Official Spin
If you prefer the Plasma desktop environment and the Fedora distribution, you're in luck because there's now an official spin that is listed on the same level as the Fedora Workstation edition.
-
New Steam Client Ups the Ante for Linux
The latest release from Steam has some pretty cool tricks up its sleeve.
-
Gnome OS Transitioning Toward a General-Purpose Distro
If you're looking for the perfectly vanilla take on the Gnome desktop, Gnome OS might be for you.