From the Palm Developer Blog.
Posted: 19 Jul 2011 11:18 AM PDT
The HP TouchPad with webOS 3.0 and the Enyo application programming framework bring significant opportunities for developers to leverage web standards for building great mobile applications and services. The growing availability of the TouchPad in countries outside North America means that developers like you will be able to bring their content to an expanding global audience. For the greatest opportunity to reach the widest consumer audience possible, it’s thus beneficial to ensure that your applications are available in the native languages of your target market countries.
The Enyo application programming framework makes it very easy to localize your applications.
The full source code for the sample application can be found here:
Sample Application Source Code
As the concepts of locale and resources are fundamental to localizing any application, let’s start with these topics.
In Enyo applications, a locale is defined with a specification string in the following format:
Typical cases are European vs. Canadian French (represented as “fr_fr” and “fr_ca”, respectively,) or European vs. Americas Spanish (represented as “es_es” and “es_us”, respectively.) The variant qualifier can be any ASCII string of characters (except for spaces and underscores) that further differentiates languages. These are not used as commonly as language and variant, and generally localized applications are limited to these.
In Enyo, a locale is represented by an instance of the enyo.g11n.Locale kind. You create an instance by passing a locale specification string. For example, to create a US English locale:
var myLocale = new enyo.g11n.Locale(“en_us”);
In Enyo, these strings are packaged with the application as one of more resource JSON files. These files use the naming convention language_variant.json. For example, an application might contain the file es_us.json to store Spanish strings:
Resource JSON files need to be saved in UTF-8 format for any special characters in the translated strings to render properly. Also, note that the byte order marker at the beginning of UTF-8 files can confuse the g11n resource loader. Some editors, like Notepad++, include the byte order mark when saving UTF-8 files. Editors like Sublime Text and Eclipse do not, so you might want to use one of these for creating your resource files.
Resources can then be loaded for use in the application using the enyo.g11n.Resources kind:
In addition to the global $L function, enyo.g11n.Resources also defines a $L method. This works the same way as the global version in that it loads the specified localized string. However, the string that is returned is the version from the resource JSON file used to create the Resources instance. Thus an application that lets the user change language can load the right resource strings at runtime:
https://developer.palm.com/content/api/dev-guide/enyo/globalization.html#enyo.g11n.datefmtparams
The sample application included with this article includes some controls for experimenting with the standard and custom date / time formatting options.
The Enyo application programming framework makes it very easy to localize your applications.
Sample Application
Included with this article is a sample Enyo application that demonstrates some of the key features and capabilities of the Enyo localization libraries. While it doesn’t cover every single detail of the framework, this sample application should get you started with the most essential elements of building webOS 3.0 applications for the global market. A screen shot of the application is shown below.The full source code for the sample application can be found here:
Sample Application Source Code
The g11n library
Enyo’s globalization support is implemented in the g11n library. This library includes g11n-base, which defines core globalization features, including locale, Enyo kinds for formatting dates, times, numbers and the like, and resources. g11n also contains libraries for parsing and formatting addresses, phone numbers, and names.As the concepts of locale and resources are fundamental to localizing any application, let’s start with these topics.
Locale
Simply put, a locale is a set of information that describes the language and country that determine the user interface of a device and its applications. A locale is primarily used to determine how textual information is to be displayed, such as which translations of text strings to use, how dates and currencies are to be formatted, and the like. Locale can also be used for non-textual information, such as default paper sizes for printing utilities and determining standard photo sizes for imaging applications.In Enyo applications, a locale is defined with a specification string in the following format:
[language][_region][_variant]
The language is a two-letter language ISO 639 language code, such as en for English, es for Spanish, fr for French, and so on. The region value is a two-letter ISO 3166 country code. Together, the language and region codes can thus specify country or regional variants of the same primary language. Typical cases are European vs. Canadian French (represented as “fr_fr” and “fr_ca”, respectively,) or European vs. Americas Spanish (represented as “es_es” and “es_us”, respectively.) The variant qualifier can be any ASCII string of characters (except for spaces and underscores) that further differentiates languages. These are not used as commonly as language and variant, and generally localized applications are limited to these.
In Enyo, a locale is represented by an instance of the enyo.g11n.Locale kind. You create an instance by passing a locale specification string. For example, to create a US English locale:
var myLocale = new enyo.g11n.Locale(“en_us”);
Current Locale
An Enyo application can read the locale currently in use by the host device by calling the currentLocale() method:var currentLocale = new enyo.g11n.currentLocale();
The return value is an enyo.g11n.Locale instance that contains the details about the current locale. The locale details can be read using value methods defined by the Locale kind. For example, the full locale specification string can be read using the getLocale method:var locale_spec = currentLocale.getLocale();
If the device’s current locale was Canadian French, locale_spec would contain the string “fr_ca.” Other methods can be used to parse out the locale details, such as getLanguage, getRegion and getVariant.Resource Files
Applications use locale to help localize their user interfaces for the language and culture of their users. The biggest component of application localization is displaying strings in the right language, and possibly, regional dialect. A localized application thus needs to include a set of translated strings for all user interface text in each of the languages supported by the application.In Enyo, these strings are packaged with the application as one of more resource JSON files. These files use the naming convention language_variant.json. For example, an application might contain the file es_us.json to store Spanish strings:
{
"Hello":"Hola",
"Goodbye":"Adios",
"Choose A Language":"Elige un idioma"
}
Each line of an Enyo resource JSON file contains an English string followed by the translated equivalent. The files are stored in a folder named “resources” right under the application root folder. Resource JSON files need to be saved in UTF-8 format for any special characters in the translated strings to render properly. Also, note that the byte order marker at the beginning of UTF-8 files can confuse the g11n resource loader. Some editors, like Notepad++, include the byte order mark when saving UTF-8 files. Editors like Sublime Text and Eclipse do not, so you might want to use one of these for creating your resource files.
Resources can then be loaded for use in the application using the enyo.g11n.Resources kind:
var resources = new enyo.g11n.Resources(locale);
The locale argument can either be a Locale instance, or a JSON formatted locale specifier, such as:var resources = new enyo.g11n.Resources({locale: "es_us"});
Now let’s take a look at where the rubber hits the road, specifically how to load individual localized strings into your Enyo application.The $L Function
The Enyo g11n library defines a global function, called $L, which is used to load localized resource strings. This function takes one string argument. The function will load the corresponding translated resource string in the resource JSON file corresponding to the default device locale. If there is no such resource string, $L returns the string argument unchanged. For example, if the default locale is es_us, using the example es_us.json file above:var helloString = $L("Hello");
would return the string “Hola.”In addition to the global $L function, enyo.g11n.Resources also defines a $L method. This works the same way as the global version in that it loads the specified localized string. However, the string that is returned is the version from the resource JSON file used to create the Resources instance. Thus an application that lets the user change language can load the right resource strings at runtime:
enyo.kind({
name: "MyApps.MainView",
kind: "enyo.Control",
components: [
{content: "Your String Here", name: "locstring"},
{kind: "Picker", name: "languagePicker",
label: "Device Default", value: "0", items: [
{caption: "Device Default", value: "0"},
{caption: "English", value: "en_us"},
{caption: "Spanish", value: "es_us"},
{caption: "French", value: "fr_fr"},
{caption: "Canadian French", value: "fr_ca"},
{caption: "German", value: "de_de"},
{caption: "Italian", value: "it_it"},
{caption: "Turkish", value: "tr_tr"}
],
onChange: "onLanguageSelected"
}],
onLanguageSelected: function(inSender) {
var selectedLanguage = inSender.getValue();
var currentLocale;
var localizedResources;
if (selectedLanguage === "0") {
currentLocale = enyo.g11n.currentLocale();
} else {
currentLocale = new enyo.g11n.Locale(selectedLanguage);
}
localizedResources = new enyo.g11n.Resources(currentLocale);
this.$.locstring.setContent(localizedResources.$L("Hello"));
}
});
Formats
Text strings are not the only things that need to get localized in a world-ready application. Many other things like dates, numbers, currency values, and even paper sizes are dependent on locale. Enyo provides a set of kinds for formatting such values, as well as phone numbers, addresses and names. To introduce the concepts, we will focus next on two of these, date and number formatting.Date Formats
enyo.g11n.DateFmt is the Enyo date / time formatter kind. Instances of this kind are created by passing one argument to the constructor, either a JSON object specifying a set of date formatting properties, or a string containing the custom date / time format to use. An example of the JSON approach is: dateFmt = new enyo.g11n.DateFmt({
locale: "es_us",
date: "long",
time: "long",
twelveHourFormat: true,
weekday: true
});
This locale property specifies the locale to use when formatting. If omitted, the device default will be used. The data and time properties are set to “long”, one of the predefined formats. The others are “short”, “medium”, and “full”, each of which renders different levels of date / time detail. Date and time can also be custom format strings if you want to fully customize information rendered. The full specification of allowed format strings can be found in the developer documentation here:https://developer.palm.com/content/api/dev-guide/enyo/globalization.html#enyo.g11n.datefmtparams
The sample application included with this article includes some controls for experimenting with the standard and custom date / time formatting options.
Number Formats
Number formatting is accomplished in a manner similar to date / time formatting. The enyo.g11n.NumberFmt is the kind to use for formatting numbers, currency values, and percentages. You specify a JSON object with the various formatting properties. These include locale, style, currency, currencyStyle, and fractionDigits. Not all of these are meaningful in all cases: the value of style determines what type of number is being formatted. The style property can be one of “number”, “percent”, or “currency”. fractionDigits specifies the number of places displayed after the decimal point. If currency is specified as the style, currencyStyle can be set to “iso” or “common” to specify how the currency sign is rendered. If “iso” is specified, the ISO 4217 currency code is used. If “common”, the locale specific currency symbol is used (for example, USD versus $.) The currency property lets you specify the ISO 4217 currency code. So, if you wanted to format 12.50 Argentinean Pesos by specifying the ISO 4217 currency code (ARS) but display the value with the peso symbol, you could do this:
var numFmt = new enyo.g11n.NumberFmt({
style: "currency",
currency: "ARS",
currencyStyle: "common"
});
var pesosString = numFmt.format("12.50");