Internationalizing a Widget

« return to the manuals

In LaxarJS, internationalization (i18n) of widgets is optional. Read on if you are interested in writing widgets that support multiple languages, and even switching languages without reloading the page.

Preliminary readings:

Locales and Language Tags: I18n in LaxarJS

LaxarJS distinguishes locales and language tags for internationalization: Each locale has a constant name such as "default" or "customer" as well as an RFC-5646 language tag like "en-US", which can change over time. Each locale corresponds to an audience (users, translators, admins, ...) for which a specific language tag should be used. If you have only one audience (all users), using only the locale "default" should be fine.

The language tag of a given locale can be modified by activities or widgets while the application is running. This is accomplished by publishing specific events from widgets that would like to set the language tag, and handling them correctly in i18n-capable widgets.

Widgets can use the language tags received over the event bus to localize internationalized values. Internationalized values are JSON-Objects which contain an entry for each supported language tag. By convention, variables and properties that contain internationalized values are prefixed with i18n:

const i18nHtmlText = {
   "en": "Upload <em>file</em>",
   "de-DE": "<em>Datei</em> hochladen"
}

Here, the localization for Germany (de-DE) will only be used if the language tag starts with de-DE. For other variants of de (such as de-CH), the configured fallback tag (by default en) will be used. Note that tags are case-insensitive and that the underscore ('_') is normalized to '-'.

Writing an I18n-Capable Widget

To work with internationalized values, widgets should specify a feature i18n in their widget.json descriptor. It allows page authors to configure the name of the locale (e.g. "customer") to be used by this widget. The actual language tag associated with that locale (for example en-GB) is usually defined by the application configuration, and used at runtime for localization.

"i18n": {
   "description": "Which locale to use for displaying this widget.",
   "type": "object",
   "properties": {
      "locale": {
         "type": "string",
         "description": "The topic under which to expect the locale for this widget.",
         "default": "default"
      }
   }
}

With this configuration, the widget service axI18n can be injected into the widget controller to localize internationalized values:

function updateView() {
   view.htmlText = axI18n.localize( i18nHtmlText );
}
updateView();

The axI18n service also helps to stay up-to-date when the language tag is changed:

   axI18n.whenLocaleChanged( updateView );

The callback passed to whenLocaleChanged is invoked with the updated language tag.

Changing the Language

Sometimes, you may want to offer users the functionality of switching the application language. The axI18n.update method can be used for this:

function onLanguageSelected( newTag ) {
   axI18n.update( newTag );
}

Performing Localization in Templates

Localization in templates is specific to the individual integration technologies. The "angular" adapter for AngularJS v1 provides the filter axLocalize which uses the axI18n service to provide up-to-date localizations of input values.

Advanced: Locale Change Events

To change the language tag of a locale, a widget has to publish the changeLocaleRequest.{locale} event. As described above, this can be achieved using axI18n.update( tag ). However, the axI18n service is just an abstraction over directly accessing the event bus to exchange locale change events.

Example: Assuming that axEventBus was injected into a widget, to change the language tag of the locale myLocale to de-DE, the widget controller has to do the following:

axEventBus.publish( 'changeLocaleRequest.myLocale', {
   locale: 'myLocale',
   languageTag: 'de-DE'
} );

Usually, you would just use axI18n.update( 'de-DE' ) to achieve the same effect.

If a widget is interested in changes to myLocale, it would subscribe to the corresponding didChangeLocale-event, which is published by the LaxarJS flow-controller:

eventBus.subscribe( 'didChangeLocale.myLocale', event => {
   axLog.info( 'I have received tag [0] for locale [1]', event.languageTag, event.locale );
} );

This is what axI18n does behind the scenes to support localize and whenLocaleChanged.