Magnolia 5.3 reached end of life on June 30, 2017. This branch is no longer supported, see End-of-life policy.
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.
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:
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 name | Value |
---|---|
fields | |
sizeOfShoes | |
class | info.magnolia.ui.form.field.definition.TextFieldDefinition |
label | documentation-reuse-content.i18n-test-component.sizeOfShoesLabel |
documentation-reuse-content.i18n-test-component.sizeOfShoes.Label = Size of shoes (EU)
Assign a unique key. The exact same key should not be present in any other message bundle.
Dialogs in the Standard Templating Kit module still use the old i18n API but there is a ticket to change this: - MGNLSTK-1423Getting 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.
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 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 name | Value |
---|---|
fields |
|
subtitle |
|
description | dialogs.paragraphs.content.stkTextImage.tabText.subtitle.description |
class | info.magnolia.ui.form.field.definition.TextFieldDefinition |
label | dialogs.paragraphs.content.stkTextImage.tabText.subtitle.label |
Template scripts still rely on the old API for their labels. Read Template labels to learn more about this special group of translatable text.
See:
When defining a template that uses a Freemarker script, provide the i18nBasename
property.
Node name | Value |
---|---|
templates | |
components | |
your-component | |
templateScript | /reuse-templates/components/i18n-test.ftl |
i18nBasename | info.magnolia.module.documentation.contentreusing.templateMessages |
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.
<div>${i18n['documentation-reuse-content.templates.i18n-test.testMessage2']}</div>
In the above snippet, the key will be translated for the locale context of the website visitor.
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.
Example:
<div>${i18nAuthoring['just-another-key']}</div>
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="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %> <fmt:setBundle basename="info.magnolia.module.documentation.contentreusing.jspMessages"/> <div> <fmt:message key="documentation-reuse-content.templates.i18n-test.anotherTestMessage"/> </div>
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.
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
.
Never ever instantiate
SimpleTranslator
or
TranslationServiceImpl
which is required in the constructor of SimpleTranslator
.
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; @Inject 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("your-module.yetAnotherSubApp.doSomething-notification.info")); // 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)SimpleTranslator#translate
wherever it is required (for example line 19) The class above is an incomplete fragment. Some things are left out for better readability. The constructor requires more params to compile, for example.
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.