Text messages to be localized must be separated from the source code of the application and stored in a separate file. These files are referred to as message bundles, message catalogs, or portable message files. Every programming language provides a set of tools to work with these files. For example, in programming languages, such as the C, Python, and Perl programming languages provide gettext functions for translating messages.
You create portable message files with the gettext utility. These files are in plain text, and have .po as the file extension. You send the portable message file to translators for translation, and the translators update the file with the translated text. Post translation, the .po file contains the message ID with the corresponding translated text. For example:
$ cat cs.po . . #: code.c:37 #,c-format msgid "My hovercraft is full of eels.\n" msgstr "Moje vznášedlo je plné úhořů.\n"
However, you can improve the performance of the system by converting a portable object file to a message object file. A message object file has .mo as the file extension. To convert a portable object file to a message object file, use the msgfmt utility.
This example shows how to generate localized message objects for a shell script. It assumes that you have the following shell script that has calls to the gettext() function.
#!/usr/bin/bash # # set TEXTDOMAIN and TEXTDOMAINDIR as per the gettext(1) manual page TEXTDOMAIN=test_gettext_sh export TEXTDOMAIN TEXTDOMAINDIR=/home/xxxxx/lib/locale export TEXTDOMAINDIR PATH=/usr/gnu/bin:/usr/bin export PATH # source gettext.sh for using eval_gettext and eval_ngettext . gettext.sh f="filename.dat" # Use eval_gettext or eval_ngettext if it refers to shell variables # TRANSLATORS: $f is replaced with a file name eval_gettext "\$f not found"; echo gettext "file not found"; echo echo "`eval_gettext "\\\$f not found"`" echo "`gettext "file not found"`"
For this shell script, you can create localized message objects by using the following steps:
Prepend usr/gnu/bin to your PATH environment variable in order to use the GNU versions of gettext() tools.
$ PATH=/usr/gnu/bin:$PATH
Extract messages from the shell script into a message file template using the xgettext command.
$ xgettext -c"TRANSLATORS:" -L"Shell" test_gettext.sh
A file called messages.po is created, which contains the header information and the message strings from the shell script. It also includes the explanatory comments for the translators. The following example shows an excerpt of the messages.po file:
#. TRANSLATORS: $f is replaced with a file name #: test_gettext.sh:18 test_gettext.sh:21 #, sh-format msgid "$f not found" msgstr "" #: test_gettext.sh:19 test_gettext.sh:22 msgid "file not found" msgstr ""
Create a portable message (.po) file which is specific to the translation language by using the msginit command. For example, use the following command to create a .po file for the Japanese ja_JP.UTF-8 locale:
$ msginit --no-translator --locale=ja_JP.UTF-8 --input=messages.po
A file called ja.po is created.
Translate the messages in the ja.po file.
Create the LC_MESSAGES directory in the directory specified by the TEXTDOMAINDIR environment variable.
$ mkdir -p lib/locale/ja/LC_MESSAGES
Either create symbolic links or set the LANGUAGE variable.
Create symbolic links
$ ln -s ja lib/locale/ja_JP.UTF-8
Set the LANGUAGE variable.
$ LANGUAGE=ja_JP.UTF-8:ja $ export LANGUAGE
Create the message object (.mo) file.
$ msgfmt -o lib/locale/ja/LC_MESSAGES/test_gettext_sh.mo ja.po
This example shows how to generate localized message objects for a C program. It assumes that you have the following C program that has calls to the gettext() function.
#include <stdio.h> #include <sys/types.h> #include <libintl.h> #include <locale.h> #include <time.h> /* * _() is used for the strings to extract messages. * N_() is used for the string array message to extract messages. * T_() is used for the strings to extract messages with working on LC_TIME */ #define _(String) gettext (String) #define gettext_noop(String) String #define N_(String) gettext_noop (String) #define T_(String) gettext_noop (String) #define LOCALEDIR "/home/xxxxx/lib/locale" #define PACKAGE "test_gettext" static const char *msg[] = { N_("The first message"), N_("The second message"), }; int main(int ac, char **av) { char *file = "test.dat"; int line = 40; int column = 10; time_t tloc; char time_buf[BUFSIZ]; setlocale(LC_ALL, ""); bindtextdomain(PACKAGE, LOCALEDIR); textdomain(PACKAGE); /* * By default, the characters are converted to current locale's encoding. * If this is not desired, call bind_textdomain_codeset(). For example, * if you want "UTF-8" encoding, specify "UTF-8" in the second argument. * * bind_textdomain_codeset("test_gettext", "UTF-8"); */ printf(_("This is a test\n")); printf("%s\n", _(msg[0])); printf("%s\n", _(msg[1])); /* TRANSLATORS: First %d is replaced by a line number. Second %d is replaced by a column number. %s is replaced by a file name. */ printf(_("ERROR: invalid input at line %1$d, %2$d in %3$s\n"), line, column, file); /* * strftime() works with LC_TIME not LC_MESSAGES so to get properly * formatted time messages we have to call dcgettext() with LC_TIME category. */ (void) time(&tloc); (void) strftime(time_buf, sizeof (time_buf), /* TRANSLATORS: This is time format used with strftime(). Please modify time format to fit your locale by using date '+%a %b %e %H:%M:%S' */ dcgettext(NULL, T_("%a %b %e %H:%M:%S"), LC_TIME), localtime(&tloc)); printf("%s\n", time_buf); return(0); }
For this C program, you can create localized message objects using the following steps:
Prepend /usr/gnu/bin to your PATH environment variable:
$ PATH=/usr/gnu/bin:$PATH
Extract messages from the source code into the message file template using the xgettext command:
$ xgettext -c"TRANSLATORS:" -k -k"_" -k"N_" -L"C" test_gettext.c
The messages.po file is created for the LC_MESSAGES locale category. It contains the header information and the message strings including the explanatory comments for the translators. The following example shows an excerpt of the messages.po file:
#: test_gettext.c:21 msgid "The first message" msgstr "" #: test_gettext.c:22 msgid "The second message" msgstr "" #: test_gettext.c:43 #, c-format msgid "This is a test\n" msgstr "" #. TRANSLATORS: #. First %d is replaced by a line number. #. Second %d is replaced by a column number. #. %s is replaced by a file name. #: test_gettext.c:51 #, c-format msgid "ERROR: invalid input at line %1$d, %2$d in %3$s\n" msgstr ""
Create another .po file for the LC_TIME locale category:
$ xgettext -c"TRANSLATORS:" -k -k"T_" -L"C" -o messages_t.po test_gettext.c
The messages_t.po file is created for the LC_TIME locale category.
Create portable message (.po) files which are specific to the translation language by using the msginit command.
For example, use the following command to create a portable file messages for the Japanese ja_JP.UTF-8 locale:
$ msginit --no-translator --locale=ja_JP.UTF-8 \ --input=messages.po $ msginit --no-translator --locale=ja_JP.UTF-8 --input=messages_t.po \ --output-file=ja_t.po
The ja.po and ja_t.po files are created.
Translate the created ja.po and ja_t.po files.
Create the LC_MESSAGES and LC_TIME directories in the directory specified by the LOCALEDIR variable.
$ mkdir -p lib/locale/ja/LC_MESSAGES lib/locale/ja/LC_TIME
Either create symbolic links or set the LANGUAGE variable:
Create symbolic links.
$ ln -s ja lib/locale/ja_JP.UTF-8
Set the LANGUAGE variable.
$ LANGUAGE=ja_JP.UTF-8:ja $ export LANGUAGE
Create the message objects (.mo files).
$ msgfmt -o lib/locale/ja/LC_MESSAGES/test_gettext.mo ja.po $ msgfmt -o lib/locale/ja/LC_TIME/test_gettext.mo ja_t.po
The message object files are created in the following format:
/usr/lib/locale/locale/category/textdomain.mo
The path has several components:
The default path predicate for the message object files. For example, in case of text domain collisions, the path is specified by a call to the bindtextdomain() function. In the case of third party software, the message object files will be available in /usr/share/locale directory.
The locale directory.
The locale category.
The text domain specified by a textdomain() function call. It is a unique identifier and the file name for the message catalog.
Consider the following example:
/usr/lib/locale/it_IT.UTF-8/LC_MESSAGES/mymessages.mo
where:
The locale directory. This message object contains translations for Italian language and will be used for this locale and any other which are symbolic links to this directory.
The locale category.
The message catalog name.
The Oracle Solaris gettext() APIs provide support for both Oracle Solaris and GNU-compatible message catalog files. However, some gettext() APIs are specific to the GNU-compatible message catalog files. The Oracle Solaris and GNU-compatible gettext() interfaces are as follows:
Retrieve a text string from the message catalog
Retrieve a message from a message catalog for a specific domain
Set and query the current domain
Bind the path for a message domain
Retrieve a message from a message catalog for a specific domain and category
The gettext() APIs that work only with GNU-compatible message catalog files are as follows:
Retrieve a text string from the message catalog and choose a plural form
Retrieve a text string from the message catalog for a specific domain and choose a plural form
Specify the output codeset for message catalogs for a domain
Retrieve a text string from the message catalog for a specific domain and category and choose a plural form
For more information about GNU text message handling, see the GNU gettext reference (http://www.gnu.org/software/gettext/manual/gettext.html).
For more information about gettext() functions, see the msgfmt, xgettext, and gettext man pages.
The gettext() utility provides functions and command-line tools to create and handle message object files. Oracle Solaris message objects have a different format from GNU gettext() message objects. The Oracle Solaris variants of command-line tools to handle messages are as follows:
Retrieve a text string from the message catalog
Create a message object from a portable message file
Retrieve calls to gettext() strings from C programs
The GNU variants of the command-line tools to handle messages are as follows:
Retrieve a text string from the message catalog
Create a message object from a message file
Retrieve gettext() call strings
To distinguish from Oracle Solaris tools, the GNU variant tools are prefixed with the letter g, and are symbolic links to the /usr/gnu/bin directory. For example, /usr/bin/ggettext is a symbolic link to /usr/gnu/bin/gettext.
The GNU gettext tools are part of the text/gnu-gettext package, which also includes other utilities for processing message catalogs.
For more information, see the msgcat(1), msgcmp(1), and msgmerge(1) man pages.