Localize a widget

You can customize widgets to recognize the language of the browser that your customer is using.

Any text in a widget that does not come from a remote API call can be defined in a resource bundle so that it can be localized. Note: You can include localized resources in your widgets/elements by including a /locales directory. However, this is not necessary. You can just as easily hardcode strings inside the HTML templates or JavaScript source files.

Use resource files

The resources reside in the widget /locales directory, as shown in the following example:

<extension-name> : the root folder of your extension
      ext.json
      widget/
         <widget-type>/
             widget.json
             locales/
               <locale code, for example, en or en_US>/
                            ns.<widget-type>.json
               <other locale codes>/
                            ns.<widget-type>.json

A child directory exists in the /locales directory for each locale you want to provide resources for and their names can be either a two-letter language code (for example, en) or a two-letter language code and a two-letter country code with an underscore in between (for example, en_US). ISO 639-1 defines the two-letter language codes. ISO 3166-1 alpha-2 defines the two-letter country codes.

The naming convention for resource files contained in these directories is ns.<widget-type>.json, for example, ns.mywidget.json. The ns prefix stands for “namespace” and widget-type corresponds to the /widget/widget-type directory. Resource files are in JSON format. Refer to the Resource loading section for more information on this format.

Localizable resources are defined using JSON objects composed of string keys mapped to string values. The keys represent the resource names and the values represent the localized version of each resource. The i18next JavaScript library is used to perform the client-side translations. An example locale file is shown below:

{
   "resources": {
      "siteNavigationFooter" : "Site Navigation Footer",
      "editFooterHeader" : "Select Header Links (multi-select allowed)"
   }
 }

Use resources in widgets

Primarily, widget resources are used when text in a widget display template is translated. A Knockout custom binding named widgetLocaleText is available on the storefront to invoke the translation of the resource using the store’s current locale. This will ultimately call the i18next library, but that is invisible to the widget templates. The following example shows using the widgetLocaleText binding in its simplest form, passing in the resource key:

<h2 data-bind="widgetLocaleText: 'cartHeader'"></h2>

The resource files defined for a widget for the current locale are used to replace the key with the right resource. The locale is defined for the storefront when the page is loaded. In the current release of Commerce, the locale is defined for the Site. The resources for the current locale are returned with the widget data when a page is loaded. These resources are mapped onto a widget and also as a namespace for il8next.

If you need to translate text within a widget’s JavaScript, use the translate function in the widget view model. This would be required, for example, when sending a message for display on the notification bar.

notifier.sendSuccess(widget.WIDGET_ID, widget.translate('loginSuccessText'));

Use variable replacement

Rather than manually concatenating variables to localized strings, the il8next library has support for variable replacement.

For example, a welcome message using the user’s first name can be defined in a resource, such as, Welcome __userName__. Then, in the display template, the translation can be invoked using a knockout object to set the userName variable, such as the following:

<span data-bind="widgetLocaleText : {value:'welcome', attr:'innerText', params:
        {userName: firstName()}}"></span>

Note that in the JSON resource, a __doubleUnderscore__ notation marks the variables but, when the resource is invoked in HTML or JavaScript, the underscores are omitted. The i18Next library provides other mechanisms such as support for plurals. Refer to the i18next section for more information.

Resource loading

By following the structure defined above for a widget, and putting the widget resources under the /locales directory for a widget, the resources will be loaded for the widget by the framework. The data to build a page in the storefront is retrieved from the Pages Web API Endpoint. For the current page, this endpoint will return both context data and the data related to the layout of the page, such as the regions and widgets to load.

Included with the data about each widget are the resources. These resources are then mapped onto the widget and loaded when the widget is loaded. The i18next namespace used to load the resources is defined as part of the widget definition within the server-side Page Repository. When a new widget is created, its widget.json file defines a property called i18nresources. The following is an example:

{
   "name": "Widget Name",
   "version": 1,
   "javascript": "widget-type-js",
   "i18nresources": "widget-type",
   "availableToAllPages": true,
   "jsEditable": true,
 }

The i18nresources property for a widget is used to determine the file name for each locale resource file, in the format ns.<i18nresources property>.json.

So, for the widget definition shown above, the resources file name would be ns.widget-type.json. This i18nresources property is used in the storefront framework when loading the resources and expects the format to be as defined here. Since the resources are no longer loaded directly via a URL, the file name itself is less important, but following the convention allows for consistency.

Use common resources: i18next

Currently there are two sets of expected common resources, as described in the following:

  • ns.common: Common text used across the store such as OK, Cancel, Close, and so on.
  • ns.ccformats: Defines a format for a number.

Use common resources: moment

The moment.js library (see http://momentjs.com) is used in the storefront to format dates. This requires a resource file per language. The en version comes with moment but other languages require a separate JavaScript file.