UsefulJS.Locale

The Locale module provides support for number and date formatting. A large number of languages and locales are supported out of the box and the locale framework is extensible.

Extending supported locales

Extending the supported locales is a (relatively) simple matter of defining an Object with the relevant properties. Although there are a large number of properties, the locale system has a simple inheritance mechanism so that you only have to fill in the properties that differ from the base locale.

The templates directory has a file called locale_template.js that you can adapt for your own purposes. The example is a self-executing function but if you don't need to define aliases or compute anything as part of the locale definition, this can be a simple list of properties.

Locale identification

Locales should be identified using BCP 47 tags which take the form

<LANGUAGE>-<SCRIPT>-<COUNTRY>

Only the language tag is necessary for most locales; the other parts are specializations for a particular country. For example, "sr" is the tag for Serbian in the default Cyrillic script. "sr-Latn" is the tag for Serbian using the Latin alphabet while "sr-Latn-ME" is the tag for Serbian using the Latin alphabet in Montenegro. See RFC 5646 for more details on language tags and the relevant IANA documentation for the correct language codes.

Inheritance

The UsefulJS core defines a default locale ("def") that is the base of all other locales. If your locale derives from the default locale (via its base property) then you only have to define properties that differ from the default locale. If the base is something other than "def", then you only need to define properties that differ from the base locale AND the def locale. Inheritance can be any number of levels deep. For example, the ar-TZ (Tunisia) locale has the following inheritance:

ar-TZ -> ar-DZ (Algeria) -> ar-MA (Morocco) -> ar-AE (United Arab Emirates) -> ar (Arabic) -> def (Default)

Locale properties

Property Type Meaning PurposeNotes Default
n String Name Displayable, localized name - English
base String Parent locale The base locale for inheritance purposes - null
ndigits String Numeric digits The default digits used for representing numbers See UsefulJS.Number latn
ds String Decimal separator The character that separates the integer component of a number from the decimal part - .
gs String Numeric group separator The character that separates groups when a number is formatted for readability - ,
gc Array Group counts How many digits are in each group of the number. Most locales use a count of 3 as in 10,000,000; in Indian locales this would be 1,00,00,000 which makes the gc value [3,2] [3]
nn String Negative number pattern The template used for rendering negative numbers "%1" is replaced with the formatted absolute value -%1
cc String Currency code The ISO 4217 currency code This is a locale-neutral currency representation; codes are listed here. EUR
cu Object Currency units Localized currency symbols This maps three-letter currency codes to currency symbols; for example, { USD : "US$", AUD : "$" }. -
cf Array Currency formats The templates used for rendering positive and negative currency values '$' is replaced with the currency code or symbol; "%1" is replaced with the formatted absolute value ["$%1", "-$%1"]
pc Array Percentage codes The templates used for rendering positive and negative percent values "%1" is replaced with the formatted absolute value ["%1%", "-%1%"]
ddigits String Date digits The default digits used for representing dates See UsefulJS.Date latn
mc Array Compact months Short forms of month names Some locales do not have a compact form for month names; use null. ["Jan", ... "Dec"]
mf Array Full months Long forms of month names - ["January", ... "December"]
mn Array Nominative month names Month names in the nominative case Some languages distinguish between, e.g. "18 September" and "September 2015", using genitive case for the former and nominative for the latter. When this is the case use the genitive forms in mf and the nominative forms in mn. null
da Array Abbreviated day names Shortest forms of day names These are the day codes that are returned by the UsefulJS.Date cal function. If this not meaningful in the locale, use null. ["Su", ... "Sa"]
dc Array Compact day names Short forms of day names Some locales do not have a compact form for day names; use null. ["Sun", ... "Sat"]
df Array Full day names Long forms of day names Values should always start at the equivalent of Sunday ["Sunday", ... "Saturday"]
um Array Uppercase meridiem names Local equivalent of AM/PM 12 hour clock is not meaningful in all locales ["AM", "PM"]
lm Array Lowercase meridiem names Local equivalent of am/pm - ["am", "pm"]
hd Array Hour divisions The starting hours of each division of the day Some locales may divide the hours of the day into more than two divisions [0, 12]
hour12 Boolean 12 hour clock flag Default value of the hour12 format property when using the Intl API Set to true if the locale uses 12 hour clock by default false
sc Object Strftime codes Macros for strftime Some strftime codes (such as %c) are expanded to a sequence of other strftime codes. Macros that may need to be defined are: %c (date and time), %x (date), %X (time) and %r (time with am/pm). { "%c" : "%a %d %b %Y %X", %x" : "%d/%m/%Y", "%X" : "%T", "%r" : "%I:%M:%S %p" }
dfmt Object Date format strings strftime sequences for formatting dates using the Intl API See below. See below
tfmt Object Time format strings strftime sequences for formatting times using the Intl API See below. See below
datetime String Date and time template The template used to combine the format strings used for rendering the date and the time "{d}" is replaced with the date format string while "{t}" is replaced with the time format string. {d} {t}
dateera String Date and era template The template used to combine the format string used for rendering the date and the era "{d}" is replaced with the date format string. {d} %!
time12 String Twelve hour clock template The template used to combine the format string used for rendering the time and am/pm "{t}" is replaced with the time format string. {t} %p
timetz String Time + timezone template The template used to combine the format string used for rendering the time and the timezone "{t}" is replaced with the time format string. {t} GMT%z
fd Number First day of the week 0-based value of the first day of the week where 0 corresponds to Sunday and 6 corresponds to Saturday - 1
calendar String Default calendar The name of the default calendar for the locale. See UsefulJS.Date gregory
<CALENDAR NAME> Object Calendar property overrides Allow overriding of selected calendar properties For example, to override the strings used for AD and BC, add a gregory property whose value is { era : ["<AD equivalent>", "<BC equivalent>"] } null

Date and time formats

When using the Intl-compatible API to format dates, rather than specifying a format string, you specify the properties that you'd like the output to have. Sensible property combinations result in sensible output via the format strings in the dfmt and tfmt Objects in the Locale definition. The keys use the characters 't', 'n' and '-' where 't' represents a text field, 'n' represents a numeric field and '-' represents an absent field. Rather than having to specify all possible combinations, you only need to specify a sensible subset and only when they differ from the base locale. dfmt keys are four characters representing weekday, year, month and day while tfmt keys are three characters representing hours, minutes and seconds. The following table lists the sensible combinations, together with their values in the def locale and example output.

Key Meaning Format String Example
dfmt
tntn Weekday, year, month, day %A, %e %B %Y Saturday, 19 September 2015
tnnn Weekday, year, month, day %A, %e/%N/%Y Saturday, 19/9/2015
-ntn Year, month, day %e %B %Y 19 September 2015
-nnn Year, month, day %e/%N/%Y 19/9/2015
-nt- Year, month %B %Y September 2015
-nn- Year, month %N/%Y 9/2015
--tn Month, day %e %B 19 September
--nn Month, day %e/%N 19/9
tfmt
nnn Hours, minutes, seconds %k:%M:%S 2:05:24
nn- Hours, minutes %k:%M 13:27

Static properties

UsefulJS.Locale.current

This read/write value is the fallback locale when no locales are specified when constructing a format object. It is initialized with information obtained from the browser which, depending on the browser, may or may not reflect a user's preference. To illustrate, assuming that the library sets "en" (US English) as the current locale:

(new UsefulJS.Date.Format()).format(new Date()); // 9/19/2015
UsefulJS.Locale.current = "fr";
(new UsefulJS.Date.Format()).format(new Date()); // 19/9/2015

If the browser supports Object.defineProperty, the current property is accessed through a getter and setter which will raise a TypeError if you attempt to set a silly value. If you set an unsupported locale, a sensible fallback will be used. To illustrate:

UsefulJS.current = null; // throws TypeError
UsefulJS.current = "zz";
UsefulJS.current         // "en"
UsefulJS.current = "zh-Hant-CN";
UsefulJS.current         // "zh"

If the browser does not support Object.defineProperty, you can set silly values which will make bad things happen. So don't!

Static methods

The UsefulJS.Locale functions are called by the numeric and date formatting code but they are public functions that your own applications may call.

alias

Sets aliases for a defined locale (two or more arguments) or resolves an alias (single argument).

Syntax
UsefulJS.Locale.alias(loc[, alias1, alias2 ...])
Parameters

Returns: String. The resolved locale (single-argument only)

Description

Aliasing is required when the lookup algorithm would give the wrong answer. For example, the locale ID for Taiwan is "zh-Hant-TW" meaning Chinese, written in Han traditional script as used in Taiwan. If we were to lookup "zh-TW" (Chinese as used in Taiwan), the lookup algorithm would resolve "zh" which is mainland Chinese. If, however, we record "zh-TW" as an alias for "zh-Hant-TW", the lookup for "zh-TW" gives the correct answer.

Usage
// Set an alias
UsefulJS.Locale.alias("zh-Hant-TW", "zh-TW");
// Resolve an alias
var resolved = UsefulJS.Locale.alias("zh-TW");  // zh-Hant-TW

lookup

Obtains best match for the requested locales from the supported locales.

Syntax
UsefulJS.Locale.lookup(locales)
Parameters

Returns: Array. Two items, the best match locale and any unicode extension requested for that locale.

Description

For ease of processing the selected code is split into the BCP 47 part and any unicode extension requested. The algorithm returns the first "acceptable" result, falling back to the default locale if no acceptable results can be obtained. Unassisted, the algorithm may not select the best match, however. For example, if the input is ["en-MY", "en-GB", "en-US"], the returned locale will be "en", since "en-MY" is not a supported locale. However, for a Malaysian audience, "en-GB" would produce better output. The solution is to alias "en-GB" to "en-MY".

Usage
UsefulJS.Locale.lookup(["ja-JP-u-nu-fullwidth", "zh-Hant"]); // ["ja", "u-nu-fullwidth"]
UsefulJS.Locale.alias("en-GB", "en-MY");
UsefulJS.Locale.lookup(["en-MY", "en-GB", "en"]);            // ["en-GB", ""]

options

Gets the locale options for the named locale.

Syntax
UsefulJS.Locale.options(loc)
Parameters

Returns: Object. The resolved locale options

Description

Although the locale Objects are properties of UsefulJS.Locale accessing them directly is unlikely to return the right thing because of the inheritance system which means that a whole bunch of properties are likely to be missing. Getting the Objects through the options method both resolves the input locale and the inherited properties. This method is primarily designed to be called to do the initial property resolution for the dateOptions and numericOptions methods so the returned value is not 100% useful.

dateOptions

Gets the fully resolved locale options required for date formatting.

Syntax
UsefulJS.Locale.dateOptions(loc[, fmtOptions])
Parameters

Returns: Object. The resolved locale options

Description

Unlike the options method, this call does return an Object with everything resolved that needs to be resolved, taking into account the requested numbering and calendar.

numericOptions

Gets the fully resolved locale options required for number formatting.

Syntax
UsefulJS.Locale.numericOptions(loc[, fmtOptions])
Parameters

Returns: Object. The resolved locale options

Description

Unlike the options method, this call does return an Object with everything resolved that needs to be resolved, taking into account the requested numbering.

supportedLocalesOf

Returns items from an input array that are supported in the sense that they do not force a fallback to the current locale.

Syntax
UsefulJS.Locale.supportedLocalesOf(locales)
Parameters

Returns: Array. Filtered items from the input array.

getSupported

Returns the list of locales that are actually supported.

Syntax
UsefulJS.Locale.getSupported()

Returns: Array. Directly supported locale codes.

numberSystems

Returns the supported numbering systems.

Syntax
UsefulJS.Locale.numberSystems()

Returns: Array. Supported numbering system names.

Description

These values go into the -nu- part of the unicode extension.

calendars

Returns the supported calendars.

Syntax
UsefulJS.Locale.calendars()

Returns: Array. Supported calendar names.

Description

These values go into the -ca- part of the unicode extension.