Skip to end of metadata
Go to start of metadata

Work to internationalize the platform.

Some general points

  • Manage and utilize user locale
  • Unit handling and formatting support
  • Metadata localization lookup system and integration
  • Add message codes to messages, so that support can deal with messages in the supported languages


Externalize text properties from GWT - mostly done. Not done

See also


Server messages need to be internationalized by the standard Java Means. In addition to that, message codes need to be supplied,
so that if a customer pastes a message in the form of

we would know that we need to run for shelter.


Agent messages need to be internationalized by the standard Java Means. In addition to that, message codes need to be supplied,
so that if a customer pastes a message in the form of

we would know that we need to run for shelter.


The situation for plugins is a bit different than for Agent or Server proper, as two pieces of data need translations:

  • properties in the plugin descriptor
  • messages from the plugin code itself

Those need to be treated differently, as one consists of metadata and the other of messages generated at runtime.

Plugin metadata

Currently plugin metadata like the description or display names of things are stored after parsing in the database. So e.g.

will return the description text that is parsed at plugin parse time and then stored in the database.

In order to change that, we need to provide alternate translations in the plugin

Options are:

  • require all properties (descriptions, display names) to be equipped with ${..} expressions for translation, where the ${..} expression points to a property in a property file that can be internationalized. Drawback is that even for the default locale, a translation file is required.
  • Leave the properties as they are and deduct the keys in the property file by the hierarchy e.g. platform.osx.service.cpu.Cpu.userLoad=User Load

The latter approach has the advantage that plugins can be kept as they are without any need to translate exisiting ones to continue working; in the first case, it is much more clear which key is meant, as this is explicitly given in the ${..} expression. Especially having the ${..} expression present will help to determine what needs to be translated and what not.
Side note: actually the property would not even be a ${..} expression, but could rather just something to start with a unique character that is normally not used in property texts as starting character like like e.g. a percent sign or the hash mark.

Next this property needs to be made available to the code.

  • Instead of storing the properties in the database columns directly, we could modify the schema so that they are links which point to a table with translations; the user would need to pass his language into the query and the relation from ResourceType to translation would be fetched by an explicit join with this translations table.
  • Metadata is stored as before, but the individual columns are no longer containing the string, but the ${..} expression. This would then be replaced by the translated value.

In any case we need a mechanism to pass in the desired language from the UI / CLI, so that the lower layers can use it to select the translation. As the Subject is passed around from the UI to the lower levels, this could be a good location to attach the desired (and fallback?) locale.

Cut through of a clients request

The next figure shows a cut through from user to database:

When a request comes in via Browser or RESTInterface, the language of the user is determined via content negotiation and attached to the subject, which is then passed into the EJB layer. For the CLI we could introduce a set language command, that allows to set the language for a session. Another option could be to store the desired language for a user with the other users information (name, ..) and always use this pre-defined value (conneg is desired).
Within the EJB layer, the language from the subject is then stored as a thread local and can this way be passed into the domain layer.
Entities in the domain layer that have translatable properties can then have a @PostLoad hook, which fetches the translated value from the cache.

The cache itself then gets the respective item and if it is not there, it can use a cache loader to retrieve it from the database in a special translations property table:

key locale translation
a.b de A und B
a.b en A and B
a.b fr A èt B

Where the primary key is the tuple (key,locale). The table still needs a "link" to the plugin - either implicit via prefix in the key or explicit via fk relation.

On server startup, the strings for the default locale will be preloaded into the cache.

Deploying metadata

The translations come from properties files bundled with the plugin and need to be stored in the server. To do this, when running the plugin deployer, the properties files are loaded in the server and then written to the database table. On plugin upgrades all old properties are first deleted from the database and then the new translations are just added in a batch.

Plugin verifier

The plugin verifier needs to be augmented to check that the ${..} expressions actually at least resolve to a default locale. Plugin builds should fail if not all expressions are satisfied.

Messages from code

Messages from code are always directly returned from the running plugin, so that the standard mechanisms of I18N can apply.

Meeting minutes

Dec 21st, 2011

17:10:14 <jbott> Meeting ended Wed Dec 21 16:09:58 2011 UTC. Information about MeetBot at . (v 0.1.4)
17:10:14 <jbott> Minutes:
17:10:14 <jbott> Minutes (text):
17:10:14 <jbott> Log:


There was some initial work done on generating properties files from plugin metadata. It may not be the best approach though as it parses the plugin xml differently from the PluginMetadataParser. The code is available at org.rhq.core.clientapi.agent.metadata.i18n.PropertiesGenerator.

  • Metadata (plugin.xml) localization property sheet generator
translation translation Delete
i18n i18n Delete
Enter labels to add to this page:
Please wait 
Looking for a label? Just start typing.