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
Although the basics of the i18n mechanism are the same for every part of the ecosystem, the packaging differs depending on what you are developing:
- Translations for the Sonar Core Platform: making the Sonar Core Platform available in a new language requires to develop and publish a new Language Pack plugin.
- By default Sonar embeds the English Pack.
- All other Language Pack plugins (like the French Pack plugin) are hosted in the Plugins Forge (https://svn.codehaus.org/sonar-plugins/trunk/l10n/), are maintained by the community and are available through Update Center (category "Localization").
- Translations for the Sonar Community Plugins: open-source plugins of the Sonar Community (hosted in the Plugins Forge) must embed only the bundles for the default locale. Translations will be done in the Language Pack plugins.
- Translations for other Plugins: closed-source/commercial/independant plugins must embed the bundles for the default locale and the translations for every language they want to support.
- Sonar Core Platform and Sonar Community Plugins rely on Language Pack plugins to get translations
- Other independant Sonar plugins embed by themselves all the translations they need
There are 2 types of files for localized messages:
- They are used for rule descriptions, which might be long and need HTML tags
- These files must be stored in the package "org.sonar.l10n.<plugin key>_<language>"
- Starting with Sonar 3.0, the files should be stored in the package "org.sonar.l10n.<plugin key>_<language>.rules.<repository key>" (backward compatibility is ensured for l10n plugins which use the former location)
- The name of these files must be the key of the rule they translate
- Example: the French description of the Squid Architectural Constraint rule is "src/main/resources/org/sonar/i18n/squidjava_fr/ArchitecturalConstraint.html"
- Or, starting with Sonar 3.0: "src/main/resources/org/sonar/i18n/squidjava_fr/rules/squid/ArchitecturalConstraint.html" (as "squidjava" is the plugin key and "squid" the repository key)
In the Java API, properties files are supposed to 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.
HTML files must also be encoded in UTF-8.
Naming conventions for keys
Here are the conventions you have to know about keys :
metric.ncloc.name=Lines of code
metric.ncloc.description=Non Commenting Lines of Code
Name of notification channel
Subscription to notification channel
notification.dispatcher.ChangesInReviewAssignedToMeOrCreatedByMe=Changes in review assigned to me or created by me
Description of rule parameter
rule.pmd.VariableNamingConventions.param.memberSuffix=Suffix for member variables
|Dashboard name, since 2.14.|
|Qualifier name, since 2.13.|
widget.alerts.description=Display project alerts
Description of widget property
Any other widget message
widget.alerts.tooltip=Threshold is raised
Page names shown in the left sidebar
Any other keys used in a page
Category name of properties, since 2.11
Property name, since 2.11
Property description, since 2.11
Any other keys used by plugin
How to use localized messages ?
Ruby on Rails API
This API is used when implementing Ruby widgets or pages. It's really simple, a single method must be used :
Options are :
:default is the default value when the property key does not exist in bundles. If it's not set, then the key itself is returned.
:params is an array of string message arguments.
message('cloud.size', :default => 'Cloud')
message('with.arguments', :params => ['First', 'Two'])
message('with.arguments', :params => ['First', 'Two'], :default => 'Not found')
Of course the Rails framework provides other formatting methods like :
# localize dates or datetimes
GWT provides its own mechanisms to internationalize components. The static technique is the most efficient and must be used into Sonar GWT extensions. Read the Google documentation for more details.
org.sonar.api.i18n.I18n is available for server extensions. Batch extensions are not supported yet and can not load bundles.
How to create a Language Pack for the Sonar Community
A Language Pack defines bundles for the Sonar Core Platform and for Sonar Community Plugins. The easiest way to create a new pack is to copy the French Pack and to adapt it to your language.
From there, you can regularly check bundles from:
- The English Pack - which contains all the bundles of the Sonar Core Platform that should be translated (you are not obliged to translate them all at once, you can proceed with baby steps)
- The following Sonar Community Plugins which support L10n (as of August 2012):
- Tab Metrics
- Useless Code Tracker
- Violation Density
- Widget Lab
How to localize an independant plugin
This part applies if you are developing a commercial / closed-source plugin, or an open-source plugin that is not part of the Sonar Community Plugins.
Such plugins must embed their own bundles. Bundles must be added to src/main/resources with the following convention names :
- Standard messages : org/sonar/l10n/<plugin key>_<language>.properties
- Rule descriptions :
- Up to Sonar 3.0: org/sonar/l10n/<plugin key>_<language>/*.html
- Since Sonar 3.0: org/sonar/l10n/<plugin key>_<language>/rules/<repository key>/*.html
The default bundle is mandatory, and must be the English translation. For example the plugin with key "mysonarplugin" must define the following files in order to enable the French translation: