Build multi-language support into your Linux application with catgets
Translator
![© Photo by Leonardo Toshiro Okubo on Unsplash © Photo by Leonardo Toshiro Okubo on Unsplash](/var/linux_magazin/storage/images/issues/2023/266/catgets/photobyleonardotoshirookuboonunsplash_translator.png/814682-1-eng-US/PhotobyLeonardoToshiroOkuboonUnsplash_Translator.png_medium.png)
© Photo by Leonardo Toshiro Okubo on Unsplash
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.
![Learn More](https://www.linux-magazine.com/var/linux_magazin/storage/images/media/linux-magazine-eng-us/images/misc/learn-more/834592-1-eng-US/Learn-More_medium.png)
News
-
NVIDIA Released Driver for Upcoming NVIDIA 560 GPU for Linux
Not only has NVIDIA released the driver for its upcoming CPU series, it's the first release that defaults to using open-source GPU kernel modules.
-
OpenMandriva Lx 24.07 Released
If you’re into rolling release Linux distributions, OpenMandriva ROME has a new snapshot with a new kernel.
-
Kernel 6.10 Available for General Usage
Linus Torvalds has released the 6.10 kernel and it includes significant performance increases for Intel Core hybrid systems and more.
-
TUXEDO Computers Releases InfinityBook Pro 14 Gen9 Laptop
Sporting either AMD or Intel CPUs, the TUXEDO InfinityBook Pro 14 is an extremely compact, lightweight, sturdy powerhouse.
-
Google Extends Support for Linux Kernels Used for Android
Because the LTS Linux kernel releases are so important to Android, Google has decided to extend the support period beyond that offered by the kernel development team.
-
Linux Mint 22 Stable Delayed
If you're anxious about getting your hands on the stable release of Linux Mint 22, it looks as if you're going to have to wait a bit longer.
-
Nitrux 3.5.1 Available for Install
The latest version of the immutable, systemd-free distribution includes an updated kernel and NVIDIA driver.
-
Debian 12.6 Released with Plenty of Bug Fixes and Updates
The sixth update to Debian "Bookworm" is all about security mitigations and making adjustments for some "serious problems."
-
Canonical Offers 12-Year LTS for Open Source Docker Images
Canonical is expanding its LTS offering to reach beyond the DEB packages with a new distro-less Docker image.
-
Plasma Desktop 6.1 Released with Several Enhancements
If you're a fan of Plasma Desktop, you should be excited about this new point release.