Intl
The Intl object is the namespace for the ECMAScript Internationalization API. It provides language-sensitive formatting and comparison across numbers, dates, strings, and lists. You access each capability through constructors attached to Intl — Intl.NumberFormat, Intl.DateTimeFormat, Intl.Collator, and so on.
A critical point: Intl is not a constructor. Calling new Intl() throws a TypeError. Each capability lives as a property of the Intl object.
Accessing Intl Constructors
All Intl APIs follow the same pattern — you call the constructor as a property of Intl, optionally passing a locale string and configuration options.
// These work
const nf = new Intl.NumberFormat("en-US");
const dtf = new Intl.DateTimeFormat("en-GB");
// This throws: TypeError: Intl is not a constructor
// const bad = new Intl();
NumberFormat
Intl.NumberFormat formats numbers according to locale conventions — decimal separators, grouping, currency symbols, and more.
Basic Usage
const nf = new Intl.NumberFormat("en-US");
nf.format(1234567.89)
// "1,234,567.89"
const nfDe = new Intl.NumberFormat("de-DE");
nfDe.format(1234567.89)
// "1.234.567,89"
Currency Formatting
Pass style: "currency" and a valid ISO 4217 currency code:
const cf = new Intl.NumberFormat("en-US", {
style: "currency",
currency: "USD"
});
cf.format(1234.56)
// "$1,234.56"
// Japanese Yen — no decimals by default
const jpy = new Intl.NumberFormat("ja-JP", {
style: "currency",
currency: "JPY"
});
jpy.format(1234.56)
// "¥1,235"
Omitting the currency option when using style: "currency" silently falls back to decimal formatting — no error is thrown. Always specify the currency code explicitly.
Compact Notation
const compact = new Intl.NumberFormat("en-US", {
notation: "compact",
compactDisplay: "short"
});
compact.format(12345678)
// "12M"
Significant Digits
const sig = new Intl.NumberFormat("en-US", {
maximumSignificantDigits: 3
});
sig.format(12345.67)
// "12,300"
DateTimeFormat
Intl.DateTimeFormat formats dates and times with locale-aware patterns.
Date and Time Styles
const fullDate = new Intl.DateTimeFormat("en-US", {
dateStyle: "long"
});
fullDate.format(new Date())
// "May 14, 2026"
const shortTime = new Intl.DateTimeFormat("en-US", {
timeStyle: "short"
});
shortTime.format(new Date())
// "5:30 PM"
Individual Components
const parts = new Intl.DateTimeFormat("en-US", {
weekday: "long",
year: "numeric",
month: "long",
day: "numeric"
});
parts.format(new Date())
// "Thursday, May 14, 2026"
Time Zones
const nyTime = new Intl.DateTimeFormat("en-US", {
timeStyle: "short",
timeZone: "America/New_York"
});
nyTime.format(new Date())
// "5:30 PM EDT"
Use IANA time zone names like "America/New_York", not abbreviations like "EST". Invalid time zone strings may be silently ignored.
Collator
Intl.Collator provides locale-aware string comparison. The .compare(a, b) method returns -1, 0, or 1.
const collator = new Intl.Collator("en-US");
collator.compare("a", "b") // -1
collator.compare("b", "a") // 1
collator.compare("a", "a") // 0
Sorting with Collator
const items = ["banana", "cherry", "apple"];
// Locale-aware sort
items.sort(new Intl.Collator("de-DE").compare)
// ["apple", "banana", "cherry"] — de-DE handles umlauts
Numeric Sorting
const files = ["file1", "file10", "file2"];
files.sort(new Intl.Collator("en-US", { numeric: true }).compare)
// ["file1", "file2", "file10"]
Without numeric: true, "file10" comes before "file2" because comparison stops at the first differing character.
Sensitivity
const caseInsensitive = new Intl.Collator("en-US", {
sensitivity: "base"
});
caseInsensitive.compare("A", "a") // 0 — treated as equal
PluralRules
Intl.PluralRules maps numbers to plural categories for localized grammar.
const pr = new Intl.PluralRules("en-US");
pr.select(0) // "other"
pr.select(1) // "one"
pr.select(2) // "other"
Ordinal Suffixes
const ordinal = new Intl.PluralRules("en-US", { type: "ordinal" });
ordinal.select(1) // "one" → "1st"
ordinal.select(2) // "two" → "2nd"
ordinal.select(3) // "few" → "3rd"
ordinal.select(4) // "other" → "4th"
ordinal.select(21) // "one" → "21st"
Arabic has more granular categories:
const ar = new Intl.PluralRules("ar");
ar.select(0) // "zero"
ar.select(1) // "one"
ar.select(2) // "two"
ar.select(6) // "few"
ar.select(100) // "other"
RelativeTimeFormat
Intl.RelativeTimeFormat formats relative time spans like “5 seconds ago” or “in 2 weeks”.
const rtf = new Intl.RelativeTimeFormat("en-US");
rtf.format(5, "second") // "in 5 seconds"
rtf.format(-5, "second") // "5 seconds ago"
rtf.format(1, "day") // "in 1 day"
rtf.format(-1, "day") // "1 day ago"
The numeric Option
By default (numeric: "always"), both past and future times use “in X” / “X ago”. Switch to "auto" to use natural phrases for positive future values:
const autoRtf = new Intl.RelativeTimeFormat("en-US", { numeric: "auto" });
autoRtf.format(1, "day") // "tomorrow" — not "in 1 day"
autoRtf.format(-1, "day") // "yesterday"
Narrow Style
const narrow = new Intl.RelativeTimeFormat("en-US", { style: "narrow" });
narrow.format(3, "minute")
// "3 min. ago"
ListFormat
Intl.ListFormat formats arrays into localized, grammatically correct lists.
const lf = new Intl.ListFormat("en-US");
lf.format(["A", "B", "C"])
// "A, B, and C"
// Spanish uses different conjunction
const esLf = new Intl.ListFormat("es");
esLf.format(["A", "B", "C"])
// "A, B y C"
List Types
// Disjunction (or)
lf.format(["A", "B"], { type: "disjunction" })
// "A or B"
// Unit (measurements)
const unitLf = new Intl.ListFormat("en-US", { type: "unit" });
unitLf.format(["5 lbs", "3 oz"])
// "5 lbs and 3 oz"
DisplayNames
Intl.DisplayNames provides consistent translations of language, region, and script codes.
const dn = new Intl.DisplayNames("en-US", { type: "language" });
dn.of("en") // "English"
dn.of("ja") // "Japanese"
dn.of("zh-Hant") // "Chinese (Traditional)"
// Region names
const regionDn = new Intl.DisplayNames("en-US", { type: "region" });
regionDn.of("US") // "United States"
regionDn.of("GB") // "United Kingdom"
Locale
Intl.Locale represents a Unicode locale identifier. It lets you inspect and manipulate locale tags programmatically.
const loc = new Intl.Locale("en-US");
loc.language // "en"
loc.region // "US"
loc.baseName // "en-US"
loc.toString() // "en-US"
Modifying a Locale
Pass options as a second argument to derive a new locale:
const loc2 = new Intl.Locale("de-DE", {
calendar: "islamic",
hourCycle: "h24"
});
loc2.calendar // "islamic"
loc2.hourCycle // "h24"
loc2.toString() // "de-DE-u-ca-islamic-hc-h24"
DurationFormat
Intl.DurationFormat formats duration objects into human-readable strings. Browser support is limited — check compatibility tables before using in production.
const df = new Intl.DurationFormat("en-US", { style: "long" });
df.format({
years: 1,
months: 2,
days: 3,
hours: 4,
minutes: 5,
seconds: 6
})
// "1 year, 2 months, 3 days, 4 hours, 5 minutes, and 6 seconds"
Quick Reference
| Constructor | Purpose | Key Method |
|---|---|---|
Intl.NumberFormat | Number and currency formatting | .format(n) |
Intl.DateTimeFormat | Date and time formatting | .format(date) |
Intl.Collator | String comparison and sorting | .compare(a, b) |
Intl.PluralRules | Plural category selection | .select(n) |
Intl.RelativeTimeFormat | Relative time strings | .format(v, unit) |
Intl.ListFormat | Localized list formatting | .format(array) |
Intl.DisplayNames | Language/region/script names | .of(code) |
Intl.Locale | Locale identifier object | .toString() |
Intl.DurationFormat | Duration formatting | .format(duration) |
Common Mistakes
new Intl()throws. Access constructors as properties:Intl.NumberFormat, notnew Intl().- Missing
currencywithstyle: "currency"silently falls back to decimal — always pass the ISO code. - Wrong time zone format — use IANA names like
"Asia/Tokyo", not"JST". numericmeans different things in different constructors. InCollator,numeric: trueenables natural number sorting. InRelativeTimeFormat,numeric: "auto"omits “in” for positive future values.
See Also
- /reference/built-in-objects/date/ — Date object for creating and manipulating dates
- /reference/string-methods/locale-compare/ — String locale-aware comparison
- /guides/javascript-intl-api/ — Deep dive into the Intl API ecosystem