The Intl API: Formatting and Localization

· 4 min read · Updated March 23, 2026 · intermediate
javascript localization intl formatting i18n

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");

See Also