Localizing Mobile Apps
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:
- Sencha Touch apps can operate when not connected to a server. This requires us to include the language resource files with the application
- Sencha Touch apps use a class system that requires the localized strings to be available to the application classes when the application JavaScript files are parsed by the browser. This requires that the language resource files are loaded into the browser memory before the application files are processed.
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:
- The locale specific language resource files are loaded by the ../Common/lang/LocaleManager.js script.
- The LocaleManager.js script is loaded during the start up of the application before the Sencha Touch app.js file is loaded.
LocaleManager.js
The LocaleManager.js script is executed before the Sencha framework files are loaded.
The LocaleManager.js script performs several functions:
- Determines the locale setting of the browser. The locale is determined using the browser navigator.language property. If the browser property is not present, the locale will default to en_US.
-
Loads the language resource files for the current locale. There are three language resource files loaded. If the locale is set to French (fr), the files will be:
- control_fr.js – localized strings for the framework text
- lang_fr.js – localized strings for the forms and custom control text
- format.js – file containing date, time and number formats for all locales.
- Translates Locale for Simplified Chinese. The mobile framework uses the browser locale to determine which localization files to load. For simplified Chinese, the browser will report a locale of zh_CN. The Archibus convention is to use ch as the locale identifier for simplified Chinese. When a locale of zh is reported by the browser, the startup.js file will check if the zh language resources are present. If the zh resources are present, they will be loaded. If the zh resources are not present, the ch language resources will be loaded.
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:
- key1: the name of the class the string is contained in
- key2: the English string
- value : the translated string
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:
- Use the Archibus Localization kit to generate the lang_[locale].js and control_[locale].js files for the new language
- Add the files to the . .src/Common/resources/language folder
- Add the format configuration for dates and numbers for the new language to the format.js file
-
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" ],
- Build the Sencha app. The new language files will be available to use.