JsWorld
Currency Formatting
1. Basic currency formatting
To format currency amounts in a particular locale you first need to load two JavaScript files:
- The
JsWorld.min.js
file containing the library classes. - The data file describing the locale properties. The JS
World library comes with ready definitions for over 450
locales, put into individual files in the
locales/js/
directory.
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:
- German/Germany (de_DE)
- Hindi/India (hi_IN)
- Portuguese/Brazil (pt_BR)
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:
- "^" suppress grouping
- "!" suppress the currency symbol
- "~" suppress both the currency symbol and the sign (positive or negative)
- "i" force international sign (ISO-4217 code) formatting
- ".n" specify decimal precision n
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.
getCurrencySymbol()
returns the currency symbol used in formattingcurrencySymbolPrecedes(intFlag)
gets the position of the currency symbol relative to the amountgetDecimalPoint()
returns the decimal delimiter charactergetFractionalDigits(intFlag)
returns the number of currency fractional digits
Here is an example how these methods could be used.
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:
- Invalid or missing locale property
- Invalid amount to format
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.