Versions Compared


  • This line was added.
  • This line was removed.
  • Formatting was changed.
titleI18n (internationalization)Table of Contents

Table of Contents


This page gives guidelines to I18n for:

  • Plugin developers who would like to apply the


  • i18n mechanism in their own plugin, so that this plugin can be available in several languages
  • People who would like to help the


  • community by making the


  • platform available in a new language
Table of Contents

Sonar and the Sonar Plugins


Although the basics of the I18n i18n mechanism are the same for every part of the Sonar ecosystem, the packaging differs if you want to apply this i18n mechanism to the Sonar core platform or to one Sonar plugin:


depending on what you are developing:

  • Translations for SonarQube: making SonarQube available in a new language requires you to develop and publish a new Sonar Language Pack plugin.
    • By
    default, Sonar
    • default SonarQube embeds the
    • English Pack
    " plugin
    • .
    • All other Language Pack plugins, like the
    • French Pack
    • plugin,
    • are hosted in the
    Sonar Plugin forge ( Sonar
    • community, and are available through
    the Sonar update center.
  • This is different for Sonar Plugins, each Sonar plugin is in charge to embed its own translations. Of course supporting i18n mechanism is not mandatory for a plugin but in that case the plugin will only be available in the default development language.
    • Marketplace (category "Localization").
  • Translations for the SonarQube Community Plugins: open-source plugins from the SonarQube Community (hosted in the Plugins Forge) must embed only the bundles for the default locale (en). Translations will be done in the Language Pack plugins.

  • Translations for other Plugins: closed-source/commercial/independent plugins must embed the bundles for the default locale and the translations for every language they want to support.
titleTo sum up
  • Sonar platform relies on plugins to get translations
  • Sonar plugins embed by themselves SonarQube Platform and SonarQube Community Plugins rely on Language Pack plugins for translations
  • Other independent SonarQube plugins must themselves embed 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
  • 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
    • Just for reminder, it is possible to pass arguments to the translated string. Such an entry would look like:
      mypluginkey.a_key=This is a message with 2 params: the first "{0}" and the second "{1}".
    • 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"


Translation Bundles

Localized messages are stored in properties files:

  • These are regular properties files with key/value pairs where you put most translations
  • These files must be stored in the org.sonar.l10n package (usually in the src/main/resources/org/sonar/l10n directory)
  • The names of these files must follow the convention "<key of the plugin to translate>_<language>.properties", for example "" or "" for core bundle. See sonar-packaging-maven-plugin for details on plugin key derivation.
  • Messages can accept arguments. Such entries would look like:

    No Format is a message with 2 params: the first "{0}" and the second "{1}".
titleUTF-8 encoding

In the Java API, properties files are supposed to be encoded in ISO-8859 charset. Without good tooling, this it can be quite annoying to write translation translations for languages that do not fit in this charset.
This is why we deciced decided 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 POMpom.xml). This makes the process of writing translations with a standard editor far easier.
HTML files must also be encoded in UTF-8.


Naming conventions for keys

Here are the conventions you have is what you need to know about key namingsconventions for keys:

  • 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:


  • 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')
    • Wiki Markup
      {{message('mypluginkey.a_key'), :params => \[,\])}}


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

Here are the main steps:






Metric name of code


Metric description

metric.ncloc.description=Non Commenting Lines of Code<channel key>

Name of notification channel

notification.dispatcher.<dispatcher key>

Subscription to notification channel

notification.dispatcher.ChangesInReviewAssignedToMeOrCreatedByMe=Changes in review assigned to me or created by me


Rule name Instantiation

rule.<repository>.<key>.param.<param key>

Description of rule parameter

rule.pmd.VariableNamingConventions.param.memberSuffix=Suffix for member variables

dashboard.<key>.nameDashboard name, since Chauds



Qualifier name, since 2.13.




Widget name


Widget description

widget.alerts.description=Display project alerts

widget.<key>.property.<property key>.name
Name of widget property severity
widget.<key>.property.<property key>.desc
Description of widget property selected, 
severity used to initialize the dropdown list of widget
Name of item of dropdown list 


Any other widget message

widget.alerts.tooltip=Threshold is raised

<page key>.page

Page names shown in the left sidebar

<page key>.*

Any other keys used in a page


property.category.<category key>

Category name of properties, since 2.11


property.category.<category key>.description
Short description of category of properties, since 3.6property.category.General.description=General properties of SonarQube
property.category.<category key>.<subcategory key>
Subcategory name of properties, since exclusions
property.category.<category key>.<subcategory key>.descriptionShort description of subcategory of properties, since of global exclusions


Property name, since 2.11 encoding


Property description, since 2.11

property.sonar.sourceEncoding.description=Source encoding

<plugin key>.*

Any other keys used by plugin


How to read localized messages from a plugin extension?

The component org.sonar.api.i18n.I18n is available for web server extensions. Scanner extensions can not load bundles.

Writing a Language Pack

A Language Pack defines bundles for SonarQube and/or plugins.

Creating a Language Pack

The easiest way to create a new pack is to copy the French Pack and adapt it to your language.

Maintaining a Language Pack

In the pom file, set the versions of SonarQube and of the plugins you want to translate.

When it's time to update your language pack for a new version of SonarQube or a plugin, the easiest way to see what keys are missing is to run:

Code Block
mvn test

If the build fails, it means that some keys are missing. Go to target/l10n to check the reports for each bundle.

Missing keys are listed under 'Missing translations are:'

Code Block
Missing translations are:
code_viewer.no_info_displayed_due_to_security=Due to security settings, no information can be displayed.

Each time you add a new bundle or update an existing one, please create a JIRA ticket on the corresponding L10n component in order to track changes.

Localizing a Plugin

This section applies if you are developing a closed-source plugin, or an open-source plugin that is not part of the SonarSonarQube Community Plugins forge.

If your plugin falls in this category, it must embed its own bundles. Bundle must be defined in src/main/resources/org/sonar/l10n/<plugin key>_<language>.properties

The default bundle is mandatory, and must be English. For example the plugin with key "mysonarplugin" must define the following files in order to enable the French translation:

  • org/sonar/l10n/
  • org/sonar/l10n/