Globalize
A JavaScript library for internationalization and localization that leverage the
official Unicode CLDR JSON data. The library works both for the browser and as a
Node.js module.
Heads up!
We're working on the migration to using the Unicode CLDR. This is an alpha version of Globalize: 1.0.0-pre.
Patches to the previous stable codebase probably can't be used. If you have a
problem, please create an issue first before trying to patch it.
Getting Started
Why globalization?
Each language, and the countries that speak that language, have different
expectations when it comes to how numbers (including currency and percentages)
and dates should appear. Obviously, each language has different names for the
days of the week and the months of the year. But they also have different
expectations for the structure of dates, such as what order the day, month and
year are in. In number formatting, not only does the character used to
delineate number groupings and the decimal portion differ, but the placement of
those characters differ as well.
A user using an application should be able to read and write dates and numbers
in the format they are accustomed to. This library makes this possible,
providing an API to convert user-entered number and date strings - in their
own format - into actual numbers and dates, and conversely, to format numbers
and dates into that string format.
About Globalize
Where to use it?
It's designed to work both in the browser, or in
Node.js. It supports both AMD and CommonJS.
Where does the data come from?
Globalize uses the Unicode CLDR, the largest and
most extensive standard repository of locale data.
We do NOT embed any i18n data within our library. However, we make it really
easy to use. Read the section How to get and load CLDR JSON data for
more information on its usage.
Load and use only what you need
Globalize is split in modules: core, number (coming soon), date, and translate.
We're evaluating other modules, eg. plural, ordinals, etc.
The core implements Globalize.load( cldrData )
, and
Globalize.locale( locale )
.
The date module extends core Globalize, and adds Globalize.formatDate( value, pattern, locale )
, and Globalize.parseDate( value, patterns, locale )
.
The translate module extends core Globalize, and adds
Globalize.loadTranslations( locale, json )
, and
Globalize.translate( path , locale )
.
More to come...
Browser Support
We officially support:
- Firefox (latest - 1)+
- Chrome (latest - 1)+
- Safari 5.1+
- IE 8+
- Opera (latest - 1)+
Dry tests show Globalize also works on the following browsers:
- Firefox 4+
- Safari 5+
- Chrome 14+
- IE 6+
- Opera 11.1+
If you find any bugs, please just let us
know. We'll be glad to fix them for
the officially supported browsers, or at least to update the documentation for
the unsupported ones.
Usage
All distributables are UMD wrapped. So, it supports AMD, CommonJS, or global
variables (in case neither AMD nor CommonJS have been detected).
Example of usage with script tags:
<script src="./external/cldrjs/dist/cldr.js"></script>
<script src="./dist/globalize.js"></script>
<script src="./dist/globalize/date.js"></script>
Example of usage on AMD:
bower install cldrjs globalize
require.config({
paths: {
cldr: "bower_components/cldrjs/dist/cldr.runtime",
globalize: "bower_components/globalize/dist/globalize"
}
});
require( [ "globalize", "globalize/date" ], function( Globalize ) {
...
});
Example of usage with Node.js:
npm install cldrjs globalize
var Globalize = require( "globalize" );
...
How to get and load CLDR JSON data
The Unicode CLDR is available for download as JSON
(json.zip
). This file
contains the complete data of what the Unicode CLDR Project considers the top
20 languages (at the time of this writing).
You can generate the JSON representation of the languages not available in the
ZIP file by using the official conversion tool
(tools.zip
). This ZIP contains a
README with instructions on how to build the data.
You can choose to generate unresolved data to save space or bandwidth (-r false
option of the conversion tool), and instead have it resolve at runtime.
For the examples below, first fetch CLDR JSON data:
wget http://www.unicode.org/Public/cldr/latest/json.zip
unzip json.zip -d cldr
Example of embedding CLDR JSON data:
<script>
Globalize.load({
main: {
en: {
...
}
},
supplemental: {
likelySubtags: {
...
},
timeDate: {
...
},
weekData: {
...
}
}
});
</script>
Example of loading it dynamically:
<script src="jquery.js"></script>
<script>
$.get( "cldr/en/ca-gregorian.json", Globalize.load );
$.get( "cldr/supplemental/likelySubtags.json", Globalize.load );
$.get( "cldr/supplemental/timeData.json", Globalize.load );
$.get( "cldr/supplemental/weekData.json", Globalize.load );
</script>
Example using AMD (also see our functional tests):
define([
"globalize",
"json!fixtures/cldr/main/en/ca-gregorian.json",
"json!fixtures/cldr/supplemental/likelySubtags.json",
"json!fixtures/cldr/supplemental/timeData.json",
"json!fixtures/cldr/supplemental/weekData.json",
"globalize/date"
], function( Globalize, enCaGregorian, likelySubtags, timeData, weekData ) {
Globalize.load( enCaGregorian );
Globalize.load( likelySubtags );
Globalize.load( timeData );
Globalize.load( weekData );
});
Example using Node.js:
var Globalize = require( "globalize" );
Globalize.load( require( "./cldr/supplemental/likelySubtags.json" ) );
Globalize.load( require( "./cldr/supplemental/timeData.json" ) );
Globalize.load( require( "./cldr/supplemental/weekData.json" ) );
Globalize.load( require( "./cldr/en/ca-gregorian.json" ) );
API
Core module
Globalize.load( cldrJSONData )
This method allows you to load CLDR JSON locale data. Globalize.load()
is a
proxy to Cldr.load()
. For more information, see
https://github.com/rxaviers/cldrjs#readme.
Parameters:
Globalize.locale( [locale] )
Set default locale, or get it if locale argument is omitted.
Parameters:
- locale The locale string, eg. "en", "pt_BR", or "zh_Hant_TW".
An application that supports globalization and/or localization will need to
have a way to determine the user's preference. Attempting to automatically
determine the appropriate culture is useful, but it is good practice to always
offer the user a choice, by whatever means.
Whatever your mechanism, it is likely that you will have to correlate the
user's preferences with the list of locale data supported in the app. This
method allows you to select the best match given the locale data that you
have included and to set the Globalize locale to the one which the user
prefers.
Globalize.locale( "pt" );
console.log( Globalize.locale().attributes );
LanguageMatching TBD (CLDR's spec http://www.unicode.org/reports/tr35/#LanguageMatching).
Number module
Globalize.formatNumber( value [, attributes] [, locale] )
Format a number according to the given attributes and the given locale (or the
default locale if not specified).
Parameters:
- value Number to be formatted, eg.
3.14
; - attributes Optional
- style: Optional String
decimal
(default), or percent
; - minimumIntegerDigits: Optional non-negative integer Number value indicating
the minimum integer digits to be used. Numbers will be padded with leading
zeroes if necessary;
- minimumFractionDigits and maximumFractionDigits: Optional non-negative
integer Number values indicating the minimum and maximum fraction digits to
be used. Numbers will be rounded or padded with trailing zeroes if
necessary;
- minimumSignificantDigits and maximumSignificantDigits: Optional positive
integer Number values indicating the minimum and maximum fraction digits to
be shown. Either none or both of these properties are present; if they are,
they override minimum and maximum integer and fraction digits. The formatter
uses however many integer and fraction digits are required to display the
specified number of significant digits;
- round: Optional String with rounding method
ceil
, floor
, round
(default), or truncate
; - useGrouping: Optional boolean (default is true) value indicating whether a
grouping separator should be used;
- locale Optional locale string that overrides default;
Globalize.locale( "en" );
Globalize.formatNumber( 3.141592 );
Globalize.formatNumber( 3.141592, {}, "es" );
Globalize.formatNumber( 3.141592, {}, "ar" );
Controlling digits by specifying integer and fraction digits counts:
Globalize.formatNumber( 3.141592, { maximumFractionDigits: 2 } );
// "3.14"
Globalize.formatNumber( 1.5, { minimumFractionDigits: 2 } );
// "1.50"
Controlling digits by specifying significant digits counts:
Globalize.formatNumber( 3.141592, {
minimumSignificantDigits: 1,
maximumSignificantDigits: 3
});
// "3.14"
Globalize.formatNumber( 12345, {
minimumSignificantDigits: 1,
maximumSignificantDigits: 3
});
// "12,300"
equal( Globalize.formatNumber( 0.00012345, {
minimumSignificantDigits: 1,
maximumSignificantDigits: 3
});
// "0.000123"
Using different rounding functions example:
Globalize.formatNumber( 3.141592, { maximumFractionDigits: 2, round: "ceil" } );
// "3.15"
Globalize.parseNumber( value, [formats], [locale] )
TBD
Date module
Globalize.formatDate( value, format [, locale] )
Format a date according to the given format and locale (or the current locale if not specified).
Parameters:
- value Date instance to be formatted, eg.
new Date()
; - format
- String, skeleton. Eg "GyMMMd";
- Object, accepts either one:
- Skeleton, eg.
{ skeleton: "GyMMMd" }
. List of all skeletons [TODO]; - Date, eg.
{ date: "full" }
. Possible values are full, long, medium, short; - Time, eg.
{ time: "full" }
. Possible values are full, long, medium, short; - Datetime, eg.
{ datetime: "full" }
. Possible values are full, long, medium, short; - Raw pattern, eg.
{ pattern: "dd/mm" }
. List of all date
patterns;
- locale Optional locale string that overrides default;
Globalize.formatDate( new Date( 2010, 10, 30, 17, 55 ), { datetime: "short" } );
Globalize.formatDate( new Date( 2010, 10, 30, 17, 55 ), { datetime: "short" }, "de" );
Comparison between different locales.
locale | Globalize.formatDate( new Date( 2010, 10, 1, 17, 55 ), { datetime: "short" } ) |
---|
en | "11/1/10, 5:55 PM" |
en_GB | "01/11/2010 17:55" |
de | "01.11.10 17:55" |
zh | "10/11/1 下午5:55" |
ar | "1/11/2010 5:55 م" |
pt | "01/11/10 17:55" |
es | "1/11/10 17:55" |
Globalize.parseDate( value [, formats] [, locale] )
Parse a string representing a date into a JavaScript Date object, taking into
account the given possible formats (or the given locale's set of preset
formats if not provided). As before, the current locale is used if one is not
specified.
Parameters:
- value String with date to be parsed, eg.
"11/1/10, 5:55 PM"
; - formats Optional array of formats;
- locale Optional locale string that overrides default
Globalize.locale( "en" );
Globalize.parseDate( "1/2/13" );
Globalize.locale( "es" );
Globalize.parseDate( "1/2/13" );
Translate module
Globalize.loadTranslation( locale, translationData )
Load translation data per locale.
Parameters:
- locale Locale string;
- translationData A JSON object with translation mappings;
Globalize.loadTranslation( "pt_BR", {
greetings: {
hello: "Olá",
bye: "Tchau"
}
});
Globalize.translate( path [, locale] )
Translate item given its path.
Parameters:
- path Translation item path;
- locale Optional locale string that overrides default
Globalize.locale( "pt_BR" );
Globalize.translate( "greetings/bye" );
Development
File structure
├── bower.json (metadata file)
├── CONTRIBUTING.md (doc file)
├── dist/ (output of built bundles)
├── external/ (external dependencies, eg. cldr.js, QUnit, RequireJS)
├── Gruntfile.js (Grunt tasks)
├── LICENSE (license file)
├── package.json (metadata file)
├── README.md (doc file)
├── src/ (source code)
│ ├── build/ (build helpers, eg. intro, and outro)
│ ├── common/ (common function helpers across modules)
│ ├── core.js (core module)
│ ├── date/ (date source code)
│ ├── date.js (date module)
│ ├── translate.js (translate module)
│ └── util/ (basic JavaScript helpers polyfills, eg array.map)
└── test/ (unit and functional test files)
├── fixtures/ (CLDR fixture data)
├── functional/ (functional tests)
├── functional.html
├── functional.js
├── unit/ (unit tests)
├── unit.html
└── unit.js
Source files
The source files are as granular as possible. When combined to generate the
build file, all the excessive/overhead wrappers are cut off. It's following
the same build model of jQuery and Modernizr.
Core, and all modules' public APIs are located in the src/
directory. For
example: core.js
, date.js
, and translate.js
.
Build
Install Grunt and external dependencies. First, install the
grunt-cli and
bower packages if you haven't before. These should be installed
globally (like this: npm install -g grunt-cli bower
). Then:
npm install && bower install
Build distribution files.
grunt
Tests
Tests can be run either in the browser or using Node.js (via Grunt).
Unit tests
To run the unit tests, run grunt test:unit
, or open
file:///.../globalize/test/unit.html
in a browser. It tests the very specific functionality
of each function (sometimes internal/private).
The goal of the unit tests is to make it easy to spot bugs, easy to debug.
Functional tests
To run the functional tests, create the dist files by running grunt
. Then, run
grunt test:functional
, or open
file:///.../globalize/test/functional.html
in a browser. Note that grunt
will
automatically run unit and functional tests for you to ensure the built files
are safe.
The goal of the functional tests is to ensure that everything works as expected when it is combined.