Skip to end of metadata
Go to start of metadata

You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 2 Next »

I18n (internationalization)

This page gives guidelines to I18n for:

  • plugin developers who would like to apply the I18n mechanism in their own plugins, so that their plugins can be translated in other languages
  • people who would like to help the Sonar community by translating parts of the Sonar ecosystem, may it be the Sonar platform itself and/or a set of Sonar Plugins

Sonar and the Sonar Plugins

Although the basics of the I18n mechanism are the same for every part of the Sonar ecosystem, the packaging differs:

  • Sonar is internationalized thanks to Language Pack plugins, each plugin offering the translation of the Sonar platform for a specific language.
    • Sonar embeds the "I18n English Pack" plugin by default
    • Other Language Pack plugins can be provided by the community, like for instance the "I18n French Pack" plugin.
  • This is different for Sonar Plugins. Each Sonar plugin will embed the translations for every language.
    • For instance, the Timeline plugin will embed all available translations in its own JAR. They will not be provided by Language Pack plugins.

To sum up

  • Sonar platform relies on plugins to get translations
  • Sonar plugins embed by themselves all the translations they need

Sonar I18n main principles

The LanguagePack extension point

Sonar I18n mechanism relies on the LanguagePack extension point, which gives information about:

  • a list of plugins for which translation is provided
  • a list of available languages for those translations

For instance, here is the EnglishPack class of the Sonar platform:

public class EnglishPack extends LanguagePack {

  public List<String> getPluginKeys() {
    return Arrays.asList("core", "design", "squidjava");

  public List<Locale> getLocales() {
    return Arrays.asList(Locale.ENGLISH);

We can see that:

  • translation is done for sonar-core-plugin, sonar-design-plugin and sonar-squid-java-plugin
    • #getPluginKeys() returns the plugin keys as defined by the [Sonar Packaging Maven Plugin]
  • only one language is available: English

The translation files

To better understand the following concepts, we'll use the sonar-i18n-fr-plugin as an exmaple to better understand the different points.

There are 2 kind of files that are used to get I18n translations:

  • Properties files
    • These are regular properties files with key/value pairs where you will put most I18n translations
    • E.g.: the French translation for the Sonar Squid Java Plugin is stored in "src/main/resources/org/sonar/i18n/"
  • HTML files
    • In case of rule descriptions, which might be long and need HTML tags, you will store the translations in HTML files to ease your work
    • Each file will be named after the key of the rule it translates, and store in a folder named after the plugin that defines this rule (and with the local attached to it)
    • E.g.: the French translation for the Squid Architectural Constraint rule is stored in "src/main/resources/org/sonar/i18n/squidjava_fr/ArchitecturalConstraint.html"

Encoding for the properties files = UTF-8

In the Java API, properties files must be encoded in ISO-8859 charset. Without good tooling, this can be quite annoying to write translation for languages that do not fit in this charset.
This is why we deciced to encode the properties files in UTF-8, and let Maven turn them into ASCII at build time thanks to native2ascii-maven-plugin (check the French plugin POM).
This makes the process of writing translations with a standard editor far easier.

Conventions for the I18n keys

Here are the conventions you have to know about key namings:

  • For metrics:
    • The key for their name is ""
    • The key for their description is "metric.metric-key.description"
  • For rules:
    • The key for their name is ""
    • The description is in a separate HTML file named "src/main/resources/org/sonar/i18n/plugin-key_locale/rule-key.html"
    • The key for their parameters description is "rule.plugin-key.metric-key.param.parameter-key"
  • For widgets:
    • The key for their title is "widget.widget-key.title"
    • The key for their description is "widget.widget-key.description"
    • Any other key starts with "widget.widget-key."
  • For pages:
    • The key for the name that will be shown on the left menu is ""

For any other key that a Sonar Plugin would define for its own I18n, the key must start with : "plugin-key."

Want to contribute to I18n in Sonar?

You are a plugin developer

Here are the main steps:

  1. Implement the LanguagePack extension point. In your case:
    • #getPluginKeys() should return only the key of your plugin
    • for each language that will be translated in your plugin, you should add the corresponding locale to #getLocales()
  1. Once you've implemented this extension point, you obviously have to declare this extension in your plugin class
  1. Use the I18n mechanism in your code
    • On Java side, use the I18nManager class
    • On Ruby on Rails side, use the #message helper method to translate your text
      • message('mypluginkey.a_key')
      • message('mypluginkey.a_key', :default => 'This is the default message')
      • {{message('mypluginkey.a_key')}, :params => [,]}
  1. Add translation files into the "src/main/resources/org/sonar/i18n/" folder
    • 1 properties file per language
      • If you need to provide parameters for the translation (like in the last exemple 3 lines above), an entry would look like: {{mypluginkey.a_key=This is a message with 2 params: the first "
        Unknown macro: {0}
        " and the second "
        Unknown macro: {1}
    • 1 folder per language if you define new rules in your plugin and you need to translate their description

You want to create a Language Pack plugin to offer a new translation to the Sonar platform

// ...

  • No labels