This page contains practical examples of i18n usage, illustrating the difference between the old and new internationalization APIs. Read New and old i18n API first to understand how the API has changed.


Dialogs are nice examples for comparing the old and the new API. A dialog has a lot of translatable text. There is a label and a description for the dialog itself, one label for every tab, and a label and a description for every field. The descriptions are used for the help text.

 You can use either the old or the new i18n API in dialogs but we recommend the new API.

New i18n API in dialogs

To use the new i18n API in dialogs, create your dialog definitions just like you did with old API but leave out the following properties:

  • label
  • description
  • 18nBasename

Magnolia generates keys for all dialog text automatically.

After creating a new dialog, open it in the browser. It may look like this. There are some kind of labels but certainly not what you want.

Some text is translated correctly such as the Save changes and Cancel buttons and the label for the Show all tab which summarizes all fields of all tabs. For these keys translations exist in other bundles provided by the framework.

The new i18n API autogenerated keys and looked for corresponding translations. It wasn't able to find any translations since you did not provide any yet. In such cases the key itself is rendered in place of the label.
Usually an autogenerated key is too long to be displayed on the UI completely. To get the complete key string use the inspector function in your browser. To inspect a label, put the mouse cursor on the element, right-click and select "Inspect element". This works the same way in most browsers as Firefox or Chrome; the screenshot is from Chrome.


After inspecting a few keys you will understand the pattern how keys for the dialog were created.

Add .properties file in the mngl-i18n folder in your project if one doesn't exist. This is the first message file in your message bundle. Add the keys in the file and provide translations.

documentation-reuse-content.components.i18n-test.label = Simple i18n test dialog
documentation-reuse-content.components.i18n-test.description = Enter data for this dummy dialog :-)
documentation-reuse-content.components.i18n-test.mainTab.label = Personal data
documentation-reuse-content.components.i18n-test.metaData.label = Metadata
documentation-reuse-content.components.i18n-test.mainTab.sizeOfShoes.label =  Size of shoes
documentation-reuse-content.components.i18n-test.mainTab.sizeOfShoes.description = Provide your shoe size.

Once you have added the keys and translations, deploy the file and start the server. Now the dialog looks different:

Custom keys

Assigning a custom message key is a method that falls somewhere between the new and the old API. You can use the automatically loaded message bundle that resides in your mgnl-i18n folder but instead of letting the system autogenerated keys for you, create and assign a custom key. Add the label property to the field definition, set its value to your custom key, and add the key and its translation in the message file.

Node nameValue








documentation-reuse-content.i18n-test-component.sizeOfShoes.Label = Size of shoes (EU)

(warning) Assign a unique key. The exact same key should not be present in any other message bundle.

Old i18n API in dialogs

Dialogs in the Standard Templating Kit module still use the old i18n API but there is a ticket to change this: MGNLSTK-1423 - Getting issue details... STATUS . We recommend that you use the new i18n API for dialogs, However, the STK module is a good example of how you can internationalize dialogs the old way if needed.

Provide a basename

Add the i18nBasename property to your dialog definition. Set it once per dialog. Magnolia will use it for all translatable text in that dialog. However, you also can set the i18nBasename property for individual fields to override the basename they inherit from the parent dialog.

Specify keys

Specify a key for each piece of translatable text, add the keys to your message file, and provide translations. For more details, study some dialogs in the STK such as /modules/standard-templating-kit/dialogs/components/content/stkTextImage.

Node nameValue











Template labels

Template scripts still rely on the old API for their labels. Read Template labels to learn more about this special group of translatable text. 


Freemarker templates

When defining a template that uses a Freemarker script, provide the i18nBasename property.

Node nameValue











The property allows you to retrieve messages from the named bundle within the template script. In this example documentation-reuse-content.templates.i18n-test.testMessage2 is a key for which you should have a translation in the bundle.


In the above snippet, the key will be translated for the locale context of the website visitor.

(warning) Since Magnolia 5.3.6  FreemarkerHelper  exposes also the locale of the authoring context. You can use the authoring context to display a message to an editor in the language of the currently logged in user.



JSP templates

When using a JSP template script, set the bundle in the JSP code. There is no need to set the i18nBasename property in the template definition.

In this example documentation-reuse-content.templates.i18n-test.anotherTestMessage is the key for which you should have a translation in the bundle.

<%@ taglib uri="" prefix="fmt" %>
<fmt:setBundle basename="info.magnolia.module.documentation.contentreusing.jspMessages"/>
    <fmt:message key="documentation-reuse-content.templates.i18n-test.anotherTestMessage"/>

Java classes

In some cases you have to internationalize texts used in Java classes. This could be the case in Action classes, in classes for custom dialogs, and generally in apps.

You can use either the old or the new i18n API in a Java content. However, we highly recommend that you use the new API. The old is deprecated and may be removed in future versions of Magnolia.

New i18n API and access to message bundles

The new i18n API gives you access to all bundles in all mgnl-i18n folders that have been loaded during module startup. See Bundle location and loading for more on this process.
To access the resources of theses bundles, use SimpleTranslator#translate .

(warning) Never ever instantiate SimpleTranslator or  TranslationServiceImpl  which is required in the constructor of SimpleTranslator.

Best practice

Inject  SimpleTranslator with IoC in the constructor of your Java class and use it to get access to resource bundles.

A typical example is a custom  BrowserSubApp for a content app where you want to display alerts:

// more imports here
import javax.inject.Named;

public class YetAnotherSubApp extends BrowserSubApp {

	private final SimpleTranslator i18n;
    private SubAppContext subAppContext;
    public YetAnotherSubApp(SimpleTranslator i18n, ActionExecutor actionExecutor, /* more params here */) {
        super(actionExecutor, subAppContext, view, browserPresenter, subAppEventBus, adminCentralEventBus, contentConnector, checker);
        this.i18n = i18n;
        this.subAppContext = subAppContext;

	private void doSomething(){
        // some more code
        subAppContext.openNotification(MessageStyleTypeEnum.INFO, false, i18n.translate(""));
        // some code
	/* some more code */

Important things to note:

  • SimpleTranslator is injected into the constructor. (lines 9-10)
  • SimpleTranslator is declared as final. (line 6)
  • Use the instance method SimpleTranslator#translate wherever it is required (for example line 19)

(warning) The class above is an incomplete fragment. Some things are left out for better readability. The constructor requires more params to compile, for example.

Old i18n API and access to message bundles

In the old i18n API,  MessagesUtil  was used to access a bundle. Search for references of this class in your custom code and refactor the code using the new API if your custom code runs in Magnolia 5.1 or later.

#trackbackRdf ($trackbackUtils.getContentIdentifier($page) $page.title $trackbackUtils.getPingUrl($page))