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.
Contents
Concepts
Cookbook
- Registering Strings (Manually)
- Registering Strings (On Startup)
- Setting The Locale
- Setting The Default Locale
- Getting The Locale
- Localizing A String
- Localizing Booleans
- Localizing Numbers
- Localizing A Keyboard
Code
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