JsWorld

Currency Formatting

1. Basic currency formatting

To format currency amounts in a particular locale you first need to load two JavaScript files:

An example how to do this for the en_GB (British English/UK) locale:

<script type="text/javascript" src="JsWorld.min.js"></script>
<script type="text/javascript" src="locales/js/en_GB.js"></script>

The first script tag loads the library logic, including the jsworld.Locale and jsworld.MonetaryFormatter classes required to format currency amounts. The second script tag loads a JavaScript object called POSIX_LC.en_GB containing the locale properties.

The next step is to configure a monetary formatter using the locale definition:

// Create locale object from the en_GB data
var lc = new jsworld.Locale(POSIX_LC.en_GB);

// Now configure a monetary formatter for the en_GB locale
var mf = new jsworld.MonetaryFormatter(lc);

Now you've got a ready formatter set up for the en_GB locale and its default currency, the British pound. Use its format() method to localise a monetary amount. The value can be passed as a number or as a string that parses to a number:

// Print a few pound amounts
document.writeln(mf.format(0));
document.writeln(mf.format(45.95));
document.writeln(mf.format(25000));
document.writeln(mf.format(7500000));

// You can also pass a string value
document.writeln(mf.format("-100000.00"));

The above statements should produce the following output. Notice how the amounts were formatted with the proper currency sign, decimal places and thousands separation:

        ₤0.00
       ₤45.95
   ₤25,000.00
₤7,500,000.00

 -₤100,000.00

Let's now do another example and format the amount 250000 in the following locales:

If you're not sure about the code for a particular locale you can look it up in the table of the JsWorld supported locales.

Assuming that the necessary locale definitions have been previously loaded (the namespacing is done in such a way that you can load as many as you wish, without causing clashes), you can proceed like this:

var amount = 250000;

// For de_DE locale
mf = new jsworld.MonetaryFormatter(new jsworld.Locale(POSIX_LC.de_DE));
document.writeln(mf.format(amount));

// For hi_IN locale
mf = new jsworld.MonetaryFormatter(new jsworld.Locale(POSIX_LC.hi_IN));
document.writeln(mf.format(amount));

// For pt_BR locale
mf = new jsworld.MonetaryFormatter(new jsworld.Locale(POSIX_LC.pt_BR));
document.writeln(mf.format(amount));

By looking at the specified locale definition the formatter determines the locale's default currency (Euro for Germany, Rupee for India, Real for Brazil) as well as the locale's conventions for displaying monetary quantities. It then proceeds to output the following:

 250.000,00 €
रु. 2,50,000.00
  R$250.000,00

Notice how the currency symbol position, the radix character and the digits grouping vary with each locale. If the rupee symbol isn't displayed properly, then your computer probably lacks a Hindi font. The JsWorld library ultimately depends on the user system to render the currency signs correctly on the screen.

2. Modifying the formatted output

The jsworld.MonetaryFormatter.format() method can also accept an optional second string argument to modify the output format:

Here is a demonstration how the various options can be applied. You can combine several at a time to obtain the formatting effect you require.

var amount = -999000;

// Create new formatter for the Japanese locale
mf = new jsworld.MonetaryFormatter(new jsworld.Locale(POSIX_LC.ja_JP));

document.writeln("default output             : " + mf.format(amount));

document.writeln("no grouping                : " + mf.format(amount, "^"));
document.writeln("no symbol                  : " + mf.format(amount, "!"));
document.writeln("no symbol and no sign      : " + mf.format(amount, "~"));
document.writeln("force international symbol : " + mf.format(amount, "i"));
document.writeln("force decimal precision 3  : " + mf.format(amount, ".3"));
document.writeln("options mix                : " + mf.format(amount, "^i.3"));

The resulting output (JPY is the ISO-4217 code for the Japanese Yen):

default output             :      -¥999,000

no grouping                :       -¥999000
no symbol                  :       -999,000
no symbol and no sign      :        999,000
force international symbol :    -JPY999,000
force decimal precision 3  :  -¥999,000.000
options mix                : -JPY999000.000

Keep in mind that the formatter will round the output amount if the specified decimal precision demands it.

mf = new jsworld.MonetaryFormatter(new jsworld.Locale(POSIX_LC.en_US));

// The output will be rounded to $0.01
mf.format(0.005);

// The output will be rounded to $0.001
mf.format(0.0005, ".3");

3. How to format non-local currencies

By now you're probably asking the question: How to format an amount in a currency that isn't the locale's default?

For such cases the jsworld.MonetaryFormatter constructor provides two additional optional arguments (see the API docs):

jsworld.MonetaryFormatter(locale, currencyCode, altIntSymbol);

Their usage is best illustrated with an example.

Suppose that your chosen locale is en_US (American English/US), which has the US Dollar as its national currency. You, however, wish to format Euro amounts. To do this you need to pass the Euro's international currency code "EUR" (see the ISO-4217 code standard) as a second argument to the constructor.

lc = new jsworld.Locale(POSIX_LC.en_US);
mf = new jsworld.MonetaryFormatter(lc, "EUR");

Now we've got an instance that is configured to format Euros instead of US Dollars, using the American conventions for displaying money. Let's now go ahead and print a few amounts.

document.writeln(mf.format(-100));
document.writeln(mf.format(100));
document.writeln(mf.format(100000));
document.writeln(mf.format(100000000));

The result:

-EUR100.00
 EUR100.00
 EUR100,000.00
 EUR100,000,000.00

But where is the Euro sign "€"?

The monetary formatter uses the international currency code when asked to format a currency that isn't native to the locale. It wisely does so, because the three-letter code, as defined by the ISO-4217 standard, is the least ambiguous way to designate a foreign currency. If you examine the world's currencies you'll see there are about a dozen sharing the "$" sign, while many use symbols which aren't globally recognised. Therefore, the standard ISO-4217 code remains the safest choice.

This behaviour can be overridden by passing the shorthand currency symbol as a third argument to the constructor. My advice is to do this only for currencies with unique and internationally recognised symbols. The Euro falls into this category, so we can do this:

// It is safer to use the UTF-8 escape sequence than pass the € sign directly
mf = new jsworld.MonetaryFormatter(lc, "EUR", "\u20ac");

Another way to specify the shorthand sign is to use the currency_symbol property from a locale that has the Euro as its national currency:

// Grab the Euro sign from the de_DE (Germany) locale
var germanLocale = new jsworld.Locale(POSIX_LC.de_DE);
mf = new jsworld.MonetaryFormatter(lc, "EUR", germanLocale.getCurrencySymbol());

Let's now format the same amounts again:

document.writeln(mf.format(-100));
document.writeln(mf.format(100));
document.writeln(mf.format(100000));
document.writeln(mf.format(100000000));

This time we got the Euro sign:

-€100.00
 €100.00
 €100,000.00
 €100,000,000.00

4. Helper methods

jsworld.MonetaryFormatter has four helper methods designed to help with tasks such as the HTML layout and styling of money input elements.

Here is an example how these methods could be used.

Helper methods usage

Imagine that you have to render an HTML form for monetary amounts consisting of two input boxes, one for the integer part and another for the fractional part. Here is a code snippet how you could determine the currency symbol, its position relative to the input boxes, the radix character and the size of the fractional digits box:

mf = new jsworld.MonetaryFormatter(new jsworld.Locale(POSIX_LC.en_US));

currencySymbol = mf.getCurrencySymbol();
// set the content of the currency symbol element
// ...

if (mf.currencySymbolPrecedes()) {
	// put the currency symbol in front
	// ...
}
else {
	// put the currency symbol at the back
	// ...
}

radixChar = mf.getDecimalPoint();
// set the decimal point char
// ...

numFracDigits = mf.getFractionalDigits();
// set the size of the fractional digits box
// ...

5. Exception handling

The JsWorld classes are programmed to raise an exception if something goes wrong. The two typical exception cases are:

You can check for such situations using a try-catch clause:

try {
	var lc = new jsworld.Locale(POSIX_LC.en_US);
	var mf = new jsworld.MonetaryFormatter(lc);
	mf.format("abc");
} catch (error) {
	document.write(error);
}

In the above example the format method is passed a string that doesn't parse to a number, so you'll get the following exception:

Error: Amount string not a number

6. The locale properties defining monetary formatting

The JsWorld library relies on the POSIX LC_MONETARY standard to describe the formatting of currency amounts in a particular locale. The standard defines a set of properties which are used to define the behaviour of the jsworld.MonetaryFormatter class. Here is a list of their names and meanings:

Property Description
int_curr_symbol the ISO-4217 code for the local currency
currency_symbol the local shorthand currency symbol
mon_decimal_point the decimal delimiter symbol
mon_thousands_sep the thousands delimiter symbol
mon_grouping the size of each group of digits to the left of the decimal delimiter
positive_sign the symbol for non-negative amounts
negative_sign the symbol for negative amounts
frac_digits the number of fractional digits of the local currency
int_frac_digits the number of fractional digits of the local currency (for ISO-4217 code formatting)
p_cs_precedes defines the shorthand symbol position for non-negative amounts
n_cs_precedes defines the shorthand symbol position for negative amounts
p_sep_by_space defines the separation of shorthand symbol, sign symbol and amount for non-negative amounts
n_sep_by_space defines the separation of shorthand symbol, sign symbol and amount for negative amounts
p_sign_posn defines the sign position for non-negative amounts
n_sign_posn defines the sign position for negative amounts
int_p_cs_precedes defines the shorthand symbol position for non-negative amounts (for ISO-4217 code formatting)
int_n_cs_precedes defines the shorthand symbol position for negative amounts (for ISO-4217 code formatting)
int_p_sep_by_space defines the separation of shorthand symbol, sign symbol and amount for non-negative amounts (for ISO-4217 code formatting)
int_n_sep_by_space defines the separation of shorthand symbol, sign symbol and amount for negative amounts (for ISO-4217 code formatting)
int_p_sign_posn defines the sign position for non-negative amounts (for ISO-4217 code formatting)
int_n_sign_posn defines the sign position for negative amounts (for ISO-4217 code formatting)

The original detailed LC_MONETARY specification is available in the corresponding POSIX document. Alternatively, you can check the JsWorld jsworld.Locale class docs for more info.

The ready locale definitions shipped with the JsWorld library should cover the needs of most users, so you won't have to delve into the internals of the LC_MONETARY spec. Still, some users may wish to create their own locale from scratch or modify an existing one.

Here is an example how to modify the en_US locale definition to use brackets instead of a minus sign when formatting negative amounts. This is done by loading the locale data and changing the applicable property. In this case this would be the n_sign_posn property, which should be set from 1 to 0.

<script type="text/javascript" src="JsWorld.min.js"></script>
<script type="text/javascript" src="locales/js/en_US.js"></script>

<script>
// Change property from 1 to 0 to turn brackets on
POSIX_LC.en_US.n_sign_posn = 0;

// Create new MonetaryFormatter with the modified definition
mf = new jsworld.MonetaryFormatter(new jsworld.Locale(POSIX_LC.en_US));

// Print a few negative amounts
document.writeln(mf.format(-2500));
document.writeln(mf.format(-5000));
document.writeln(mf.format(-7500));
</script>

Now we should see brackets in the output:

($2,500.00)
($5,000.00)
($7,500.00)

7. Examples

All examples presented in this manual can be found here.

8. API documentation

Auto-generated documentation for the MonetaryFormatter class is available here.