Page tree
Skip to end of metadata
Go to start of metadata

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:

The base – Java message bundle

Java provides an API to load resource properties files for the purposes of internationalization. 

What is a 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:

LocationIn Magnolia Maven moduleIn Magnolia light module
Preferredsrc/main/resources/<module-name>/i18n<magnolia.resources.dir>/<module-name>/i18n
Deprecated*src/main/resources/mgnl-i18n-

Message bundles stored in these directories will be loaded automatically during module startup.

*) (warning) If you have modules with message bundles located within the deprecated folder, make sure that the bundles' 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 i18n folder, as well as in the deprecated mgnl-i18n folder, must be unique throughout all files in Magnolia i18n directories. When using one and the same key twice, the one which is loaded second overwrites the one loaded first. Organize your bundles and keys in a way that does not depend on the bundle load order.

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  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.yaml (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 and their list 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  I18nKeyGenerator  or extend  AbstractI18nKeyGenerator .

I18nable and I18nText annotations

Below is an example of an existing Magnolia definition class using an existing key generator class:

info.magnolia.rendering.template.RenderableDefinition (simplified)
@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: I18nable annotation specifes the key generator class.
  • Lines 11, 14: I18nText annotation marks methods that return text which should be translated.

Use I18nable and I18nText for custom definition classes which should be i18n-ized.

SimpleTranslator – using i18n in Java classes

If you want to internationalize UI elements or other things which are built directly on Java, use the 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:

(warning) 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:

myapp-messages_en.properties
messages-app.app.button.sendMessage=Send message