Page History
...
In Magnolia 5.0, many Strings used in UI are either hardcoded, or used from configuration without i18n. To allow full i18n in M5.1, such Strings have to be replaced by message keys, and the proper i18n code has to be used. This applies especially for the new code, i.e. magnolia_ui, and contacts and dam modules.
Solution
Suggestions
Differentiate between in-code-translations, vs in-config-translations. Translations in-configuration will require very little code change, but will require some work on update tasks and bootstrap files.
i18nBasename
Up to Magnolia 4.5, the i18nBasename
property was defined in a dialog definition (or further down). With 5.0, this property is moved one level down (into the form
subnode).
However, actions definitions also need to be i18n'd. For apps, it would make sense to have i18nBasename
defined at the app level (AppDescription). Dialogs however are not necessarily tied to an app i.e they're used by the page-editor, so we wouldn't want to use the page-editor's i18nBasename.
In-config translations
...
A complete code review is required to identify all places with a direct String output (such as button labels, column headers, etc.). Such places have to be replaced with a proper i18n mechanism ( as MessagesManager.getWithDefault(key, defaultMsg)
, where the original String will be used defaultMsg
).
...
as defaultMsg
).
A complete code review is not necessary. A search for usages of the following (to be completed) should cover 95% of our bases.
info.magnolia.ui.form.field.definition.FieldDefinition#getLabel
info.magnolia.ui.form.field.definition.FieldDefinition#getDescription
info.magnolia.ui.form.definition.TabDefinition#getLabel
...
Bootstrap files update
After the code review, the configuration (bootstrap) files have to be reviewed, and values of properties label and description (and alternatively others) will be replaced with a proper message key. Such message key (and value) will be added to the messages_en.properties file of the admincentral UI module (or the other module's messages file), and the path of the property + the key will be added to the list of changed properties (one list for each module, a properties file named i18n_properties_to_update.properties
on classpath), which will be then used in the VersionHandler
to replace the values on the upgrade (using new UpdateI18nPropertiesTask
).
Code Block | ||||
---|---|---|---|---|
| ||||
public class UpdateI18nPropertiesTask extends AbstractRepositoryTask {
// ...
public UpdateI18nPropertiesTask(String name, String description, String propertyListFilename) {
super(name, description);
this.propertyListFilename = propertyListFilename;
}
@Override
protected void doExecute(InstallContext installContext) throws RepositoryException, TaskExecutionException {
Map<String, String> pathsAndValues = loadFromFile();
for (String path : pathsAndValues.keySet()) {
Node node = getNode(path); // path is the path to property, this gets the last node on the path
String propertyName = getPropertyPath(path); // the part of the path after the last "/"
Property prop = PropertyUtil.getPropertyOrNull(node, propertyName);
if (prop!=null) {
// if exists, replace
PropertyUtil.setProperty(node, propertyName, pathsAndValues.get(path));
}
}
}
// ...
} |
i18nBasename
In the Magnolia up to 4.5, it is possible to define i18nBasename
property in a dialog configuration to define a different message bundle. In Magnolia 5, this still works, just the property has to be placed under the form
sub-node of the dialog.
I suggest to allow to use this property also in the app definition, to choose a message bundle for the whole app (actions, workbench, ...). This will require some API extensions, such as adding getI18nBasename()
method to the AppDescriptor
interface, etc.
Based on existing (or then existing) translation files, we should be able to write a script that does a search/replace into bootstrap files. And/or a (temporary) update task could help regenerating them.
Migration
Based on existing (or then existing) translation files, it should be easy to update content. (find i18nBasename, find values for "label" and "description" properties, reverse-lookup, replace by corresponding key)