According to the documentation on MDN,
The
Intl.NumberFormat
object is a constructor for objects that enable language-sensitive number formatting
And this means what in practice?
It simply means that with Intl.NumberFormat
, JavaScript can construct an object that will have the ability to style (or to be technically correct, format) numbers based on human languages. In other words, numbers can be styled in a more human-understandable format.
Instead of numbers being presented as bland as 1234
or 4561254
, numbers can be better presented as 1,234
or $4,561.254
. You get the gist? Good!
How does this work? Well, the syntax is simple.
const formatterObject = new Intl.NumberFormat([locales[, options]]);
What the syntax above means is this:
-
formatterObject
is the object constructed (created) byIntl.NumberFormat
.formatterObject
holds methods that can be used to format numbers, -
locales
represents the code for human language that we want to format the number in. And why is this important?
Different languages have different ways of displaying numbers. A number like 123456
will be displayed in Spanish as 123.456
, in English as 123,456
and in the Indian numerical system as 1,23,456
. locales
is a code in the form of a string that informs formatterObject
of which language to use when formatting.
You can find a list of the locales under subtag
here. Examples are 'hi'
for Hindi, 'de-AT'
for German (de) used in Austria (AT) and 'en-IN'
for English (en) used in India (IN). Number system codes such as "arab"
, "arabext"
and "latn"
-
options
refers to additional configurations that can be used to configure howformatterObject
styles numbers.options
is an object.
Don't be dismayed by the square braces []
in the syntax. They are simply saying Hey developer! Whatever is within me is optional. You can decide to exclude them when writing the syntax and the default configurations will be used.
Using the number 1234567890.1234
as an example, lets convert our knowledge into code.
const num = 1234567890.1234;
// setup formatters
const hindiNumberFormatter = new Intl.NumberFormat("en-IN");
const britishNumberFormatter = new Intl.NumberFormat("en-GB");
const spanishNumberFormatter = new Intl.NumberFormat("es-ES");
// use formatters
console.log(hindiNumberFormatter.format(num)); // 1,23,45,67,890.123
console.log(britishNumberFormatter.format(num)); // 1,234,567,890.123
console.log(spanishNumberFormatter.format(num)); // 1.234.567.890,123
What happened?
We created three types of number formatters with Intl.NumberFormat: hindiNumberFormatter
, britishNumberFormatter
and spanishNumberFormatter
. Each formatter was created with a locale configuration that sets the formatting language of the formatter.
Next, we use the format
method on the formatters to style the number num
and display the result on the console.
And why is the last 4
not displayed in the formatted result? Did you notice that? Okay. Lets try another example:
const num = 1234567890.1234;
const formatConfig = {
style: "currency",
currency: "USD", // CNY for Chinese Yen, EUR for Euro
minimumFractionDigits: 2,
currencyDisplay: "symbol",
};
// setup formatters
const britishNumberFormatter = new Intl.NumberFormat("en-GB", formatConfig);
const spanishNumberFormatter = new Intl.NumberFormat("es-ES", formatConfig);
// use formatters
console.log(britishNumberFormatter.format(num)); // US$1,234,567,890.12
console.log(spanishNumberFormatter.format(num)); // 1.234.567.890,12 US$
😃 Interesting! What happened here again?
Remember the second parameter in the Intl.NumberFormat
? The options
object? It is used to setup additional configurations for how formatterObject
would format numbers passed to it. With properties such as style
(possible values are "decimal"
for plain number formatting, "currency"
for currency formatting, and "percent"
for percent formatting; the default is "decimal"
), currency
, maximumSignificantDigits
(values are integers that determine how many significant digits the number to be formatted should have), minimumFractionDigits
(having the value of an integer that determines the how many decimal digits the formatted number should have).
As in the second example, did you notice that the last two decimal digits (3 and 4) are not in the formatted number? That's because the minimum number of decimal digits we set in the options
parameter as formatConfig
, (minimumFractionDigits
) was 2. See?
Apart from the format
method on the formatterObject
, there is also another method, the formatToParts
method which returns an array of objects representing the number string in parts that can be used for custom locale-aware formatting.
For example:
const num = 1234.5678;
const britishNumberFormatter = new Intl.NumberFormat("en-GB");
const spanishNumberFormatter = new Intl.NumberFormat("es-ES");
console.log(britishNumberFormatter.formatToParts(num));
/*
[
0: Object { type: "integer", value: "1" }
1: Object { type: "group", value: "," }
2: Object { type: "integer", value: "234" }
3: Object { type: "decimal", value: "." }
4: Object { type: "fraction", value: "568" }
]
*/
console.log(spanishNumberFormatter.formatToParts(num)); // 1.234.567.890,123
/*
[
0: Object { type: "integer", value: "1234" }
1: Object { type: "decimal", value: "," }
2: Object { type: "fraction", value: "568" }
] */
formatToParts
splits the formatted number into parts, and determines the digit type (integer or fraction) and the symbol type (group or decimal).
Other configuration options for options
can be found in the MDN documentation for Intl.NumberFormat
.
Experimental Features with Intl.NumberFormat
Some interesting features are being added to Intl.NumberFormat
such as the ability to format with units (l, mi/h, mph
), using exponential notations (E8, E-2) and BigInt support. These features cannot be used in production code yet. At the moment, only Chrome 77+ provides support for these features.
const num = 1235.12;
const formatConfig = {
style: "units",
unit: "meter-per-second",
};
// setup formatters
const britishNumberFormatter = new Intl.NumberFormat("en", formatConfig); // 1,235.12 m/s
It's a pity but at the time of this writing, Intl.NumberFormat
does not exist in Node.js.
All the best of all the best as you use Intl.NumberFormat
to display numbers in styles customised for human languages and human-readable formats.
Cheers!
Top comments (14)
I needed to format a number and I just discovered that in spanish if the number 12345.67 it will print 12.345,67 cool but if the number is 1234.56 it will print 1234,56 not cool, it should be: 1.234,56, still looking a way to do it without regex
Hello Tony. I am replying late, I guess, but I should. haha
What language locale are you converting from, and to?
No problem, I read this: stackoverflow.com/questions/589913..., so it's an expected behaviour
Thanks for sharing.
I'm curious though. How did you find the configuration options? I spent a while searching for them before coming across your post. It doesn't seem to be on the Documentation page. Would appreciate if you could share. Thanks.
What! Boss! You read my post! Arrrgggh! You made my daaaaaay.. or night..
You're one of the Nigerian devs I look up to. Feels good to see your comment here.
Now for the answer to your question.. Drum roll..
developer.mozilla.org/en-US/docs/W...
I got there by clicking the constructor link in the compatibility table
Thanks again. This means much to me.. That you read and commented on my article
Thank you for the kind words... Keep up the good work and thanks for sharing.
u are right the doc page on MDN has nothing on the parameter for the constructor.
Apologies.
Here you are => developer.mozilla.org/en-US/docs/W...
Thank you for pointing me to this. I read a lot of MDN documentation but yet I did not stumbled over this one. Powerful tool indeed.
Whoa! Thanks! This feedback really means a lot! Blessings!
parameter to be passed into the constructor was not explained in MDN doc or maybe I was looking at the wrong place in the doc.
is there a way to convert numbers like 70,678 to a format like this 70.6k ?
good day, I have the format in an input, how could I reverse it or put it back to its original format, thanks