Wednesday, September 23, 2015

Using gettext Library for Translations

GNU gettext is a C library which lets you add translation support to your program with fallbacks to original text if no translation is available.

Here's a list of links to how you use the different utils in the gettext package:

See http://stackoverflow.com/questions/1003360/complete-c-i18n-gettext-hello-world-example for a hello world example using gettext.

See http://www.gnu.org/software/libc/manual/html_node/Locating-gettext-catalog.html for selecting translation file in code.
See http://www.gnu.org/software/libc/manual/html_node/Translation-with-gettext.html for using gettext in code.
See http://www.gnu.org/software/gettext/manual/html_node/lib_002fgettext_002eh.html for using gettext.h instead of libintl.h to get extended capabilities such as pgettext (adds context) and support for replacing gettext commmands with no-op if gettext is not installed on system. See http://www.gnu.org/software/gettext/manual/html_node/PO-Files.html for how PO files work (text files translations).
See http://www.heiner-eichmann.de/autotools/using_gettext.html, http://www.gnu.org/software/gettext/FAQ.html, and http://www.gnu.org/savannah-checkouts/gnu/gettext/manual/html_node/xgettext-Invocation.html for some information on using xgettext to extract strings for translation into a POT file.
See http://www.gnu.org/software/gettext/manual/html_node/msginit-Invocation.html on how msginit generates language specific translation files (PO) from POT file.
See http://www.gnu.org/software/gettext/manual/html_node/msgmerge-Invocation.html on how msgmerge generates updated language specific translation files (PO) from a changed POT file.
See http://www.gnu.org/software/gettext/manual/html_node/msgfmt-Invocation.html on how msgfmt generates binary translation files (MO) from human readable translation files (PO).


See http://www.gnu.org/software/gettext/FAQ.html#integrating_noop for troubleshooting missing translations


Simple example

  1. Copy gettext.h from /usr/share/gettext/ to your component or project.
  2. Set macro ENABLE_NLS to 1
  3. Include gettext.h in your cpp file.
  4. Example code:
    ::setlocale(LC_ALL, "");
    
    // Set directory to search for translation files in (which contains
    
    // en_US.UTF-8/LC_MESSAGES/hellogt.mo)
    
    bindtextdomain("hellogt", ".");
    
    // Set name of translation file to use (hellogt.mo)
    
    textdomain( "hellogt");
    
    std::cout << gettext("hi") << std::endl;
    
    std::cout << pgettext("bob", "hello, world!") << std::endl;
    

Generate translation files

#Common
find . -name "*.cpp" > files.txt
xgettext --package-name mygt --package-version 1.2 --default-domain mygt --output mygt.pot -f files.txt

#Spanish translations
sudo locale-gen es_MX.UTF-8
msginit --no-translator --locale es_MX --output-file mygt_spanish.po --input mygt.pot
mkdir -p ./es_MX.UTF-8/LC_MESSAGES
msgfmt --check --verbose --output-file ./es_MX.UTF-8/LC_MESSAGES/mygt.mo mygt_spanish.po

#Norwegian translations
sudo locale-gen nb_NO.UTF-8
msginit --no-translator --locale nb_NO --output-file mygt_norwegian.po --input mygt.pot
mkdir -p ./nb_NO.UTF-8/LC_MESSAGES
msgfmt --check --verbose --output-file ./nb_NO.UTF-8/LC_MESSAGES/mygt.mo mygt_norwegian.po

Update translation files

Add changes in code to language specific translation file:
xgettext --package-name mytgt --package-version 1.2 --default-domain mygt --output mygt.pot -f files.txt
msgmerge mygt_norwegian.po_old mygt.pot --output-file=mygt_norwegian.po_new
use msgfmt to generate new mygt.mo file from mygt_norwegian.po_new.