Formatting lists with JavaScript's Intl.ListFormat

Published on in JavaScript

Last updated on

Pass an array of strings and get back a string with the array items separated by commas, except with the last comma replaced with the word "and" or "or." Like "item 1, item 2 and item 3."

Table of contents

Using locales

Intl.ListFormat enables "language-sensitive list formatting," so you can use different locales:

const list = ['Ham', 'Spam', 'Eggs']

/* en-US */

new Intl.ListFormat('en-US', {
  style: 'long',
  type: 'conjunction',
}).format(list)
//=> Ham, Spam, and Eggs

new Intl.ListFormat('en-US', {
  style: 'short',
  type: 'disjunction',
}).format(list)
//=> Ham, Spam, or Eggs

/* en-GB */

new Intl.ListFormat('en-GB', {
  style: 'long',
  type: 'conjunction',
}).format(list)
//=> Ham, Spam and Eggs

new Intl.ListFormat('en-GB', {
  style: 'short',
  type: 'disjunction',
}).format(list)
//=> Ham, Spam or Eggs

/* ja-JP */

new Intl.ListFormat('ja-JP', {
  style: 'long',
  type: 'conjunction',
}).format(list)
//=> Ham、Spam、Eggs

new Intl.ListFormat('ja-JP', {
  style: 'short',
  type: 'disjunction',
}).format(list)
//=> Ham、Spam、またはEggs

Notice how the en-US locale uses Oxford commas and en-GB does not.

Formatting to parts

There's also a formatToParts() method that "returns an Array of objects representing the different components that can be used to format a list of values in a locale-aware fashion":

const list = ['Ham', 'Spam', 'Eggs']

new Intl.ListFormat('en-US', {
  style: 'long',
  type: 'disjunction',
}).formatToParts(list)
//=> [
//     { type: 'element', value: 'Ham' },
//     { type: 'literal', value: ', ' },
//     { type: 'element', value: 'Spam' },
//     { type: 'literal', value: ', or ' }, // Oxford comma 👀
//     { type: 'element', value: 'Eggs' },
//   ]

new Intl.ListFormat('en-GB', {
  style: 'short',
  type: 'disjunction',
}).formatToParts(list)
//=> [
//     { type: 'element', value: 'Ham' },
//     { type: 'literal', value: ', ' },
//     { type: 'element', value: 'Spam' },
//     { type: 'literal', value: ' or ' }, // No Oxford comma
//     { type: 'element', value: 'Eggs' },
//   ]

new Intl.ListFormat('ja-JP', {
  style: 'short',
  type: 'disjunction',
}).formatToParts(list)
//=> [
//     { type: 'element', value: 'Ham' },
//     { type: 'literal', value: '、' },
//     { type: 'element', value: 'Spam' },
//     { type: 'literal', value: '、または' },
//     { type: 'element', value: 'Eggs' },
//   ]

I'm using formatToParts() on this site to format lists of tag links.

Browser support

Browser support of Intl.Listformat is nicely green, though Safari and iOS Safari have only recently (April 2021) added support for Intl.ListFormat.