This page explains the internationalization concept as applied in Magnolia. The first part of the page provides the internationalization basics, the second part mentions some more advanced points.
Internationalization vs localization
Internationalization and localization, usually abbreviated as i18n and l10n respectively, are ways to adapt Magnolia to different languages and regional differences.
- Internationalization involves designing a system in which it is easy to accommodate new languages without programming.
- Localization adapts Magnolia to a particular region or language by adding locale-specific configuration.
i18n vs l10n
Magnolia primarily provides technical means for internationalization and it is mainly these aspects that the text below and other parts of the Language section deal with. For more information regarding l10n and the differences between i18n and l10n, see for example W3C's page.
The running system assigns a
java.util.Locale depending on the user settings or browser information. While rendering a page, a dialog, an app or any other part or the user interface, the i18n system evaluates the proper translation for a text by the current
Locale. It may happen that the i18n system cannot find a translation for the given locale - in this case the translation of the default language is applied.
The basics of Internationalization with message bundles
All types of translatable text (besides editorial content stored in JCR) are internationalized with message bundles. With message bundles a translator can work with a plain text file and doesn't need to touch the code. To do this, you need message bundles which contain message keys.
i18n message bundle
.propertiesfiles. 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.
Location of message bundles
|Location||In Magnolia Maven module||In Magnolia light module|
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 bundles' file names are unique!
Message bundle file name
Magnolia will find your message bundle files as long as they are in the
i18n folder (or in the deprecated folder). Message bundle file names must have the following form:
<locale> part of the filename, defining the i18n language used in the
.properties file, must conform with the Java locale notation.
Bundle name is arbitrary. However, it is a good practice to use one of the following patterns:
i18n message keys
.properties file usually contains one or more key-value pairs that provide the translations for labels, descriptions and other elements:
In Magnolia documentation we often use the term key to mean a key-value pair.
The keys may be module- and/or (sub)app-specific in which case the module name and/or the (sub)app name forms a part of the key, e.g.
This key will assign the word "Products" to the label for the root section of the actionbar of the Browser subapp in the Products app.
For standard Magnolia components, such as dialogs, forms, fields etc., template labels and for texts within custom java classes.generates keys automatically. You will only have to define keys for the so called
Referencing keys on the UI
Once you have defined the keys in the message bundle, the keys can be referenced in the UI. If applied correctly, the UI will render the values of the referenced keys in the language of the current locale settings.
*) Magnolia references i18n keys in templates, dialogs, apps, forms, fields, messages, etc..
Unicode and UTF-8 encoding
UTF-8 is the dominant character encoding for the World Wide Web. Magnolia supports UTF-8 character encoding for Unicode. UTF-8 can represent any character in the Unicode standard and is backwards compatible with ASCII.
The Java Content Repository (JCR) will store values in whatever format you provide. Magnolia always ensures that all values are UTF-8 encoded. Java classes read
.properties files of message bundles from the file system. Depending on the implementation of these stream reading classes, Java allows you to set the encoding in which the files are read.
Magnolia's i18n framework assumes that files in message bundles are UTF-8 encoded (see DefaultMessageBundlesLoader , DefaultMessagesImpl ).
If you open some older properties files in some of the Magnolia modules you will find keys like this:
This file contains Unicode entities or Java Unicode Character Representations. When you use Unicode entities to encode special characters, it doesn't matter what encoding your file is stored in or read by the Java class.
However, the above is a legacy practice that is no longer necessary. You don't have to use Unicode entities, just make sure your properties files are UTF-8 encoded. The above snippet from the bundle with basename
info.magnolia.module.templatingkit.messages can be written like this:
More advanced points
Finding the full name of a key
Magnolia generates keys for all dialog text automatically. If a translation for a key is not found in the existing
.properties file(s), Magnolia will use the key itself in place of the translation. The full name of a key can be obtained in several ways.
Use the browser inspector
In the following scenario, a new dialog containing a text input form is added to the Contact Page of the Travel Demo module. After creating the dialogue, it may look like this in the browser:
Two labels in this dialog are provided with correct i18n texts: the Cancel and the Save Changes buttons. These translations are reused from message bundles of modules that already exist in the Magnolia framework.
The other two labels in the dialog have been replaced by the keys themselves and because the names of the keys are too long, the UI displays only their parts. The full names can be obtained via the inspector function of your web browser. To inspect a label, e.g. the one shortened just to
travel-demo.compon..., place the mouse cursor on the element, right-click and select "Inspect element". This works the same way in most web browsers. The following screenshots are from Firefox:
Upon selecting the Inspect Element option, the full key together with its translation (here actually the key name itself) will be revealed in the code window of your browser:
The page code reveals that the name of this key is
which itself has been used as the label (viz the red frame) for the dialog element. To assign to the label the translation text "Enter Your Text", add the following line to the English
.properties files of the Travel Demo module:
Deploy the file and start the server. The dialog will now look like this:
The translation "Enter Your Text" appears as a label attached to the input text field. Inspecting the element again, the change will also be reflected in the code of the page:
Use the log
The full names of translation keys can also be obtained by logging the
info.magnolia.i18nsystem.TranslationServiceImpl class while using an app. This class prints keys into the
catalina.out log file as Magnolia looks for them in bundles.
- In the Log Levels app of the Log Tools module, set the logging level for
- Use your app. Open all subapps and dialogs.
- In the log, look for messages starting with "Looking up in global i18n message bundle with key..."
The raw log output can be confusing since it also contains keys from other Magnolia apps. Parse the log to find keys that are relevant to your app only. Here's an example command you can run in an OS X Terminal:
cat catalina.outprints the contents of the log file to the console
egrep -o "products(\.\w+)+"matches message keys that start with your app name. Replace
productswith your app name.
sort –uniqueignores duplicate entries
Using the translation service
When you create UI elements in code, use the SimpleTranslator translation service. In a simple content app, you likely won't need to create UI elements in code since most can be configured. But if you do a custom app or anything more complex, this is how to use the service.
SimpleTranslatorbut inject it in the constructor.
Then pass the key in the
messages-app.app.button.sendMessage must be in a message file with a value:
- Translatable fields in a component: ContactPreviewComponent
- Translatable error message: DirectUploadAction
Similar to Java code, you can use the translation service in a template script.
Example: i18n of the Tutorial module
This example shows a selection of English messages from the
app-products-messages_en.properties message file in the Products app of the Tutorial module:
The Products app has message files for English and for Spanish:
These files together build a message bundle which is stored in the
i18n directory within the module path: