Formatting Language-Sensitive Lists in JavaScript With ListFormat
Tags: webdev, tutorial, javascript, beginners
Published: 2020-01-18 03:32:56

**Subscribe to my email list now at http://jauyeung.net/subscribe/**

**Follow me on Twitter at https://twitter.com/AuMayeung**

**Many more articles at https://medium.com/@hohanga**

With the `Intl.ListFormat` constructor, we can format language-sensitive lists with ease. It lets us set the locale in which to format a list. Also, it lets us set options for formatting lists such as the type of list or style of the list. To use it, we can create a new `ListFormat` object with the `Intl.ListFormat` constructor.

The constructor takes up to two arguments. The first argument is a string of the locale that you want to format the list for. The second argument takes an object with the options for formatting and styling the list. An example use of the `Intl.ListFormat` constructor is:

```javascript
const arr = ['bus', 'car', 'train'];
const formatter = new Intl.ListFormat('en', {
  style: 'long',
  type: 'conjunction'
});
const formattedList = formatter.format(arr);
console.log(formattedList);
```

If we run the code above, we will see _bus_, _car_, _and_ _train_ logged from the `console.log` statement. The `Intl.ListFormat` constructor creates a formatter object that has the `format` method to convert an array into a list according to the locale and formatting options that we set.

In the example above, we set the locale to `en` for English, we set the `style` property to `long`, which formats an array of strings into something like _A_, _B_, _and C_ or _A, B, or C_. The `type` property specifies the kind of list we want to format the list into. Conjunction means that we format a list into _A, B, and C_.

The arguments of the constructor are the locales that you want to format the list into. It can be a string or an array of strings containing the locale of the list you want to format it into. The locale string or strings should be a BCP 47 language tag. The `locales` argument is optional. An abridged list of BCP-47 language tags includes:

```
ar — Arabic
bg — Bulgarian
ca — Catalan
zh-Hans — Chinese, Han (Simplified variant)
cs — Czech
da — Danish
de — German
el — Modern Greek (1453 and later)
en — English
es — Spanish
fi — Finnish
fr — French
he — Hebrew
hu — Hungarian
is — Icelandic
it — Italian
ja — Japanese
ko — Korean
nl — Dutch
no — Norwegian
pl — Polish
pt — Portuguese
rm — Romansh
ro — Romanian
ru — Russian
hr — Croatian
sk — Slovak
sq — Albanian
sv — Swedish
th — Thai
tr — Turkish
ur — Urdu
id — Indonesian
```

The second argument for the constructor is an object that lets us set the options for how to format the list’s string. There are three properties for this object: `localeMatcher`, `type`, and `style`. The `localeMatcher` option specifies the locale-matching algorithm to use. The possible values are `lookup` and `best fit`.

The `lookup` algorithm searches for the locale until it finds the one that fits the character set of the strings that are being compared.

`best fit` finds the locale that is at least as, but possibly more, suitable than the `lookup` algorithm.

The `type` property can take on two possible values: `conjunction`, `disjunction`, or `unit`. `conjunction` means that the list is joined with an _and_, as in _A, B, and C_. This is the default option. `disnjunction` means the list is joined with an _or_, as in _A, B, or C_.

`unit` stands for a list of values with units.

The `style` property specifies the length of the formatted message. There are two possible values for this property. It can either be `long` (e.g., _A, B, and C_), `short` (e.g., _A, B, C_), or `narrow` (e.g., _A B C_). When `style` is `short` or `narrow`, `unit` is the only allowed value for this option.

For example, we can use it to format a list into a string that is joined with an _and_ at the end. We can write the following to do so:

```javascript
const arr = ['bus', 'car', 'bicycle'];
const formatter = new Intl.ListFormat('en', {
  style: 'long',
  type: 'conjunction'
});
const formattedList = formatter.format(arr);
console.log(formattedList);
```

If we log the `formattedList` constant like we did above, we get _bus, car, and bicycle_. We set the `en` locale to format the string for the English locale, with style `long` and as a conjunction, which means the list will be joined with an _and_ at the end. If we want to get an _or_\-based list, we can change the `type` property to a `disjunction`, as in the following code:

```javascript
const arr = ['bus', 'car', 'bicycle'];
const formatter = new Intl.ListFormat('en', {
  style: 'long',
  type: 'disjunction'
});
const formattedList = formatter.format(arr);
console.log(formattedList);
```

If we run the code above, then we get _bus, car, or bicycle_ logged in the `console.log` statement above.

We can convert it to a shorter list by using the `short` or `narrow` option for the `style` property. For example, we can write:

```javascript
const arr = ['bus', 'car', 'bicycle'];
const formatter = new Intl.ListFormat('en', {
  style: 'short',
  type: 'conjunction'
});
const formattedList = formatter.format(arr);
console.log(formattedList);
```

Then we get _bus, car, & bicycle_ in the `console.log` output when we run the code above. The `short` and `disjunction` combination is the same as the `long` and `disjunction` combination. If we write:

```javascript
const arr = ['bus', 'car', 'bicycle'];
const formatter = new Intl.ListFormat('en', {
  style: 'short',
  type: 'disjunction'
});
const formattedList = formatter.format(arr);
console.log(formattedList);
```

Then we get _bus, car, or bicycle_. The `narrow` option would make it even shorter. For example, if we put:

```javascript
const arr = ['bus', 'car', 'bicycle'];
const formatter = new Intl.ListFormat('en', {
  style: 'narrow',
  type: 'conjunction'
});
const formattedList = formatter.format(arr);
console.log(formattedList);
```

Then we get _bus, car, bicycle_ logged in the `console.log` when we run the code above.

This also works for non-English locales. For example, if we want to format a list of Chinese strings into a list, we can write the following code:

```javascript
const arr = ['日', '月', '星'];
const formatter = new Intl.ListFormat('zh-hant', {
  style: 'narrow',
  type: 'conjunction'
});
const formattedList = formatter.format(arr);
console.log(formattedList);
```

Then we get ‘日、月和星’, which means _sun, moon, and stars_. If we switch the `style` option to `long` or `short`, we would get the same thing because in Chinese there’s only one way to write a conjunction, unlike in English. `disjunction` also works with Chinese. For instance, if we have:

```javascript
const arr = ['日', '月', '星'];
const formatter = new Intl.ListFormat('zh-hant', {
  style: 'long',
  type: 'disjunction'
});
const formattedList = formatter.format(arr);
console.log(formattedList);
```

Then we get ‘日、月或星’ which means _sun, moon, or stars_. If we switch the `style` option to `long` or `short`, as with Chinese conjunctions, we would get the same thing because in Chinese there’s only one way to write a disjunction, unlike in English.

* * *

formatToParts() Method
======================

In addition to the `format` method, the `Intl.ListFormat` instance also has the `formatToParts` method, which formats an array into a conjunction or disjunction string and then returns it as an array of the parts of the formatted string.

For example, if we want to return an array of the parts of the formatted English string for a list, then we can write the following code:

```javascript
const arr = ['bus', 'car', 'bicycle'];
const formatter = new Intl.ListFormat('en', {
  style: 'long',
  type: 'conjunction'
});
const formattedList = formatter.formatToParts(arr);
console.log(formattedList);
```

Then we get:

```json
[
  {
    "type": "element",
    "value": "bus"
  },
  {
    "type": "literal",
    "value": ", "
  },
  {
    "type": "element",
    "value": "car"
  },
  {
    "type": "literal",
    "value": ", and "
  },
  {
    "type": "element",
    "value": "bicycle"
  }
]
```

from the `console.log` statement. These are the parts of the formatted string that we get with the `format` method, but broken apart into individual entries. This method is handy if we only want some parts of the formatted string.

* * *

With the `Intl.ListFormat` constructor, formatting language-sensitive lists is easy. The constructor takes a locale string or an array of locale strings as the first argument and an object with some options for the second argument. We can convert an array into a string that has the list formatted into conjunction or disjunction with the `Intl.ListFormat` instance’s `format` method, which takes a locale string and options for the length style of the formatted string and whether it’s a conjunction, disjunction, or unit string. It also has a `formatToParts` method to convert it to a formatted list and then break up the parts into an array.