Candlepin uses gettext-commons to support internationalization.

Internally, we are using zanata for translations. The configuration is controlled by a zanata.xml file located in the po directory. You will need to set up the zanata-client package.

zanata-client is quite broken in Fedora (often) whenever dependency Java rpms are updated. Instead the authors currently recommend using the ivy setup outlined here.


The regular process for updating translations consists of extraction of resources that should be localized, providing translations, and compilation of resource bundles.

  1. buildr gettext:extract will extract all strings in calls. This command will generate a catalogue file (keys.pot) in the po directory in the common subproject.
  2. buildr gettext:merge will merge the keys from the catalogue file into locale-specific .po files.
  3. From the common/po directory, push the key files to zanata: zanata-cli push --src-dir $PWD --trans-dir $PWD
  4. From the common/po directory, pull down the latest translations from zanata: zanata-cli pull --src-dir $PWD --trans-dir $PWD
  5. Validate the translations, ensure there are no un-escaped single quotes: buildr validate_translation
  6. Fix any errors: buildr validate_translation:fix

Other Tips

  • use poedit (or vim, or emacs, or some other WMD) to provide translations for extracted keys.
  • The next build will compile the pot files into java class files in common/target/generated-source/org/candlepin/common/i18n. The file names are Messages_LOCALE.class.
  • If you wish to replace the latest po files on the server, use: zanata-cli pull --src-dir $PWD --trans-dir $PWD --import-po (this is not normally required). To import the po files, you need to ensure that you have merged the keys as shown above.

Zanata Client Config

  • add a ~/.config/zanata.ini with content like:

    # "zanata" in this case is just a name for the
    # server
    zanata.url =
    zanata.username =  myfedorausername
    # need to generate on zanata "my profile page"
    zanata.key = cfd50f51cd8ed9876f3f126a7be431bb

How To Code With It

Things of Note

  • file determines the name and the package of resource bundles.
  • When creating an instance of I18n, I18nFactory.READ_PROPERTIES flag is required for the property file mentioned above to take effect
  • I18nFactory.FALLBACK flag is required during instantiation of I18n if you want to see non-translated strings when resource bundle for a specific locale is not available. The default behaviour is to throw MissingResourceException.
  • the default locale is en_US; all strings in this locale will be returned unchanged.
  • Currently only non-singleton (as in guice scope) resources can use localized strings.

Internal Bits

The Guice I18nProvider allows guice to inject instances of I18n into resource classes (or other non-singleton objects managed by guice). The provider relies on ‘Accept-Language’ http header to determine the locale.

In Code

  • Inject I18n into the object of your choice.
  • Then (assuming instance variable name is i18n):"goodbye, cruel world.");
Last modified on 12 September 2016