i18n API
This page describes the Magnolia i18n API, which is based on standard Java resource bundles.
Overview
The Magnolia i18n API is based on Java resource bundles and related classes. Among the main advantages of this API are:
-
a mechanism to automatically load bundles, eliminating the need to handle bundle base names
-
merging bundles into one large bundle
-
automatic generation of keys for Magnolia items such as template definitions, dialogs, apps and similar things
The base – Java message bundle
Java provides an API to load resource properties files for the purposes of internationalization.
Message bundle
A message bundle
(resource
bundle in Java) is a collection of .properties
files. Each file
contains key-value pairs of translated user interface text such as
labels and messages. The keys in all files of the same bundle are
identical but the values are language-specific translations.
A message bundle must contain at least one .properties
file. The files
are named after the language (locale):
<bundle-name>_<locale>.properties
, for example,
app-pages-messages_en.properties
. Every Magnolia module should provide
its own message bundle. If a module installs several apps, each app
should have its own message bundle.
Bundle basename and location
Typically message bundle files are located within the resources
directory of a Java (Maven) project. For example, the files could be in
the src/main/resources/com/example/foobar/messages
directory:
src/ └── main/ └── resources/ └── com/ └── example/ └── foobar/ └── messages/ ├── app-texts_en.properties └── app-texts_de.properties
Working with the ordinary Java internationalization API you have to know
the basename to load a message bundle. The basename for the above
bundle would be com.example.foobar.messages.app-texts
. The basename
reflects the location within the module by the dot notation. Magnolia
allows you to use this plain
Java internationalization API and
provides utility classes to operate with it. However, we recommend using
the Magnolia i18n API.
Automatic loading of message bundles from the Magnolia i18n folder
The Magnolia i18n API automatically loads message bundles if they are kept in the appropriate folders:
Location of message bundles
Location | In Magnolia Maven module | In Magnolia light module |
---|---|---|
Preferred |
|
|
Deprecated* |
|
- |
Message bundles stored in these directories will be loaded automatically during module startup.
If you have modules with message bundles located within the deprecated folder, make sure that the bundle file names are unique. |
Bundle load order and bundle merging
Message bundles are loaded in the same order as modules. The Magnolia i18n API loads bundles automatically during module startup as long as they are stored in the directories specified in the table above. If present in the directories, all bundles from all modules are merged at startup into one large bundle, a virtual file, which is then used by the Magnolia i18n API.
The keys stored in the message files in the |
Since Magnolia 6.2.19, adding or modifying an i18n file results in loading (or reloading) of that specific file only, instead of processing of all the i18n files. However, deleting an i18n file will trigger a reload of all the i18n files. |
Auto-generated keys
The Magnolia i18n API automatically creates and assigns keys for properties of items such as template definition, dialog definition, forms, fields, validators, column definitions, subapp description, app definition and others. Depending on the underlying info.magnolia.i18nsystem.I18nKeyGenerator, one or more keys are generated for a property. As a result, you don’t have to assign keys to them. You only have to provide the translations, at least one translation for one key. Please note that you may nonetheless use your own custom keys instead of those that are generated automatically by Magnolia.
Example: Auto-generated keys in a template definition
Let’s suppose there is a template named dilberts-page
in a module
called foobar
and the task is to provide the translation of the
title
property of this template definition.
Here is the yaml template definition file:
foobar/templates/pages/dilberts-page (fragment)
templateScript: /foobar/templates/pages/dilberts-page.ftl
renderType: freemarker
visible: true
dialog: foobar:pages/dilberts-page-properties
#title: foobar.customlabels.page.dilbert.title
-
The key for the
title
property is created automatically by Magnolia, you do not have to provide it. In fact Magnolia will recognize two keys, one with module name and one without it:
foobar.templates.pages.dilberts-page
templates.pages.dilberts-page
-
Line 5: If desired, you can assign a custom key.
Here is the message bundle file for the translation of the foobar
module:
foobar/i18n/module-foobar-messages_en.properties (fragment)
# Translation for the auto-generated key(s)
#
#templates.pages.dilberts-page=This is the dilbert page :-/
foobar.templates.pages.dilberts-page=This is the dilbert page :-)
# Translation for the custom key(s)
#
foobar.customlabels.page.dilbert.title=Dilberts page :^)
Generic keys
Note that Magnolia provides many so called generic keys
which are
already translated and which may fit to your items. See
generic i18n keys for
further details.
Key generators
Magnolia provides different key generator classes for different items. These key generators are responsible for the creation and assignment of the auto-generated keys.
You can also implement your own custom key generator class. Implement info.magnolia.i18nsystem.I18nKeyGenerator or extend info.magnolia.i18nsystem.AbstractI18nKeyGenerator.
I18nable
and I18nText
annotations
Below is an example of an existing Magnolia definition class using an existing key generator class:
@I18nable(keyGenerator = RenderableDefinitionKeyGenerator.class)
public interface RenderableDefinition extends NamedDefinition {
String getId();
@Override
String getName();
String getRenderType();
@I18nText
String getTitle();
@I18nText
String getDescription();
@Deprecated
String getI18nBasename();
String getTemplateScript();
Map<String, RenderableDefinition> getVariations();
}
-
Line 1: The info.magnolia.i18nsystem.I18nable annotation specifies the key generator class.
-
Lines 11, 14: The info.magnolia.i18nsystem.I18nText annotation marks methods that return text that should be translated.
Use I18nable
and I18nText
for custom definition
classes that should be i18n-ized.
From Magnolia 6.2.1, any method annotated with
info.magnolia.i18nsystem.I18nText uses NO_FALLBACK by
default if no translation is found.
|
info.magnolia.i18nsystem.I18nText
public @interface I18nText {
/**
* Without {@link #fallback()} explicitly specified, {@link info.magnolia.i18nsystem.TranslationServiceImpl} use the longest i18n key if translation key is not found as fallback.
*/
String NO_FALLBACK = "<no-fallback>";
/**
* @return Value to be used if no translation is found.
*/
String fallback() default NO_FALLBACK;
}
SimpleTranslator – using i18n in Java classes
If you want to internationalize UI elements or anything built directly on Java, use the info.magnolia.i18nsystem.SimpleTranslator translation service. In a simple content app, you probably won’t need to create UI elements in code since most of them can be configured. But if you do a custom app or anything more complex, below is the way the translation service should be used:
i18n java example
Do NOT instantiate SimpleTranslator but inject it in the
constructor.
|
import info.magnolia.i18nsystem.SimpleTranslator;
import com.vaadin.ui.Button;
import javax.inject.Inject;
public class MyClass {
private final SimpleTranslator i18n;
@Inject
public MyClass(SimpleTranslator i18n){
this.i18n = i18n;
}
public void someMethod(){
// more code here ...
Button sendMessageButton = new Button(i18n.translate("messages-app.app.button.sendMessage"));
// more code here ...
}
}
Then pass the key in the #translate(String key).
The key messages-app.app.button.sendMessage
must be in a message file
with a value:
messages-app.app.button.sendMessage=Send message