Repository resource bundles
This page introduces repository resource bundles, how they are used in the Hippo product and how to use them in your own plugins.
Repository resource bundles are used to provide translations for strings that are introduced through configuration in the repository. Examples are:
- Translations for document type names, fields names and hints
- Translations for image set names and field names
- Translations for validator feedback texts
Repository resource bundles are one source for providing translations for the CMS UI. For more details, see CMS UI localization.
Bootstrapping
Repository resource bundles are imported using the Hippo bootstrap mechanism, and can be exported using the auto-export plugin. To import a resource bundle, specify an additional initialize item with a “hippo:resourcebundles” property and as property value specify the json file containing the resource bundle(s) that should be imported, for example:
<sv:node sv:name="myhippoproject-translations"> <sv:property sv:name="jcr:primaryType" sv:type="Name"> <sv:value>hippo:initializeitem</sv:value> </sv:property> <sv:property sv:name="hippo:sequence" sv:type="Double"> <sv:value>30000.2</sv:value> </sv:property> <sv:property sv:name="hippo:resourcebundles" sv:type="String"> <sv:value>translations.json</sv:value> </sv:property> </sv:node>
An example translations.json file:
{ "hippo:types": { "myhippoproject:book": { "en": {"myhippoproject:title": "Book title"}, "nl": {"myhippoproject:title": "Boek titel"} } }, "myhippoproject:translations": { "channelmanager": { "awesomecomponent": { "en": {"name": "value"} } } } }
The above example loads several resource bundles providing translations for the document type “myhippoproject:book”, and for a project specific section for a project specific plugin.
The content of the file is always loaded into the repository at the path “/hippo:configuration/hippo:translations”. The resource bundle can be placed any level deep.
Merge behavior
It is possible to add multiple initialize items that each import their own set of resource bundles. In case the content overlaps, the resource bundles are merged. For example:
<sv:node sv:name="myhippoproject-translations"> <sv:property sv:name="jcr:primaryType" sv:type="Name"> <sv:value>hippo:initializeitem</sv:value> </sv:property> <sv:property sv:name="hippo:sequence" sv:type="Double"> <sv:value>30000.3</sv:value> </sv:property> <sv:property sv:name="hippo:resourcebundles" sv:type="String"> <sv:value>translations1.json</sv:value> </sv:property> </sv:node> <sv:node sv:name="myhippoproject-translations"> <sv:property sv:name="jcr:primaryType" sv:type="Name"> <sv:value>hippo:initializeitem</sv:value> </sv:property> <sv:property sv:name="hippo:sequence" sv:type="Double"> <sv:value>30000.3</sv:value> </sv:property> <sv:property sv:name="hippo:resourcebundles" sv:type="String"> <sv:value>translations2.json</sv:value> </sv:property> </sv:node>
And the files
translations1.json
{ "hippo:types": { "myhippoproject:book": { "en": {"myhippoproject:title": "Book title"}, "nl": {"myhippoproject:title": "Boek titel"} } } }
translations2.json
{ "hippo:types": { "myhippoproject:book": { "en": {"myhippoproject:title": "Updated book title"}, "nl": {"myhippoproject:other": "Ander veld"} } } }
Will be merged as:
{ "hippo:types": { "myhippoproject:book": { "en": {"myhippoproject:title": "Updated book title"}, "nl": { "myhippoproject:title": "Boek titel", "myhippoproject:other": "Ander veld" } } } }
Using resource bundles in code
To use translated labels in Wicket code, the helper class org.hippoecm.frontend.l10n.ResourceBundleModel can be used such as in the following code snippet. This snippet could be used by the fictitious custom plugin in the example in section “Bootstrapping” to load the translation for the key “name” for the locale of the current user:
final String bundleName = "myhippoproject:translations.channelmanager.awesomecomponent"; final String key = "name"; final Label label = new Label("label-wicket-id", new ResourceBundleModel(bundleName, key));
In case the label could not be found due to a coding or configuration error, the ResourceBundleModel returns “???” + key + “???” so you get visual feedback while setting up your Hippo project. See also the rules for the ResourceBundle below.
Under the hood, the ResourceBundleModel loads its data using the LocalizationService. It is also possible to call the LocalizationService directly such as in the following code snippet. This snippet shows how to obtain the English resource bundle containing the translations for the fictitious custom plugin in the example in section “Bootstrapping”:
final String bundleName = "myhippoproject:translations.channelmanager.awesomecomponent"; final String locale = "en"; final LocalizationService localizationService = HippoServiceRegistry.getService(LocalizationService.class); if (localizationService != null) { final ResourceBundle bundle = localizationService.getResourceBundle(bundleName, locale); if (bundle != null) { // ... } } // …
Conventions
When you examine the resource bundles that are bootstrapped by the product, you’ll notice two conventions:
- The # character is used to separate a label and a sub label for document field hints. For example when you enable the “blog” feature from Essentials, you see that for the type “myhippoproject:author” a hint is defined for several fields, for instance for “account”: “myhippoproject:accounts#hint”.
- The = character is used to separate a label and possible sub values, for instance in the resource bundle for the type “hippostd:date” which contains keys such as “hippostd:dayofweek=1”.