Jump to Navigation

Gettext: extracting translations

Symptoms

You have prepared your sources for translation with gettext. You actually have translations available, but those files contain too many translations (for example, for a larger project). Alternatively, you want to see if those files may contain translations you can use. You need to get only relevant translations extracted1.

Solution

You can extract the translations from the existing files using the default tooling.

Assumptions

  • You have access to the sources
  • The sources are prepared to use gettext
  • There are existing translations you want to (re)use
  • You have GNU gettext tooling instaled

Procedure

First, you need to prepare a translation template (a pot file). Next, you can retrieve translations for strings in that pot file from the existing po files.

Preparing the pot file

To get all translatable strings in the pot file you can use xgettext.

# Replace OUTPUTFILE with the pot file you want to generate, for example po/messages.pot
# Replace SOURCEFILE1, SOURCEFILE2 etc. with the sources
xgettext -o OUTPUTFILE SOURCEFILE1 SOURCEFILE2

For code written in C something like this should work fine, from the root of your project:

xgettext -o po/messages.pot -k_ $(find . -name '*.h' -o -name '*.c')

The -k_ argument is needed because for C code xgettext does not recognize the often used abbreviation function _.

Creating the po files

For each language, get the translations with msgmerge and discard obsolete translations with msgattrib:

# Replace OLDPOFILE with the file of old translations
# Replace POTFILE with the POTFILE you just created
# Replace POFILE with the output file
msgmerge -N OLDPOFILE POTFILE | msgattrib --no-obsolete > POFILE

The -N option disables fuzzy matching. I would recommend using it, especially if you do no speak the target languages.

If you have several files with translations you want to combine, try adding them to the msgmerge invocation as -C EXTRAFILE.

Something like the following loop may work well:

# Invoke from the directory in which you want the po-files placed
# Replace PATH_TO_OLD_POFILES with the directory containing the old translation files
# Replace POTFILE_LOCATION with the location of the pot-file.
OLDPATH=PATH_TO_OLD_POFILES
POTFILE=POTFILE_LOCATION
for oldfile in $OLDPATH/*.po; do
msgmerge -N $oldfile $POTFILE | msgattrib --no-obsolete > $(basename $oldfile)
done
  • 1. My use case: I wanted to extract the getopt(1) translations from the util-linux sources
Tags:


Technical_article | by Dr. Radut