Узнайте, как Intl.Segmenter улучшает сегментацию текста в JavaScript для интернационализации

В обширной области JavaScript объект Intl играет ключевую роль в облегчении сравнения строк с учетом языка, форматирования чисел и форматирования даты и времени. Среди множества впечатляющих функций выделяется Intl.Segmenter. Этот мощный инструмент обеспечивает сегментацию текста с учетом региональных настроек, упрощая извлечение значимых элементов, таких как графемы, слова или предложения из строки.

Необходимость в международном сегменте

Вам может быть интересно, зачем нам нужен Intl.Segmenter, когда у нас есть такие методы, как split(). Чтобы понять это, давайте возьмем простой пример. Допустим, мы хотим разбить строку на предложения. Базовый подход может выглядеть так:

'Hello there! How are you doing?'.split(/[.!?]/);

Этот код даст нам массив: ['Hello there', ' How are you doing', '']. Хотя кажется, что это работает, есть несколько проблем:

  1. Знаки препинания, которые использовались в качестве разделителей, теперь исчезли.
  2. В некоторых результирующих строках есть начальные пробелы.
  3. Этот подход не зависит от языка. Это не сработает для языков, в которых не используются ., ! или ? в конце предложения.

Предположим, мы имеем дело с японской строкой: «吾輩は猫である。名前はたぬき。», что переводится как «Я кошка. Меня зовут Тануки». Наш простой метод split() не работает. Вот где Intl.Segmenter приходит на помощь!

Механика Intl.Segmenter

Intl.Segmenter позволяет нам разбивать строки на значимые части. Нам просто нужно определить локаль и степень детализации (это может быть предложение, слово или графема), и он готов к сегментации любой строки.

Вот пример использования Intl.Segmenter:

const germanSegmenter = new Intl.Segmenter('de', { 
  granularity: 'word'
});
const germanSegments = germanSegmenter.segment('Was geht ab, Freunde?');

В этом фрагменте мы разбиваем немецкую строку на слова.

Возвращение Segmenter.segment

Метод segment() возвращает не массив, а итерируемый объект. Чтобы получить доступ ко всем сегментам, мы можем использовать расширение массива, Array.from() или цикл for...of.

Вот как это сделать:

const germanSegmenter = new Intl.Segmenter('de', {
  granularity: 'sentence'
});
const germanSegments = germanSegmenter.segment('Was geht ab, Freunde?');

console.log([...germanSegments]);
console.log(Array.from(germanSegments));
for (let segment of germanSegments) {
  console.log(segment);
}

Каждый сегмент включает исходное значение строки (input), индекс символа в исходной строке (index) и фактическую строку сегмента (segment).

Сопоставление сегментов с их строковыми значениями

Если вы хотите сопоставить сегменты с их строковыми значениями, вы можете использовать второй аргумент Array.from(), который является функцией сопоставления.

Вот пример:

const germanSegmenter = new Intl.Segmenter('de', {
  granularity: 'sentence'
});
const germanSegments = germanSegmenter.segment('Was geht ab?');

console.log(Array.from(germanSegments, s => s.segment));

Использование свойства isWordLike

Когда вы разбиваете строку на слова, все сегменты включают пробелы и разрывы строк. К счастью, Intl.Segmenter предоставляет свойство isWordLike, которое может помочь их отфильтровать. Вот как:

const germanSegmenter = new Intl.Segmenter('de', {
  granularity: 'word'
});
const germanSegments = germanSegmenter.segment('Was geht ab?');

console.log([...germanSegments].filter(s => s.isWordLike));

В этом примере мы отфильтровываем все сегменты, которые не являются словами. Таким образом, пробелы, знаки препинания и разрывы строк будут исключены из результата.

Обработка эмодзи с помощью Intl.Segmenter

Одним из интересных применений Intl.Segmenter является его способность разбивать строку на визуальные смайлики. Смайлики могут быть довольно сложными, особенно с появлением составных смайликов, состоящих из нескольких кодовых точек.

Давайте рассмотрим эту строку смайликов: «🫣🫵👨‍👨‍👦‍👦».

Если мы попытаемся разбить его по кодовым единицам или даже кодовым точкам, мы не получим ожидаемых результатов:

const emojis = '🫣🫵👨‍👨‍👦‍👦';

console.log(emojis.split(''));  // Split by code units
console.log([...emojis]);       // Split by code points

Однако Intl.Segmenter изящно справляется с этим:

const emojis = '🫣🫵👨‍👨‍👦‍👦';

const segmenter = new Intl.Segmenter('en', {
  granularity: 'grapheme'
});
console.log(Array.from(segmenter.segment(emojis), s => s.segment));

В этом случае мы получаем каждый составной эмодзи как отдельную графему.

Подведение итогов

С постоянно растущей сложностью и глобализацией веб-приложений такой инструмент, как Intl.Segmenter, может изменить правила игры. Он привносит в JavaScript обработку строк с учетом языка, делая такие задачи, как сегментация, не только возможными, но и относительно простыми.

Спасибо за чтение! Любите эти истории? Поддержите меня членством в ежемесячных подборках статей. Или присоединяйтесь к Medium по моей ссылке.

Дополнительные материалы на PlainEnglish.io.

Подпишитесь на нашу бесплатную еженедельную рассылку новостей. Подпишитесь на нас в Twitter, LinkedIn, YouTube и Discord .