Skip to content

Intermediate · Modules, errors, JSON and dates · topic 30 of 61 · 20 min

Formatting numbers, money and text with Intl

Explanation

The built-in Intl object formats numbers, currencies, dates, plurals and relative times for any language and region. With the en-IN locale, numbers use the lakh and crore grouping (12,34,567) and INR shows as ₹. Intl.Collator sorts names the way people expect, including accented letters.

Why not format by hand?

Formatting looks easy until you meet real users. India groups digits as 12,34,567 (lakhs and crores) while the US writes 1,234,567. Germany writes 1.234.567,50. Some languages have several plural forms. Writing all of this yourself is slow and full of bugs. The Intl object, built into every modern browser and Node.js, already knows these rules.

Locales

A locale is a code for a language and region: 'en-IN' (English, India), 'hi-IN' (Hindi, India), 'en-US', 'de-DE'. Intl uses it to choose the right format.

Intl.NumberFormat

javascript
const inr = new Intl.NumberFormat('en-IN', { style: 'currency', currency: 'INR' });
console.log(inr.format(1234567.5));     // '₹12,34,567.50'
console.log(new Intl.NumberFormat('en-IN').format(123456));  // '1,23,456'
console.log(new Intl.NumberFormat('en-US').format(123456));  // '123,456'
console.log(new Intl.NumberFormat('en-IN', { notation: 'compact' }).format(1500000)); // '15L'
console.log(new Intl.NumberFormat('en-IN', { style: 'percent' }).format(0.18));      // '18%'

Create the formatter once and reuse it; creating a new NumberFormat for every row of a big table is slow.

Plurals and relative times

javascript
const rules = new Intl.PluralRules('en');
const word = (n) => (rules.select(n) === 'one' ? 'ticket' : 'tickets');
console.log(`1 ${word(1)}, 3 ${word(3)}`);   // 1 ticket, 3 tickets

const rtf = new Intl.RelativeTimeFormat('en', { numeric: 'auto' });
console.log(rtf.format(-1, 'day'));    // 'yesterday'
console.log(rtf.format(3, 'hour'));    // 'in 3 hours'

Sorting text properly: Intl.Collator

The default sort compares character codes, so capital letters come before small letters and accented letters go to the end. A collator compares the way people expect in a language.

javascript
const names = ['Zoya', 'arjun', 'Émile'];
console.log([...names].sort());                                   // ['Zoya', 'arjun', 'Émile']
console.log([...names].sort(new Intl.Collator('en').compare));    // ['arjun', 'Émile', 'Zoya']
console.log('a'.localeCompare('B', 'en'));                        // -1 (a comes before B)

Quick helpers: toLocaleString

Numbers and Dates have toLocaleString(locale, options), a shortcut that uses Intl underneath: (1234567).toLocaleString('en-IN') gives '12,34,567'. Fine for one-off use; reuse a formatter object in loops.

Dates in Indian languages

The same Intl.DateTimeFormat you met in the last topic works for Indian languages too. With the locale 'hi-IN' the month names come out in Hindi, and with 'ta-IN' in Tamil. You do not need a translation table for month or weekday names; the browser or Node.js already has them. Pass the user's preferred locale (for example from a settings page) into one helper function and use it everywhere, so a single change switches the whole app.

javascript
const when = new Date(Date.UTC(2026, 7, 15, 4, 30));
const opts = { timeZone: 'Asia/Kolkata', day: 'numeric', month: 'long', year: 'numeric' };
console.log(new Intl.DateTimeFormat('en-IN', opts).format(when)); // '15 August 2026'
console.log(new Intl.DateTimeFormat('hi-IN', opts).format(when)); // the same date with the month name in Hindi
Careful: Formatted strings are for showing to people only. Never store '₹1,499.00' in a database or do maths on it. Keep the raw number (preferably in paise) and format at the last moment.
Think of it like this: Intl is like a multilingual receptionist: you hand over the same number or date, say which visitor (locale) it is for, and the receptionist writes it the way that visitor is used to reading it.
Tip: Exact output can differ slightly between browsers and versions (spaces, symbols). In automated tests, avoid comparing long formatted strings exactly unless you control the environment.

Need help?

Stuck on a word or an idea? Search this course, or every course, and jump straight to the explanation or a worked question.

Try:

Watch the lesson

Formatting numbers, money and text with Intl · 1/6

Intl

In this lesson you will format numbers, money and text correctly for any region with Intl.

Prefer a video by a teacher? Find free videos on “javascript Intl NumberFormat currency INR locale formatting” on YouTube ↗

In real life: A mutual fund dashboard

An investment app shows portfolio values to Indian users in lakhs and crores and to NRI users abroad in their own format. The same number goes through a formatter chosen by the user's locale setting.

javascript
const value = 2575000;
const show = (locale, currency) =>
  new Intl.NumberFormat(locale, { style: 'currency', currency, maximumFractionDigits: 0 }).format(value);
console.log(show('en-IN', 'INR')); // ₹25,75,000
console.log(show('en-US', 'INR')); // ₹2,575,000

Practice (0/3 done)

Task 1 · Code · Javascript

Write indianNumber(n) that returns n formatted with Indian digit grouping, using Intl.NumberFormat("en-IN"). indianNumber(1234567) returns "12,34,567".

Task 2 · Code · Javascript

Write sortNames(names) that returns a NEW array sorted alphabetically the way people expect, ignoring upper/lower case, using Intl.Collator("en").compare.

Task 3 · Code · Javascript

Write ticketsLabel(n) that returns "1 ticket" or "<n> tickets" using Intl.PluralRules("en").

Quick quiz

Question 1

1.What does new Intl.NumberFormat('en-IN').format(1500000) give?

Question 2

2.What is a locale?

Question 3

3.Where should "₹1,499.00" be used?

Question 4

4.Why use Intl.Collator to sort names?

Read more (free)

Open a question to see the answer and why. The first ones are this topic's own quiz, so try the quiz above before you peek.

What does new Intl.NumberFormat('en-IN').format(1500000) give?

Answer: 15,00,000

en-IN groups as lakhs: 15,00,000.

What is a locale?

Answer: A language and region code like en-IN

Locales tell Intl which language and regional rules to use.

Where should "₹1,499.00" be used?

Answer: Shown to the user

Formatted strings are for display only.

Why use Intl.Collator to sort names?

Answer: It sorts as people expect, handling case and accents

Default sort compares character codes, which puts all capitals first.

Which gives the last character of the string text?Related

Answer: text.at(-1)

at(-1) counts from the end. text[-1] is undefined, there is no last() method, and slice(0, 1) gives the first character.

From Strings in depth

Two Date objects for the same moment: a === b is…Related

Answer: false

=== compares object identity; compare getTime() values instead.

From Dates and times

One crore is equal to...Related

Answer: ten million

1 crore = 1,00,00,000 = 10,000,000 = ten million.

From Numbers: from one to one crore

What is the safest way to store ₹199.99 for calculations?Related

Answer: 19999 paise as a whole number

Whole numbers are exact, so store the smallest unit.

From Numbers and Math

Pass the quiz (60% or more) or mark this topic as done when you are ready.

Your progress is saved on this device only.

Next steps

  1. This is the last topic of “Modules, errors, JSON and dates”. The module exam comes next.
  2. Module 6 exam: Modules, errors, JSON and dates · 12 questions · 25 min, without help. 5 topics of this module still to finish first.
  3. Then the next module, Map, Set, iterators, generators and regular expressions. 61 topics left in the course before the final exam.

← Previous: Dates and times