Localizing Mobile Apps

The Sencha Touch 2 framework dictates that we use a localization strategy that is different from the standard Archibus approach. Some of the differences are:

Mobile apps have three kinds of localized text:

Type Description
Framework Text This is text that is contained in components of the Sencha framework. Examples of this include the Ext.MessageBox and the Ext.picker.Date classes. The Archibus mobile localization framework overrides the framework text values with values obtained from the language resource files.
Forms and Custom Control Text This includes text defined in the form, including panel titles, custom HTML text fragments, and messages displayed to the user. This also includes text used in common custom controls.
Field Titles and Enumerated Lists Translated values for field titles and enumerated lists are provided by the TableDef object. The TableDef objects are downloaded and stored on the device during synchronization actions. The TableDef provides translated values based on the value of the session locale parameter when the TableDef object was retrieved from the server.

Loading Language Resource Files

The Sencha Touch framework uses a class system that uses config objects to initialize the class values. This impacts the design of the localization framework because the translated strings have to be available to the class when the application JavaScript is parsed by the browser. The language resource files along with the localization framework classes have to be loaded before the application files.

The following loading process is used:

LocaleManager.js

The LocaleManager.js script is executed before the Sencha framework files are loaded.

The LocaleManager.js script performs several functions:

Language Resource File Formats

The language resource files are stored in the ../src/Common/resources/language folder.

There are three types of language resource files.

Type Explanation
Control Strings The control strings are contained in the files named control_[locale].js where [locale] is the two character locale code. The strings in this file are used to override the text values of the Sencha framework controls. The string values in the control_[locale].js files are processed and applied by the Common.lang.ComponentLocalizer class.
Format Strings The format.js file contains the formats and characters to be used for the decimal separator, the grouping separator, the date format and the slot order of the DatePicker class.
Language Strings

The language strings are contained in the lang_[locale].js files. The contents of the lang_[locale].js files are generated by the Archibus Localization Kit. The following is an extract from the simplified Chinese lang_ch.js file.

var Mobile = Mobile || {}; Mobile.language = Mobile.language || {}; Mobile.language.ch = { localizedStrings: [ {key1: "AppLauncher.controller.Preferences", key2: "URL Required", value: "需要 URL"}, {key1: "AppLauncher.controller.Preferences", key2: "Reset Sync Flag", value: "重置同步标志"} ] };

The file creates the locale specific namespace and assigns the translated strings to the localized strings array. Each localizedString has the following properties:

Localization

Common.lang.LocaleManager

The LocaleManager module manages the localization data used in the application. The LocaleManager module is responsible for processing the localizedStrings array into an easily searchable object. The LocaleManager module also provides the getLocalizedString function that is used to provide the translated strings to the Sencha application.

LocaleManager.getLocalizedString

The getLocalizedString function returns the localized text string for a provided key value and class name. If the locale or the localized string cannot be found , the key value is returned. /** * Returns localized string value for the given key. * If the locale is not available or the localized string cannot be found, the key value is returned. * @public * @param key {String} key of the localized string. * @param className {String} name of the class that the string is contained in * @return {String} localized value or the key value if the localized string was not found. */ getLocalizedString: function (key, className)

LocaleManager.getJavaLocale

Returns the browser locale converted to Java locale format.

LocaleManager.getLocalizedDateFormat

Returns the date format for the active locale:

/** * Returns the date format string of the current locale. * @return {String} Date format string */ getLocalizedDateFormat: function ()

Tagging Strings for Translation

When creating new applications or new controls, the strings that are to be translated should be tagged using the LocaleManager.getLocalizedString function. The Localization Kit will parse the mobile JavaScript files and extract the strings that are included in the LocaleManager.getLocalizedString function parameters.

The following code snippet illustrates how the getLocalizedString function is used in the AppLauncher Registration view to provide translated values for the ‘Sign in as Guest’ text.

items: [ { xtype: 'titlebar', docked: 'top', items: [ { xtype: 'button', text: LocaleManager.getLocalizedString('Sign in as Guest', 'AppLauncher.view.Registration'), align: 'right', ui: 'action', action: 'guestSignOn', itemId: 'guestSignOnButton', hidden: true } ] },

When the AppLauncher.view.Registration file is parsed, the LocaleManager.getLocalizedString function will retrieve the translated string for the ‘Sign in as Guest’ key and set the button text configuration value to the translated string value.

Translating Form Field Labels and Enumerated Lists

The Form Field label values are provided by the MobileSyncService.getTableDef function. The TableDef objects are downloaded during the synchronization actions. The TableDef contains the translated Field Heading text for each of the fields in the server side table.

The Common.view.navigation.EditBase class contains the setColumnHeadings function that can be used to retrieve the Field Heading text from the TableDef and apply the values to the form field names. An example of this function being used in the Maintenance.view.WorkRequestEdit class is shown below:

initialize: function () { // Hide the segmented button if we are creating a work // request var me = this, isCreateView = this.getIsCreateView(), statusEnumList, dateRequestedField, problemTypeField; me.callParent(); // Set the Date Requested value in the form header dateRequestedField = me.query('hiddenfield[name=date_requested]')[0]; dateRequestedField.on('change', me.onDateRequestedChanged, me); problemTypeField = me.query('field[name=prob_type]')[0]; problemTypeField.on('change', me.onProblemTypeChanged, me); statusEnumList = TableDef.getEnumeratedList('wr_sync', 'status'); if (statusEnumList && statusEnumList.length > 0) this.query('selectfield[name=status]')[0].setOptions(statusEnumList); } me.setFormView(); me.setReadOnlyFields(isCreateView); me.setColumnHeadings('wr_sync'); },

The setColumnHeadings function retrieves the Field Heading values from the TableDef object for the wr_sync table and applies the values to the form field labels.

The translated values for enumerated lists are also supplied by the TableDef object. When enumerated lists are attached to the Sencha Select field control, the selectfield options configuration value should be set to the enumerated list supplied by the TableDef.getEnumeratedList function.

Adding Custom Languages

The following steps are required to add a custom language to the mobile framework:

  1. Use the Archibus Localization kit to generate the lang_[locale].js and control_[locale].js files for the new language
  2. Add the files to the ..src/Common/resources/language folder
  3. Add the format configuration for dates and numbers for the new language to the format.js file
  4. Add the language and control file to the appCache and resources section of each applications app.json file.

    For example, if we are adding Portuguese language, the app.json sections would be:

    "appCache": { "cache": [ "index.html", "device-api.js", "d3.v3.min.js", "startup.js", "lang_en.js", "lang_de.js", "lang_fr.js", "lang_it.js", "lang_nl.js", "lang_ch.js", "control_en.js", "control_de.js", "control_fr.js", "control_it.js", "control_nl.js", "control_ch.js", "format.js", "control_pt.js", "lang_pt.js" ], "network": [ "*" ], "fallback": [] }, "resources": [ "device-api.js", "d3.v3.min.js", "startup.js", "lang_en.js", "lang_de.js", "lang_fr.js", "lang_it.js", "lang_nl.js", "lang_ch.js", "control_en.js", "control_de.js", "control_fr.js", "control_it.js", "control_nl.js", "control_ch.js", "format.js", "control_pt.js", "lang_pt.js" ],

  5. Build the Sencha app. The new language files will be available to use.