In computing, internationalization and localization are means of adapting computer software to different languages, regional differences, and the technical requirements of a target market. The term localization refers to all the activities needed before your app can be deployed in different languages and according to local cultural conventions. Before starting to localize an app, you have to internationalize your code by removing any language and cultural dependencies and designing your code in order to be adapted to various languages without engineering changes. You can then localize your app, translate client-facing content and labels, and otherwise adapt it so that it works well in a particular locale. The term locale refers to a collection of settings or preferences to be used in localization. A locale is often described as a language and country pair such as en-US, de-AT, it-IT, and so on. The term globalization stands for the combination of internationalization and localization.
There are some odd-looking abbreviations in which a number is used to indicate the number of letters between the first and last letter used to refer to internationalization, localization, and globalization:
i18n
stands for internationalizationl10n
stands for localizationg11n
stands for globalization
From a development point of view, the common practice is to place the text in resource strings that are loaded at the execution time depending on the user settings. There are several techniques you can use to globalize your app such as storing the translations in PO (portable object) files, creating a JSON object containing all of them, or loading the localization files dynamically when the app starts. The goal is to deploy an app able to select the relevant language resource file at runtime and to handle culture-aware number and date parsing and formatting, plurals, currencies, special characters, validation, and so on.
Note
Software internationalization is a very huge topic because it covers plurals, dates, special characters, and so on. Discussing all of them is beyond the scope of this book. If you are interested in learning more about internationalization, take a look at the GNU project gettext (http://www.gnu.org/software/gettext/manual/), the globalize project (https://github.com/jquery/globalize), or the jed project (http://slexaxton.github.io/Jed/). For an overview of the most common challenges to address during the internationalization process, watch this great talk at http://www.youtube.com/watch?v=uXS_-JRsB8M.
PhoneGap offers great support for localization through the Globalization API accessible through the globalization
object. The globalization
object is a child of the navigator
object and therefore has global scope. Therefore, in order to access the globalization
object, it's enough to type the following code snippet:
var globalization = navigator.globalization;
The globalization
object exposes several asynchronous methods that have a similar signature. In fact, usually most methods accept an argument, a success and a failure handler, and optionally an options
object:
globalization.methodName(argument, onSuccess, onError, options);
Not all the methods accept an argument and the option
object; some of them accept only a success and a failure handler. The failure handler receives a GlobalizationError
object as an argument. There are two properties defined on this object message and code. The first one contains a string describing the error details; the second one contains an integer equal to one of the following pseudo constants defined in the GlobalizationError
object:
GlobalizationError.UNKNOWN_ERROR
(return value0
), a generic error occurredGlobalizationError.FORMATTING_ERROR
(return value1
), an error occurred during a formatting operationGlobalizationError.PARSING_ERROR
(return value2
), an error occurred during a parsing operationGlobalizationError.PATTERN_ERROR
(return value3
), an error occurred recovering a currency, date or number pattern
The Globalization API exposes the following methods defined in the navigator.globalization
object:
getPreferredLanguage
, returns the string identifier for the device's current language; the string is stored in thevalue
property of the object received as an argument in the success handler (i.e.{value: 'English'}
).getLocaleName
, returns the locale identifier according to the device's current language; the string is stored in thevalue
property of the object received as an argument in the success handler (i.e.,{value: 'en'}
).dateToString
, returns a date formatted as a string according to the client's locale and time zone; the method accepts aDate
object as the first argument and an optionaloptions
object as the last argument:var globalization = navigator.globalization; var today = new Date(); globalization.dateToString(today, onSuccess, onError);
The returned result is stored in the
value
property of the object received as an argument in the success handler (i.e.,{value: '06/14/2013 12:49 PM'}
).stringToDate
, parses a date formatted as a string, and depending on the device's preferences and calendar, returns the correspondingDate
object as an argument in the success handler.getDatePattern
, returns an object received as an argument in the success handler containing:A pattern string to format and parse dates according to the device's preferences
The time zone of the device
The difference in seconds between the device time zone and the universal time and the offset in seconds between the device's non-daylight saving's time zone
The client's daylight saving's time zone (i.e.
{pattern: 'dd/MM/yyyy HH:mm', timezone: 'CEST', utc_offset: 3600, dst_offset: 3600}
)
The method accepts an optional
options
object through which it's possible to specify the format length (i.e.,short
,medium
,long
, orfull
) and the data to be returned (i.e.,date
,time
, ordate and time
).getDateNames
, returns an array of names of the months or days of the week depending on the device's settings; the array is stored in the value property of the object received as an argument in the success handler (i.e.,{value: Array[12]}
).isDayLightSavingsTime
, returns a Boolean stating whether daylight saving time is in effect for a givenDate
object passed as the first argument using the device's time zone and calendar; the value is stored in thedst
property of the object received as an argument in the success handler (i.e.,{dst: true}
).getFirstDayOfWeek
, returns as a number the first day of the week depending on the device's user preferences and calendar, assuming that the days of the week are numbered starting from 1 (= Sunday
). The string is stored in the value property of the object received as an argument in the success handler (i.e.,{value: 1}
).numberToString
, returns the number passed as the first argument formatted as a string according to the client's locale and preferences; the number is stored in thevalue
property of the object received as an argument in the success handler (i.e.,{value: '12,456,246'}
).stringToNumber
, returns the string passed as the first argument formatted as a number according to the client's locale and preferences; the number is stored in thevalue
property of the object received as an argument in the success handler (i.e.,{value: 1250.04}
).getNumberPattern
, returns an object received as an argument in the success handler containing:A pattern string to format and parse numbers according to the device's preferences
The number of fractional digits to use when parsing and formatting numbers, the rounding increment to use when parsing and formatting, and so on (i.e.,
{decimal: '.', fraction: 0, grouping: ',', negative: '-', pattern: '#,##0.###', positive: '', rounding: 0, symbol: '.'}
).
getCurrencyPattern
, returns an object received as an argument in the success handler containing a pattern string to format and parse currencies according to the currency code passed as the first argument and the device's preferences; the number of fractional digits to use when parsing and formatting numbers, the rounding increment to use when parsing and formatting, the ISO 4217 currency code for the pattern, and so on (i.e.,{code: 'EUR', decimal: '.', fraction: 2, grouping: ',', pattern: '$#,##0.00;(¤#,##0.00)', rounding: 0}
).
Tip
Both the numberToString
and stringToNumber
methods accept an optional options
object; through the type
property of this object, you can specify the format of the number (i.e., decimal
, percent
, or currency
).
Through the combination of the data provided by the methods of the globalization
object, it's possible to handle very complex scenarios and provide a highly localized app to the end user. In the following example you will learn how to load different strings depending on the device settings using Require.js and its i18n plugin (both of them are available for download at http://requirejs.org/docs/download.html
).