Lesson 68 of 80
The browser already knows how every locale writes numbers, currency, dates, and '3 days ago' — Intl is the built-in you reach for before writing a single formatting regex.
12 min read
Every option explains itself — why the right one is right, and why each wrong one is wrong. Miss one and it comes back later on a spaced-repetition schedule.
This topic is about judgment and practical tradeoffs more than a single right answer — a mock interview is the better way to test yourself on it.
Be interviewed on this →Hints without spoilers, and a plain explanation of why a wrong answer was wrong — answered only from this lesson. Free account, no card.
Sign up freeWhat interviewers actually ask about this, and what a strong answer has to cover.
A strong answer covers
Likely follow-ups
Formatting a number or date "correctly" isn't one fixed rule — it depends entirely on locale. 1234.5 is 1,234.5 in the US, 1.234,5 in Germany, and 1 234,5 in France. A price is $1,234.50 in the US and 1 234,50 € in France, with the currency symbol on the opposite side. Hand-rolling this with string splitting and manual symbol placement is exactly the kind of thing that looks fine in a demo and breaks the moment a real user in another country opens the app.
Intl is a built-in JavaScript object that already knows these rules for essentially every locale, and exposes them through a handful of formatter constructors: Intl.NumberFormat, Intl.DateTimeFormat, and Intl.RelativeTimeFormat cover the vast majority of what apps need.
const price = 1234.5;
new Intl.NumberFormat("en-US", { style: "currency", currency: "USD" }).format(price);
// "$1,234.50"
new Intl.NumberFormat("de-DE", { style: "currency", currency: "EUR" }).format(price);
// "1.234,50 €"
new Intl.NumberFormat("en-US", { style: "percent" }).format(0.256);
// "26%"
const date = new Date("2026-03-15T14:30:00Z");
new Intl.DateTimeFormat("en-US", { dateStyle: "long" }).format(date);
// "March 15, 2026"
new Intl.DateTimeFormat("ja-JP", { dateStyle: "long" }).format(date);
// "2026年3月15日"
const rtf = new Intl.RelativeTimeFormat("en", { numeric: "auto" });
rtf.format(-3, "day"); // "3 days ago"
rtf.format(2, "hour"); // "in 2 hours"
Same input value, correct locale-specific output, with no manual symbol placement, comma insertion, or month-name lookup table anywhere. The formatter takes the locale as its first argument and an options object describing what kind of value it is — currency, percent, a date style — and does the actual formatting work internally.
undefined uses the user's own browser/OS setting. new Intl.NumberFormat(undefined, {...}) automatically formats using whatever locale the visitor's environment reports — often exactly what you want for a global audience without detecting it yourself.style: "currency" requires a currency code, but doesn't validate it's the "right" currency for that locale. You can format EUR with an en-US locale (€1,234.50) — the locale controls formatting conventions, the currency code controls the symbol and rounding rules, and they're independent.Intl.RelativeTimeFormat doesn't compute the time difference for you. You still have to calculate "3 days ago" as the number -3 and unit "day" yourself; the formatter only turns that pair into locale-correct wording.The date-handling lesson in this track covers why raw Date math for things like "format this for display" is the wrong tool — Intl.DateTimeFormat is the concrete built-in that replaces it. The broader idea, using a platform API instead of reimplementing locale rules yourself, is the same instinct that leads you to structuredClone over a hand-rolled deep clone, or Array.prototype.at over manual negative-index math.