The Intl API: Formatting and Localization
Introduction
JavaScript’s built-in Intl API provides language-sensitive formatting and processing for dates, numbers, and text. Instead of manually formatting strings based on locale conventions, you can use the Intl namespace to handle the complexity.
The API is available in all modern browsers and Node.js without any external dependencies. It supports:
- Date and time formatting
- Number formatting (including currency and percentages)
- Relative time formatting
- String comparison and sorting
- Text segmentation
This guide walks through each API with practical examples you can use in your projects.
Date and Time Formatting with Intl.DateTimeFormat
The Intl.DateTimeFormat API formats dates according to locale conventions.
Basic Usage
const date = new Date("2026-03-15T14:30:00Z");
const usFormatter = new Intl.DateTimeFormat("en-US");
console.log(usFormatter.format(date));
// "3/15/2026"
const deFormatter = new Intl.DateTimeFormat("de-DE");
console.log(deFormatter.format(date));
// "15.3.2026"
Customizing the Output
The second argument is an options object that controls which parts to include:
const date = new Date("2026-03-15T14:30:00Z");
const formatter = new Intl.DateTimeFormat("en-US", {
weekday: "long",
year: "numeric",
month: "long",
day: "numeric",
hour: "2-digit",
minute: "2-digit",
timeZone: "America/New_York"
});
console.log(formatter.format(date));
// "Sunday, March 15, 2026, 10:30 AM"
Preset Styles
Instead of specifying each component, use dateStyle and timeStyle:
const date = new Date("2026-03-15T14:30:00Z");
const shortFormatter = new Intl.DateTimeFormat("en-US", {
dateStyle: "short"
});
console.log(shortFormatter.format(date));
// "3/15/26"
const longFormatter = new Intl.DateTimeFormat("en-US", {
dateStyle: "long",
timeStyle: "medium"
});
console.log(longFormatter.format(date));
// "March 15, 2026, 10:30:00 AM"
Supported styles: full, long, medium, short.
Number Formatting with Intl.NumberFormat
Format numbers, currency, and percentages with Intl.NumberFormat.
Basic Number Formatting
const number = 1234567.89;
const usFormatter = new Intl.NumberFormat("en-US");
console.log(usFormatter.format(number));
// "1,234,567.89"
const deFormatter = new Intl.NumberFormat("de-DE");
console.log(deFormatter.format(number));
// "1.234.567,89"
Currency Formatting
const amount = 1999.99;
const usdFormatter = new Intl.NumberFormat("en-US", {
style: "currency",
currency: "USD"
});
console.log(usdFormatter.format(amount));
// "$1,999.99"
const eurFormatter = new Intl.NumberFormat("de-DE", {
style: "currency",
currency: "EUR"
});
console.log(eurFormatter.format(amount));
// "1.999,99 €"
Percentages
const ratio = 0.756;
const percentFormatter = new Intl.NumberFormat("en-US", {
style: "percent",
minimumFractionDigits: 1
});
console.log(percentFormatter.format(ratio));
// "75.6%"
Compact Notation
const large = 1234567;
const compact = new Intl.NumberFormat("en-US", {
notation: "compact",
maximumSignificantDigits: 3
});
console.log(compact.format(large));
// "1.23M"
Relative Time with Intl.RelativeTimeFormat
Format relative times like “3 days ago” or “in 2 hours”. This API requires ES2020 or later.
const rtf = new Intl.RelativeTimeFormat("en", { style: "long" });
console.log(rtf.format(-1, "day"));
// "1 day ago"
console.log(rtf.format(3, "week"));
// "in 3 weeks"
console.log(rtf.format(-2, "hour"));
// "2 hours ago"
Short and Narrow Styles
const rtfShort = new Intl.RelativeTimeFormat("en", { style: "short" });
console.log(rtfShort.format(-1, "day"));
// "1 day ago"
const rtfNarrow = new Intl.RelativeTimeFormat("en", { style: "narrow" });
console.log(rtfNarrow.format(-1, "day"));
// "1d ago"
String Sorting with Intl.Collator
The Intl.Collator API provides language-sensitive string comparison and sorting.
Basic Sorting
const names = ["ä", "z", "a", "b"];
const enCollider = new Intl.Collator("en");
console.log(names.sort(enCollider.compare));
// ["a", "b", "ä", "z"]
const svCollider = new Intl.Collator("sv");
console.log(names.sort(svCollider.compare));
// ["a", "ä", "b", "z"]
Numeric Sorting
const files = ["file1.txt", "file10.txt", "file2.txt"];
const numericCollator = new Intl.Collator("en", { numeric: true });
console.log(files.sort(numericCollator.compare));
// ["file1.txt", "file2.txt", "file10.txt"]
Sensitivity Options
const collatorBase = new Intl.Collator("en", { sensitivity: "base" });
console.log(collatorBase.compare("a", "A"));
// 0 (equal)
const collatorVariant = new Intl.Collator("en", { sensitivity: "variant" });
console.log(collatorVariant.compare("a", "A"));
// -1 (not equal)
Text Segmentation with Intl.Segmenter
The Intl.Segmenter API splits text into segments by character, word, or sentence. This API requires ES2020 or later.
Word Segmentation
const segmenter = new Intl.Segmenter("en", { granularity: "word" });
const text = "Hello world, how are you?";
const segments = segmenter.segment(text);
for (const segment of segments) {
if (segment.type === "word") {
console.log(`"${segment.segment}" [word]`);
}
}
// "Hello" [word]
// "world" [word]
// "how" [word]
// "are" [word]
// "you" [word]
Sentence Segmentation
const segmenter = new Intl.Segmenter("en", { granularity: "sentence" });
const text = "Hello! How are you? I hope you're well.";
const segments = segmenter.segment(text);
for (const segment of segments) {
console.log(`"${segment.segment}" [sentence]`);
}
// "Hello!" [sentence]
// "How are you?" [sentence]
// "I hope you're well." [sentence]
Common Pitfalls
Creating Formatters Inside Loops
Avoid creating new formatter instances inside loops. Formatters are expensive to create:
// Bad
const dates = [new Date(), new Date(), new Date()];
dates.forEach(date => {
const formatter = new Intl.DateTimeFormat("en-US");
console.log(formatter.format(date));
});
// Good
const formatter = new Intl.DateTimeFormat("en-US");
dates.forEach(date => {
console.log(formatter.format(date));
});
Conflicting Options
When using dateStyle or timeStyle, individual component options are ignored:
const date = new Date("2026-03-15T14:30:00Z");
const formatter = new Intl.DateTimeFormat("en-US", {
dateStyle: "short",
day: "numeric" // This option is ignored
});
console.log(formatter.format(date));
// "3/15/26"
Locale String Format
Use BCP 47 language tags for locales:
// Correct
const formatter = new Intl.DateTimeFormat("en-US");
const formatter2 = new Intl.DateTimeFormat("de-DE");
// May not work as expected
const badFormatter = new Intl.DateTimeFormat("english");