Localize

TIBET Localization

wins

  • Built-in localization of strings, dates, numbers, booleans, etc.
  • Extensible localization of both parsing and formatting for your types.
  • Fully configurable keyboard mapping for non-ASCII keyboards.

concepts

Localization support is woven into TIBET at a very low level and is easy to leverage.

From parsing and formatting Strings, Dates, Numbers, Booleans, etc. to remapping signal names from the keyboard to match non-ASCII keyboards, TIBET lets you do more than any other framework to ensure your applications support multiple locales effectively.

TIBET supports localization by adding new types such as TP.i18n.Locale, extending native types (Date, Number, String, etc) with localizing methods like construct, and via primitives such as TP.sc, TP.dc, and TP.nc. Most TIBET operations automatically localize any content.

In terms of concrete processing logic the localization subsystem makes use of a number of "getBestMethod" patterns. If you're not familiar with TIBET's getBestMethod feature it's a way of using type information and reflection to determine the best method, e.g. the most specific method to use for handing a particular request.

Common methods using the getBestMethod pattern include as, from, format and parse. For example, if you ask a Locale to parse() an object it will use that object's type to look for a parse{Typename} method. Pass a Date and ultimately parseDate will be invoked.

One key advantage of the getBestMethod approach is its ability to adapt to new types without having to alter library code. If you create an Employee type and want to localize it you can implement formatEmployee and/or parseEmployee and it will "just work".

cookbook

Registering Strings (Manually)

You can register strings using the TP.i18n.Locale.registerStrings method at any time:

var strings = {
    en: {
        HELLO: 'Hello',
        GOODBYE: 'Cheers'
    },

    'en-us': {
        HELLO: 'Sup',
        GOODBYE: 'Later'
    },

    fr: {
        HELLO: 'Bonjour',
        GOODBYE: 'Au Revoir'
    }
};

TP.i18n.Locale.registerStrings(strings);

Registering Strings (On Startup)

You can register strings on application startup using the AppDidInitialize signal handler.

In the example below we assume there's a JSON file containing all our localized string data in ~app_dat (usually your application's public/TIBET-INF/dat directory).

By using a simple TIBET URI we can fetch that content and pass it to the root Locale type for registration:

APP.hello.Application.Inst.defineHandler('AppDidInitialize',
function() {
    var url,
        strings;

    url = TP.uc('~app_dat/strings.json');
    strings = url.getContent();

    TP.i18n.Locale.registerStrings(strings);
});

Setting The Locale

To set a particular Locale use the TP.sys.setLocale method and provide it with a proper ISO code such as en, en-us, fr, etc:

TP.sys.setLocale('fr');

Setting The Default Locale

You can tell TIBET what you want the current locale to be on startup by using the tibet.locale configuration setting.

In the example below we set it to fr rather than the default null value:

//  what is the currently active locale (in xml:lang format)
TP.sys.setcfg('tibet.locale', 'fr');

Getting The Locale

To query for the current locale use TP.sys.getLocale:

TP.sys.getLocale();
...

You will receive back the proper subtype of TP.i18n.Locale for the current system locale.

Localizing A String

To localize a string you can use either TP.sc, the String.construct method, or the target Locale's localizeString method.

In the example below we assume the Locale has been set to 'fr' and the strings from the manual loading cookbook entry have been configured:

TP.sc('HELLO');
Bonjour

// or

String.construct('HELLO');
Bonjour

// or

TP.sys.getLocale().localizeString('HELLO');
Bonjour

You can also change the locale by passing it to the TP.sys.getLocale call:

TP.sys.getLocale('en-us').localizeString('HELLO');
Sup

Localizing Booleans

Booleans ultimately only have two values, true and false. That said, you can express true and false in string form in a wide variety of ways. TIBET offers support for this via the parse getBestMethod pattern and the parseBoolean method which leverages locale information to determine whether an incoming string represents a true or false value.

Below is a snippet from the German locale (de) which TIBET pre-configures with a variety of settings including a number of different ways of expressing true and false in string form:

TP.i18n.DELocale.Type.defineAttribute('falseStrings',
    TP.ac('0', '', 'nein', 'Nein', 'NEIN', 'n', 'N',
        'f', 'F', 'falsch', 'Falsch', 'FALSCH'));

With that locale in place you can see that TIBET's boolean contruct functionality (accessible via either Boolean.construct or TP.bc) will attempt to parse using the current locale:

TP.sys.setLocale('de');
TP.bc('Nein');
false
TP.bc('Falsch');
false

NOTE that in the previous example if you set the locale to anything else the string Nein results in Boolean value of true since it's non-empty.

Localizing Numbers

Unlike strings and booleans, numbers have a universal input format. Still, depending on the locale, a number may output differently due to differences in the thousands separator or other factors.

TIBET's Locale types provide support for configuring your locale so it will properly output numerical strings.

The de (German) locale uses . as its thousands separator, which we can see in the following sample code:

TP.sys.setLocale('de');
'#{###,###}'.substitute(123456789);
123.456.789
TP.sys.setLocale('en-us');
'#{###,###}'.substitute(123456789);
123,456,789

In the previous examples we use TIBET's string substitution feature to template a numerical value into a specific output format. Within the template we always use the , (comma) to denote thousands separators should be shown, however note that the output uses the proper thousands separator for the current locale.

Localizing A Keyboard

Rather than rely only on ASCII 101 keycodes TIBET actually makes use of a keyboard map, allowing you to localize your keyboard as needed. See the documentation on TIBET Devices for specifics on how to map keyboard codes to TIBET signal name components.

code

The TP.i18n.Locale type is defined in ~lib/src/tibet/kernel/TIBETLocalization.js.

Locale types are found in ~lib/src/xml/lang/*. This directory includes placeholders for French, German, and English including samples for both US and UK variations of English.

Device logic (for keyboards etc.) is found in ~lib/src/tibet/kernel/TIBETDeviceTypes.js