Splitting text by character or word
Intl.Segmenter
Baseline newly available
Chrome87
Edge87
Firefox125
Safari14.1
Features it needs
- Intl.SegmenterNewly available
A string's length counts UTF-16 code units, so a thumbs-up with a skin tone reads as four and slicing at an arbitrary index can cut a character in half. These libraries fix that by shipping their own copy of the Unicode grapheme cluster rules, which is most of their weight. Intl.Segmenter reads the copy the browser already holds and segments by grapheme, word or sentence, so "how many characters" and "what are the words" both get a locale-aware answer.
When this applies
Counting, splitting or truncating text by user-perceived character, word or sentence.
The native approach
const graphemes = new Intl.Segmenter("en", { granularity: "grapheme" });
"๐๐ฝok".length; // 6
[...graphemes.segment("๐๐ฝok")].length; // 3
const words = new Intl.Segmenter("en", { granularity: "word" });
[...words.segment("Hello, world")]
.filter((part) => part.isWordLike)
.map((part) => part.segment);
// ["Hello", "world"]When the dependency is still right
An answer that always says "the platform covers it" is worse than no answer. These are the cases where this one does not hold.
- You use lodash.words to split identifiers, as in fooBarBaz or snake_case. That is a camel case convention rather than a Unicode word boundary, and Intl.Segmenter will not split it.
- You only need code points rather than grapheme clusters. Array.from(str) and the spread form already split by code point, with no Segmenter and no library.
- You need segmentation that cannot move. Each engine ships its own Unicode version, so a recent emoji can segment differently between browsers and can change when one updates.
- The same code runs on a Node build compiled with small-icu, where the locale data Segmenter depends on is largely absent.
- You measure the width of terminal output. string-length also strips ANSI escape codes before counting, and Intl.Segmenter counts them as segments, so a colourised CLI silently gets its column widths wrong.