💰 Configure EcmaScript's Intl.NumberFormat with a string pattern
Instead of using something like this:
const options = { style: 'currency', currencyDisplay: 'symbol', currency: 'USD' };
const numberStr = new Intl.NumberFormat( 'en-US', options ).format( 123456 );
Use formatNumber
:
const numberStr = formatNumber( 123456, 'en-US', '$' ); // Guesses the currency code
✨The function formatNumber
uses Intl.NumberFormat
internally and guesses the currency code (ISO 4247) from the country code (ISO 3166-1 alpha-2).
npm i intl-number-helper
Notes:
- It does not polyfill
Intl.NumberFormat
(you can use your own polyfill if you need it). - Use it in the browser, NodeJS or DenoJS, with JavaScript 5+ and TypeScript.
- Unit-tested.
- Semantic Versioning.
Some polyfills for Intl.NumberFormat
:
- @formatjs/intl-numberformat - Browsers and NodeJS (recommended)
- Intl.js - Browsers and NodeJS
Although NodeJS offers support to
Intl.NumberFormat
from version10
, a polyfill like formatjs' is recommended, since it is more complete and correct.
ESM, NodeJS
import { formatNumber } from 'intl-number-helper';
// US$123,456.00
console.log( formatNumber( 123456, 'en-US', '$' ) );
// R$ 123.456,00
console.log( formatNumber( 123456, 'pt-BR', '$7.2' ) );
// 123,456.00 American dollars
console.log( formatNumber( 123456, 'en-US', 'n' ) );
// 123,456.00
console.log( formatNumber( 123456, 'en-US', 'd.2' ) );
// 123,456
console.log( formatNumber( 123456, 'en-US', 'd' ) );
// 123456
console.log( formatNumber( 123456, 'en-US', 'd#' ) );
// 75%
console.log( formatNumber( 0.75, 'en-US', '%' ) );
// 100 kilometers per hour
console.log( formatNumber( 100, 'en-US', 'u',
{ unit: 'kilometer-per-hour', unitDisplay: 'long' } ) );
Browser
<script crossorigin src="https://unpkg.com/intl-number-helper" ></script>
<script>
console.log( intlNumberHelper.formatNumber( 123456, 'en-US', 'd' ) ); // 123,456
</script>
DenoJS
// Alternatively, use an import map and include it like NodeJS
import { formatNumber } from "https://unpkg.com/intl-number-helper/index.esm.js";
console.log( formatNumber( 123456, 'en-US', 'd' ) ); // 123,456
Pattern is symbol grouping sign integer-digits fraction-range significant-range
, in this order.
Every part is optional.
Pattern example | Generated object |
---|---|
'd' |
{ style: 'decimal' } |
'%' |
{ style: 'percent' } |
'u' |
{ style: 'unit' } |
'$' |
{ style: 'currency', currencyDisplay: 'symbol' } |
'w' |
{ style: 'currency', currencyDisplay: 'narrowSymbol' } |
'n' |
{ style: 'currency', currencyDisplay: 'name' } |
'o' |
{ style: 'currency', currencyDisplay: 'code' } |
'a' |
{ style: 'currency', currencySign: 'accounting' } |
'E' |
{ notation: 'scientific' } |
'e' |
{ notation: 'engineering' } |
'c' |
{ notation: 'compact' } |
'l' |
{ notation: 'compact', compactDisplay: 'long' } |
's' |
{ notation: 'compact', compactDisplay: 'short' } |
Pattern example | Generated object |
---|---|
'' |
{} , which is the same as { useGrouping: true } (default value) |
'#' |
{ useGrouping: false } |
Pattern example | Generated object |
---|---|
'' (empty) |
{} , which is the same as { signDisplay: 'auto' } (default value) |
'+' |
{ signDisplay: 'exceptZero' } |
'!' |
{ signDisplay: 'never' } |
'@' |
{ signDisplay: 'always' } |
A number between 0
and 21
(inclusive).
Pattern example | Generated object |
---|---|
'7' |
{ minimumIntegerDigits: 7 } |
- It establishes the minimum and the maximum digits for the fraction part.
- It must be preceded by
.
and use-
to separate the values (numbers). - The minimum part is always informed.
- Every number must be between
1
and20
(inclusive).
Pattern example | Generated object |
---|---|
'.1' |
{ minimumFractionDigits: 1 } |
'.1-2' |
{ minimumFractionDigits: 1, maximumFractionDigits: 2 } |
'#.1-2' |
{ useGrouping: false, minimumFractionDigits: 1, maximumFractionDigits: 2 } |
- Same as
fraction-range
, but preceded by;
Pattern example | Generated object |
---|---|
';1' |
{ minimumSignificantDigits: 1 } |
';1-2' |
{ minimumSignificantDigits: 1, maximumSignificantDigits: 2 } |
'#;1-2' |
{ useGrouping: false, minimumSignificantDigits: 1, maximumSignificantDigits: 2 } |
Putting some patterns together
Pattern example | Generated object |
---|---|
'$7.2-2' |
{ style: 'currency', currencyDisplay: 'symbol', minimumIntegerDigits: 7, minimumFractionDigits: 2, maximumFractionDigits: 2 } |
'$7.2-2;2' |
{ style: 'currency', currencyDisplay: 'symbol', minimumIntegerDigits: 7, minimumFractionDigits: 2, maximumFractionDigits: 2, minimumSignificantDigits: 2 } |
'$+7.2-2;1-2' |
{ style: 'currency', currencyDisplay: 'symbol', signDisplay: 'exceptZero', minimumIntegerDigits: 7, maximumFractionDigits: 2, minimumSignificantDigits: 1, maximumSignificantDigits: 2 } |
/**
* Formats a number.
*
* @param value Value to be formatted.
* @param locale Locale. When `pattern` uses currency, it guesses the currency from the country code.
* @param pattern Pattern. Optional. It generates an empty options object by default.
* @param additionalOptions Options to be added to those generated from the pattern. Optional. Useful for units.
*
* @throws Error When
*/
function formatNumber(
value: number,
locale: string,
pattern?: string,
additionalOptions?: Intl.NumberFormatOptions
): string;
/**
* Creates a `Intl.NumberFormatOptions` object from a given pattern.
* @param pattern Pattern. Optional. It generates an empty options object by default.
* @param additionalOptions Options to be added to those generated from the pattern. Optional. Useful for units.
*
* @example
* const options = makeOptions( '$', { currency: 'USD' } );
* const numberStr = new Intl.NumberFormat( 'en-US', options ).format( 123456 );
*
*/
function makeOptions(
pattern?: string,
additionalOptions?: Intl.NumberFormatOptions
): Intl.NumberFormatOptions;
/**
* Indicates if the given pattern is correct.
*
* @param pattern Pattern
*/
function isPatternCorrect( pattern: string ): boolean;
- Offering support to more patterns.
Suggestions? Please open an Issue. 👍