A polyfill for Intl.ListFormat tested by the official ECMAScript Conformance test suite

npm Version size

ECMA-402 Spec Compliance

This package implements Intl.ListFormat. See the conformance report for tested coverage and known limitations.

✅ Implemented Features

Core Methods

  • format(list) - Format a list of strings as a localized string
  • formatToParts(list) - Format a list and return an array of parts
  • resolvedOptions() - Returns resolved formatting options
  • supportedLocalesOf(locales) - Returns supported locales

List Types

  • 'conjunction' (default) - "and" lists (e.g., "A, B, and C")
  • 'disjunction' - "or" lists (e.g., "A, B, or C")
  • 'unit' - Unit lists (e.g., "5 pounds, 12 ounces")

List Styles

  • 'long' (default) - Full format (e.g., "A, B, and C")
  • 'short' - Abbreviated format (e.g., "A, B, & C")
  • 'narrow' - Most compact format (e.g., "A, B, C")

Example Usage

Global import

import '@formatjs/intl-listformat/polyfill.js'

// Conjunction (and)
const conjunctionFormatter = new Intl.ListFormat('en', {
  style: 'long',
  type: 'conjunction',
})
conjunctionFormatter.format(['Apple', 'Banana', 'Orange'])
// "Apple, Banana, and Orange"

// Disjunction (or)
const disjunctionFormatter = new Intl.ListFormat('en', {
  type: 'disjunction',
})
disjunctionFormatter.format(['Red', 'Green', 'Blue'])
// "Red, Green, or Blue"

// Unit lists
const unitFormatter = new Intl.ListFormat('en', {
  style: 'short',
  type: 'unit',
})
unitFormatter.format(['5 lb', '12 oz'])
// "5 lb, 12 oz"

// formatToParts
const parts = conjunctionFormatter.formatToParts(['A', 'B', 'C'])
// [
//   {type: "element", value: "A"},
//   {type: "literal", value: ", "},
//   {type: "element", value: "B"},
//   {type: "literal", value: ", and "},
//   {type: "element", value: "C"}
// ]

ES Modules

import {ListFormat} from '@formatjs/intl-listformat'

// Conjunction (and)
const conjunctionFormatter = new ListFormat('en', {
  style: 'long',
  type: 'conjunction',
})
conjunctionFormatter.format(['Apple', 'Banana', 'Orange'])
// "Apple, Banana, and Orange"

Installation

npm i @formatjs/intl-listformat

Requirements

Usage

Via polyfill-fastly.io

You can use polyfill-fastly.io URL Builder to create a polyfill script tag for Intl.ListFormat. By default the created URL does not come with any locale data. In order to add locale data, append Intl.ListFormat.~locale.<locale> to your list of features. For example:

<!-- Polyfill Intl.ListFormat, its dependencies & `en` locale data -->
<script src="https://polyfill-fastly.io/v3/polyfill.min.js?features=Intl.ListFormat,Intl.ListFormat.~locale.en"></script>

Simple

import '@formatjs/intl-listformat/polyfill.js'
import '@formatjs/intl-listformat/locale-data/en.js' // locale-data for en

Dynamic import + capability detection

async function polyfill(locale: string) {
  const unsupportedLocale = shouldPolyfill(locale)
  // This locale is supported
  if (!unsupportedLocale) {
    return
  }
  // Load the polyfill 1st BEFORE loading data
  await import('@formatjs/intl-listformat/polyfill-force.js')
  await import(`@formatjs/intl-listformat/locale-data/${unsupportedLocale}.js`)
}

Tests

The Bazel :test262 target runs the upstream suite against a reviewed failure baseline. A green baseline check does not mean every test passed. See the conformance report; run bazel test //packages/intl-listformat:test262-strict to require zero failures.

Iterable inputs

format and formatToParts accept iterables of strings, including a string's individual code points. undefined produces an empty list. Non-iterables and non-string elements throw TypeError; an invalid element also closes the iterator.

Loading und locale data preserves existing English data. Root patterns remain separate from language-specific patterns, regardless of registration order.

Loading a locale also registers its CLDR default-content variants. For example, English data supports en-US. Explicitly loaded regional data remains distinct from its language's data, regardless of load order.