JsWorld
Library Design and Features
1. Clean separation between formatting logic and locale data
The JsWorld library makes a clean separation between formatting logic and locale data. So, on one hand you've got the generic classes for formatting and parsing numbers, money and dates/times, and on the other -- a set of loadable data files describing the formatting rules for each supported locale. You as a user have freedom to easily fine-tune formatting to your particular needs and I, as a maintainer of the library, can quickly update it as newer locale data is published by the Unicode Consortium.

The formatting classes are located in file JsWorld.js
(and the minified JsWorld.min.js), while
the definitions for the 300+ locales are put into files in the locales/
directory.
2. Use of POSIX-style locale properties
Care was taken to keep things standard and unsurprising. To describe the formatting conventions of the various locales JsWorld follows the POSIX specification, which should be well known to OS and systems programmers. And while the POSIX locale definition standard may have some shortcomings, it is good enough for most localisation purposes.
| Category | POSIX specification |
|---|---|
| Numeric formatting | LC_NUMERIC |
| Monetary formatting | LC_MONETARY |
| Date/time formatting | LC_TIME |
If you open one of the locale data files in the locales/js/
directory, you'll see a JavaScript object with the various POSIX LC_NUMERIC,
LC_MONETARY and LC_TIME properties. Here is the file storing the properties
for the French locale:
locales/js/fr_FR.js
if(typeof POSIX_LC == "undefined") var POSIX_LC = {};
POSIX_LC.fr_FR = {
"decimal_point" : ",",
"thousands_sep" : "\u00a0",
"grouping" : "3",
"abday" : ["dim.","lun.","mar.",
"mer.","jeu.","ven.",
"sam."],
"day" : ["dimanche","lundi","mardi",
"mercredi","jeudi","vendredi",
"samedi"],
"abmon" : ["janv.","f\u00e9vr.","mars",
"avr.","mai","juin",
"juil.","ao\u00fbt","sept.",
"oct.","nov.","d\u00e9c."],
"mon" : ["janvier","f\u00e9vrier","mars",
"avril","mai","juin",
"juillet","ao\u00fbt","septembre",
"octobre","novembre","d\u00e9cembre"],
"d_fmt" : "%d/%m/%y",
"t_fmt" : "%H:%M:%S",
"d_t_fmt" : "%e %B %Y %H:%M:%S %Z",
"am_pm" : ["AM","PM"],
"int_curr_symbol" : "EUR ",
"currency_symbol" : "\u20ac",
"mon_decimal_point" : ",",
"mon_thousands_sep" : "\u00a0",
"mon_grouping" : "3",
"positive_sign" : "",
"negative_sign" : "-",
"int_frac_digits" : 2,
"frac_digits" : 2,
"p_cs_precedes" : 0,
"n_cs_precedes" : 0,
"p_sep_by_space" : 1,
"n_sep_by_space" : 1,
"p_sign_posn" : 1,
"n_sign_posn" : 1,
"int_p_cs_precedes" : 0,
"int_n_cs_precedes" : 0,
"int_p_sep_by_space" : 1,
"int_n_sep_by_space" : 1,
"int_p_sign_posn" : 1,
"int_n_sign_posn" : 1
};
Note that all non-ASCII characters have been replaced with the appropriate Unicode escape sequences.
The locale data is used to construct a jsworld.Locale
object which is then required to create a corresponding formatting
or parsing object.
// Create a new locale object from the fr_FR locale data var lc = new jsworld.Locale(POSIX.fr_FR); // Print the current date in French var formatter = new jsworld.DateTimeFormatter(lc); document.writeln(formatter.formatDate(new Date())); // Print the current time in French document.write(formatter.formatTime(new Date()));
The meaning of the individual locale properties is described in the corresponding POSIX specifications (see LC_NUMERIC, LC_MONETARY and LC_TIME) as well as in JsWorld's API docs.
3. Locale data formats
Depending on the type of your application, you have a choice between three different formats for locale data.
| Locale data format | File location | Suitable for |
|---|---|---|
| JavaScript | locales/js/ | Static include in HTML docs via <script> tag |
| JSON | locales/json/ | Dynamic loading via XMLHTTPRequest |
| Mozilla properties | locales/mozilla/ | Mozilla XULRunner applications |
3.1 JavaScript
For common web applications you should use the regular JavaScript data
files in the locales/js/ directory. Use a <script> tag to
include them, which places an object "POSIX_LC.<locale_code>"
into your JavaScript namespace. The namespacing is done in way which allows
you to include multiple locale definitions, without causing clashes.
<!-- Include the JsWorld formatting classes --> <script type="text/javascript" src="JsWorld.js"></script> <!-- Include the en_US locale data --> <script type="text/javascript" src="locales/js/en_US.js"></script> <!-- Include the de_DE (German) locale data --> <script type="text/javascript" src="locales/js/de_DE.js"></script> <script> // Create formatter for US locale var usLocale = new jsworld.Locale(POSIX_LC.en_US); var usNumericFormatter = new jsworld.NumericFormatter(usLocale); // Create formatter for German locale var germanLocale = new jsworld.Locale(POSIX_LC.de_DE); var germanNumericFormatter = new jsworld.NumericFormatter(germanLocale); // Show number in US locale alert(usNumericFormatter(25000.10)); // Show number in German locale alert(germanNumericFormatter(74999.90)); </script>
You also have the option to include the definitions of all available
locales (over 300) by pointing to the locales/js/POSIX_LC.js
file. This, however, will consume a lot more memory and bandwidth as the
aggregate data for all locales takes up about 500KB.
<!-- Include data for all available locales --> <script type="text/javascript" src="locales/js/POSIX_LC.js"></script>
3.2 JSON
For highly interactive web applications (also known as AJAX or Web 2.0)
you may look at the locale data files in the locales/json/ directory.
They are in the form of JSON,
making them suitable for dynamic loading via
XMLHTTPRequest.
<!-- Include the JsWorld formatting classes -->
<script type="text/javascript" src="JsWorld.js"></script>
<script>
// Example assumes Firefox 3.5!
// The locale data file (e.g. Canadian English) in JSON format
var url = "http://my-site.com/jsworld/locales/json/en_CA.json";
// Make request
var req = new XMLHttpRequest();
req.open("GET", url, true);
req.onreadystatechange = function (aEvt) {
if (req.readyState == 4) {
if(req.status == 200) {
// Parse response JSON
var localeData = JSON.parse(req.responseText);
// Create new formatter with received locale properties
var lc = new jsworld.Locale(localeData);
var dateTimeFormatter = new jsworld.DateTimeFormatter(lc);
}
else {
alert("Error loading locale data");
}
}
};
req.send(null);
</script>
3.3 Mozilla property files
Finally, the locale data is also made available as Mozilla
property files.
These are located in the locales/mozilla/ directory.
The format is suitable for localising
XULRunner
applications and Firefox add-ons.
Here is a useful example how to import all items from a Mozilla property file and pack them into a single JavaScript object:
// XPCOM shorthands
const Cc = Components.classes;
const Ci = Components.interfaces;
// Location of the properties file
var stringBundleURI = "chrome://app/locale/en_US.properties";
// Open properties file
var stringService = Cc["@mozilla.org/intl/stringbundle;1"]
.getService(Ci.nsIStringBundleService);
var sb = stringService.createBundle(stringBundleURI);
// Retrieve locale data
var localeProps = {};
var propertyList = sb.getSimpleEnumeration();
while (propertyList.hasMoreElements()) {
var prop = propertyList.getNext().QueryInterface(Ci.nsIPropertyElement);
localeProps[prop.key] = prop.value;
}
// Create locale object from the raw properties
var lc = new jsworld.Locale(localeProps);
// Create the corresponding formatters
var nf = new jsworld.NumericFormatter(lc);
var mf = new jsworld.MonetaryFormatter(lc);
var dtf = new jsworld.DateTimeFormatter(lc);
4. Exception handling
The formatting classes will raise an exception if something goes wrong, e.g. on:
- Invalid or missing locale properties
- Invalid input to the format method
You can handle these error conditions by using a try-catch clause:
try {
var lc = new jsworld.Locale(POSIX_LC.en_GB);
var mf = new jsworld.MonetaryFormatter(lc);
// attempt to format an invalid amount
mf.format("abc");
} catch (error) {
alert(error);
}
5. Character encoding issues
Do you see garbled output in the browser? Most probably the cause is character encoding.
- The strings in the locale data files are stored in UTF-8 format. Make sure your web page is served with the same encoding.
- If you create your own locale definitions make sure that all characters outside the ASCII range are saved as a Unicode escape sequence (for example, specify the pound sign as "\u00a3" instead of "₤").
- If you still see strange output, they your OS probably lacks the appropriate font to display the required symbols.
6. API documentation
Auto-generated API documentation is provided with the package as well as here online:
7. Platforms
Here is a list of all platforms where the JsWorld library has been successfully tested:
- Web browsers:
- Mozilla Firefox 3.0, 3.1, 3.5, 3.6, 4.0, 5.0, 6.0, 7.0
- Internet Explorer 6, 7, 8, 9
- Apple Safari 3.0, 3.2, 4.0, 5.0
- Google Chrome 4.0 - 13.0
- Opera 9.6, 10.0
- Other runtimes with JavaScript support:
- Mozilla XULRunner 1.9.0, 1.9.1, 1.9.2, 5.0, 6.0, 7.0