This site has been retired. For up to date information, see handbook.gnome.org or gitlab.gnome.org.


[Home] [TitleIndex] [WordIndex

Migrating from Intltool to Gettext

It used to be that Gettext could only translate strings in source code, and some limited other formats. Since about version 0.18, Gettext has been adding support for a lot more file formats that are used in modern GNOME desktop applications. This has slowly been making Intltool obsolete, which was invented to bridge that gap between what Gettext supported and what applications needed.

This is a migration guide for moving your Intltool-using project to pure Gettext.

Prerequisites

First make sure that you are prepared to support a recent enough version of Gettext. Here are the versions of Gettext in which support was added for files that Intltool was previously used for:

(This information taken from Gettext's release announcements, http://savannah.gnu.org/news/?group_id=425)

Conversely, these are the Gettext versions packaged by major Linux distributions at the time of writing:

If you're working on a core GNOME package, you don't have to be concerned, but third-party application developers may want to check that they are not making their package impossible to build on a platform that they still want to support.

Remove Intltool

Start by removing mentions of Intltool from anywhere throughout your whole build chain:

Upgrade to a modern Gettext

Gettext has the peculiarity that if you ask for a particular version of it in your build system, then you get exactly that version, and not any later version. So depending on what platforms you want to support (see above), you may want to pick the highest version that's common between all your supported platforms, even if you don't need the latest functionality from that version. Otherwise, you wouldn't be able to take advantage of as many bug fixes as possible. For the rest of this document, we'll assume that 0.19.7 is the version you're upgrading to.

You will also need a po/Makevars file, if you don't have one yet. Many Intltool-using programs didn't. A template for this file called po/Makevars.template is installed by modern versions of Gettext's setup program "autopoint".

Add rules for merging translations back into non-source files

Some files have translatable strings extracted at build time, but the translations themselves are fetched at runtime; these include source code, GtkBuilder XML files, and GSettings schema files. Other files need to have translations merged back into them at build time, before they are installed: these include .desktop files and AppData files. (If you don't have any files that need merging, then you can skip this section.) As an example, we'll use a .desktop file called com.example.Foo.desktop.

The way it works is that Gettext extract translatable strings from a .desktop.in file into your .pot file. The translators translate those strings and put them in the .po files, and so your build process needs to merge the translated strings back into the .desktop file. You commit the .desktop.in file to version control, and not the .desktop file. This is how Intltool worked as well internally, but with Gettext it's a transparent make rule.

com.example.Foo.desktop: com.example.Foo.desktop.in
    $(AM_V_GEN)$(MSGFMT) --desktop --template $< -d $(top_srcdir)/po -o $@

For an XML format such as AppData, you would replace --desktop by --xml in the make rule above.

Check your work

The upshot of all this should be that you get exactly the same results with one less dependency. So, check your .pot file by first making a backup copy and then updating it: run make -C po mypotfile.pot-update. (That is, if your .pot file is named po.mypotfile.pot, append -update to the end of it.) Diff the updated .pot file against the backup copy; you may see formatting differences, but you should not see any strings being removed.


Addendum: Translate other XML formats

These instructions are outdated and need to be rewritten to use https://www.gnu.org/software/gettext/manual/html_node/Preparing-ITS-Rules.html instead of ITS Tool.

There are still other, more obscure XML formats that Gettext does not handle. For these cases, we have http://itstool.org/.

ITS Tool extracts translatable strings from XML files using ITS rules, which are a W3C standard; Intltool did the same thing, but using an ad-hoc notation which made some XML files invalid.

(It's planned for Gettext to support ITS rules natively in the future, in which case this section will become obsolete. This section does contain a few annoying hoops to jump through, and it would be great if those went away with Gettext ITS rule support.)

For this example, we'll use a MIME type description file called foo-mime.xml. Following this example should make it possible for people to still build your package even if they don't have ITS Tool installed; it would only be a hard requirement for building from a fresh checkout from version control.

foo-mime.pot: foo-mime.xml.in
    $(AM_V_GEN)$(ITSTOOL) -o $@ $<

foo-mime.xml: foo-mime.xml.in
    $(AM_V_GEN)$(ITSTOOL) -j $< -o $@ $(top_srcdir)/po/*.gmo

Now, build and check that:

In case the first two conditions are not satisfied, then ITS Tool's default ITS rules were not enough, and you need to write a custom ITS rule. The default rule is to translate text inside of elements, and skip text inside attribute values. For MIME types, this works fine; only the <comment> elements need to be translated, and the translations become <comment xml:lang="en"> elements as they are merged back in.

A custom ITS rule set will look basically like this:

<its:rules xmlns:its="http://www.w3.org/2005/11/its" version="1.0">
  <its:translateRule translate="no" selector="//some-element"/>
  <its:translateRule translate="yes" selector="//@some-attribute"/>
  <!-- Add more as needed -->
</its:rules>

That is, you can tell it to ignore text inside of some elements, and you can tell it not to ignore text inside of some attributes. You can also use any other XPath expressions inside the selector attributes, so it can be as complicated as you need it to be.

Tell ITS Tool to use your custom rules by adding an -i myrules.its flag to the $(ITSTOOL) invocation in the first make rule above (the rule that builds the .pot file from the .xml.in file.) You can see an example of complicated ITS rules in action, in the data/ directory of the gtksourceview project.


2024-10-23 11:23