Localize the interface

This guide describes how to use the localization framework to localize text found throughout the UI of FontoXML.

The FontoXML localization framework enables translation of FontoXML into other languages. It can also be used to replace built-in text with text adjusted to your environment, such as mentioning the CMS by its name, or referring to documents with a term more familiar to your users. It can also be used to render all dates and numbers in FontoXML using the format defined by your locale. An instance can use the localization framework to merely translate the application, but the API can also be used to easily add localization support to your own packages.

While it is not yet possible to switch languages while the editor is open, the preferred language can be selected dynamically in config/configuration.js. This enables selecting the language to use when FontoXML is started, for instance based on the scope provided by the CMS.


There are a few texts that can't be translated. Those texts are in the unsupported browser UI. This is a known technical limitation which can't be solved within Fonto because JavaScript may not even executed during that stage. If this is critical to your application, we recommend performing the checks in the host application.

Using localization in a FontoXML instance

The following assumes an existing FontoXML application, upgraded to the 6.8.0 release (or newer) of the FontoXML platform. The upgraded editor instance should include a file called messages-template.json, which will be used in the steps below.

  1. Create a new package directory for containing the translated strings

    Localization bundles can be placed in the src folder of any package. When in doubt, create a single package named [instance-name]-localization. Make sure that the config package depends on this localization package, either directly or via another package. For more information on how to create packages, please read the documentation on the structure of a package directory.

    Because this package redefines messages used in the platform, it should depend on the platform using a fonto-manifest.json with the following contents:

    {
    	"dependencies": {
    		"fontoxml-platform-base": "platform/fontoxml-platform-base"
    	}
    }
  2. Copy the messages-template.json file to the package directory as src/messages.[IETF language tag].json.

    The IETF language tag is used to select the appropriate plural forms for your localization. Make sure to use the appropriate code from the CLDR plural rules chart in order for the correct plural forms to be used for your localization. Variations on a language can be made using a dash and suffix after the language code.

    Translating an instance to Lojban should be done in a file called messages.jbo.json. Dialects would create a file messages.en-US.json.

  3. Fill in the blanks

    Message bundles are JSON files, containing an array of message objects. Each message contains an in property with the original message, and optionally some metadata reflecting the use of the message in the FontoXML source files.

    [{ "in": "Insert character", "meta": [{…}] }]

    To turn this template into a usable message bundle, add a new field called out to each message containing the translated string. For example, to translate this string to Lojban, add an 'out' key, containing the translated text as a string:

    [{ "in": "Insert character", "out": "Setca lo lerfu", … }]

    Repeat this part for all strings in the application. In the future, the localization tooling will contain a converter from and to other file formats, to ease collaboration with translation services.

    The translation messages use the MessageFormat format, which also supports genders, dates, times and pluralization. The message {REPORT_COUNT, plural, one{# content issue} other{# content issues}} can output either 1 content issue or 9001 content issues, depending on the variable REPORT_COUNT. The message {REPORT_TIME, date, long} will output a date using the format defined by the locale.

    When translating such messages, make sure to leave the MessageFormat syntax intact and to use the appropriate plural forms for your language.

  4. Configure the locales to use

    Set the configuration variable preferred-locales to an array of IETF language tags, in order of preference. If a message is not translated in a preferred locale, it will fall back to a locale higher in the array.

    It is recommended to always include the “en” language tag as the last entry in the array. This way, when new messages are added in future releases of the platform for which no localization has been created yet, the application will fall back to the built-in English localization for these messages rather than causing an error.
    configurationManager.set('preferred-locales', ['jbo', 'en-US', 'en']);

  5. Remove old work-arounds


If all went well, the instance is now translated. Remove any operations and toolbar button properties that were only intended to override built-in text - using the localization framework for this purpose is less likely to break your application in unexpected ways. Additionally, translating these messages using the localization files will keep all messages in the same location.


After performing these steps, the instance-level code is reduced and the translated messages are located in a single file.

Updating localization for a new release

The following assumes an existing, localized FontoXML application running the 6.8.0 release (or newer) of the FontoXML platform, and describes the process of updating the translations to a new release of the platform.

  1. Use the FontoXML development tools to upgrade your editor instance.
  2. (Optional) merge the new messages-template.json with any templates for your local packages.

    See “Making your code and configuration localizable” for details on using the FontoXML localization API in your custom packages.

  3. Open a command-line window.
  4. Run the update command.

    Run fdt localization update BUNDLE_PATH TEMPLATE_PATH, replacing BUNDLE_PATH with the path to the localization message bundle to update and TEMPLATE_PATH with the path to the new template.

    The update command will compare the “in” properties of all messages in the template and the existing bundle. It will preserve the translations of any existing messages, and display an overview of messages that have been removed or are missing a translation after the update.

    For example: fdt localization update ./<localization-package-name>/src/messages.<langcode>.json ./messages-template.json.

    You can add --help after any FDT command to get more information on how to use it, for example fdt localization --help lists available localization commands, and fdt localization update --help displays instructions on how to use the update command.

  5. Localize the new messages.

    Edit the resulting message bundle to add “out” properties for any missing translations reported by the update command.

    FontoXML will report warnings in the developer console for any messages missing a translation when message bundles are loaded.

  6. Replace the original message bundles with the updated versions.

The localizations have now been updated for the new FontoXML release. Remember to update localizations after every FontoXML release (or when updating your custom packages) to ensure that all text will be displayed in the desired language.

Making your code and configuration localizable

If you use custom packages shared between multiple instances, or if your instances use multiple languages, it may be beneficial to enable localization for your own code and configuration. FontoXML provides an API to enable custom packages to take advantage of the same features used to localize the platform.

  1. Ensure all text is in English.

    The FontoXML localization framework assumes all text in the code is in the default “en” locale. This means that the strings marked for localization in the steps below should be written in English.

    Localized versions of these strings may use any language, as long as it corresponds to the IETF language code in the message bundle filename. As message bundles can be placed in any package, default localizations for a package can be included with the package itself by simply including the messages.*.json files.

  2. Prefix localizable text in operations.json.

    The operation.json files containing the operation configuration for your application likely contain various strings of text that will be displayed to users of the instance. To enable localization for these, simply add the prefix “t__” (a lower case t and two underscores) directly in front of the text. When loading the operation, FontoXML will use the text following the prefix to look up the proper message to show.

    To make the following operation localizable:

    {
    	"insert-code-block": {
    		"label": "Code block",
    		"description": "Inserts a block of source code.",
    		"steps": [
    			{
    				"type": "operation/show-select-language-modal",
    				"data": {
    					"modalTitle": "Select the programming language"
    				}
    			},
    			...
    		]
    	}
    }

    Add the t__ prefixes like this:

    {
    	"insert-code-block": {
    		"label": "t__Code block",
    		"description": "t__Inserts a block of source code.",
    		"steps": [
    			{
    				"type": "operation/show-select-language-modal",
    				"data": {
    					"modalTitle": "t__Select the programming language"
    				}
    			},
    			...
    		]
    	}
    }
  3. Wrap text in JavaScript files with the t() function.

    Any localizable text in JavaScript files should be wrapped with a call to the t() function, which can be imported from fontoxml-localization/t. This function should always be called with a string literal as its first argument.

    Import the t() function at the top of the module:

    define([
    	...
    	'fontoxml-localization/t'
    ], function (
    	...
    	t
    ) {
    	'use strict';
    	...

    Then use it for each localizable string in the code:

    configureAsBlock(sxModule, 'self::p', t('paragraph'));

  4. Adapt dynamically changing text to the MessageFormat syntax.

    In some cases, text may be composed dynamically by the code, such as when including other sources like user names, or when using plural forms. As other languages may not use the same sentence ordering or plural forms as used in English. The t() function supports the MessageFormat syntax, including date and time. This covers most of these cases while using a single, easily localizable message. The t() function accepts an object as its second argument, containing the arguments for the message. By convention, we use ALL_UPPER_CASE names for any message arguments.

    // Using variables
    t('{CURRENT_RESULT_INDEX} of {TOTAL_RESULTS}', {
    	CURRENT_RESULT_INDEX: this.currentResultIndex,
    	TOTAL_RESULTS: this.totalResults
    });
    
    
    // Using variables with plural forms
    button.label = t('{REPORT_COUNT, plural, one{# content issue} other{# content issues}}', {
    	REPORT_COUNT: reportCount
    });

    In FontoXML, dates are usually outputted like 12 February 2018. By default, messageformat does not include a formatter which can output dates like this. For this reason, a special fonto_date formater is available. This formatter uses the configured locale to build the same string for a date as FontoXML does, accros browsers. This can be used like this:

    // Using fonto_date
    t('It is {DATE, fonto_date}', {
    	DATE: new Date()
    });
  5. Extract a message bundle template for your packages.
    1. Open a command-line window.
    2. Ensure that the FontoXML Development Tools are installed.

    3. Run the extract command

      From the root directory of your instance, run the command fdt localization extract app-messages-template.json

      If you want to extract messages from specific packages only, you can run the command fdt localization extract --paths PACKAGE_PATHS package-messages-template.json instead. Replace PACKAGE_PATHS with the (space-separated) relative paths to the packages for which you want to generate the message bundle template, and feel free to use a different name for the template .json file.

      We recommend writing the message bundle template for your own packages to a file different from the platform template, to facilitate updating either in the future.

  6. (Optional) merge the template with the platform template.

    While it is possible to split localizations over as many message bundles as desired, you may want to use a single bundle to keep things simple. Message bundles can be merged using the merge command provided by the FDT localization module. Run fdt localization merge messages-merged.json --bundles BUNDLES_OR_TEMPLATES to combine multiple bundles. Replace BUNDLES_OR_TEMPLATES with the paths to the bundles to merge, and feel free to use a different output file name.

  7. (Optional) update your localizations.

    Follow the steps in “Updating localizations for a new release” to use the new message bundle template to update any existing localizations.


Making your localization dynamic based on a scope object parameter

It is possible to read scope object parameters and use a custom object parameter to dynamically use a localization file.

scope object
{
    "documentIds": [ "74257961-EDE3-4180-AF17-0A435EE8FB7B" ],
    "cmsBaseUrl": "https://cms/api/fontoxml",
    "user": {
        "id": "1",
        "displayName": "Mr. Author"
     },
    "editSessionToken": "EF091CD9-DC7A-4F91-9964-21CAF0DC3DCE",
    "locale": "nl-NL"
}


configuration.js
define([
	'fontoxml-configuration/get!scope'
], function (
	scope
) {
	'use strict';


	configurationManager.set('preferred-locales', [scope.locale, 'en']);
);