浏览器的 Intl API 提供了大量关于文本和数字编辑格式化的功能。当我填写 HTML 状态调查时,发现了一个从未见过的功能:分词 API。了解后得知,它可以根据文本语言把文本划分成不同段落。
这引起我注意,因为我最近实现了一个文本测量功能,非常恼火它只支持西方语言,使用拉丁字母和空格分词。
我在 npm 包、正则表达式上花了大量时间做试错,却无法支持其他语言。
就是这个segmenter API 让我看到了希望。
Polypane 如何利用分词 API
在 Polypane 中选择文本并右键打开菜单时,会显示选中文本中的字符、单词和表情符号数,这就是利用了分词 API。
可以快速检查推文字符数是否正确,或者博客文章词数是否达标。
配置segmenter API
坏消息是,该 API 仅在 Safari 14.1+ 和 Chromium 87+ 可用,Firefox 还不支持。有个 polyfill 但似乎非常笨重。
使用时,先创建一个分词实例,需要指定语言和选项。
const segmenter = new Intl.Segmenter('en', { granularity: 'word' });
选项对象有两个可选属性:
- localeMatcher 可选 'lookup' 或 'best fit'(默认)。'lookup' 使用特定匹配算法 (BCP 47),'best fit' 使用更宽松算法尽可能匹配可用语言。
- granularity 可选 'grapheme'(默认)、'word' 或'sentence', 决定返回的段落类型。默认 'grapheme' 返回可见字符。
调用 segmenter.segment 传入要分割的文本,它返回一个迭代器,可以用 Array.from 转换为数组:
const segments = segmenter.segment('This has four words!');
Array.from(segments).map((segment) => segment.segment);
// ['This', ' ', 'has', ' ', 'four', ' ', 'words', '!']
迭代器每个项目是一个对象,根据粒度它包含不同的值,至少有:
- segment 段落文本。
- index 段落在原文中的索引,如起始位置。
- input 原文。
单词粒度还包含:
- isWordLike 布尔值,如果是单词则为 true。
你可能看数组说 “空格不是单词吧?”。确实不是。要获取单词,需过滤数组:
const segments = segmenter.segment('This has four words!');
Array.from(segments)
.filter((segment) => segment.isWordLike)
.map((segment) => segment.segment);
// ['This', 'has', 'four', 'words']
这样我们就能知道句子中的单词个数了。
不仅可以分割单词像上例,还可以分割句子,它能识别句号是结束句子还是数字的千分位分隔符:
const segmenter = new Intl.Segmenter('en', { granularity: 'sentence' });
const segments = segmenter.segment('This is a sentence with the value 100.000 in it. This is another sentence.');
Array.from(segments).map((segment) => segment.segment);
// [
// 'This is a sentence with the value 100.000 in it.',
// 'This is another sentence.'
// ]
没有 isSentenceLike 和 isGraphemeLike 属性,可以直接统计项目数。
支持其他语言
API 的实力在于,它不仅根据空格或句号来分割,而是为每种语言使用特定算法。这意味着它可以分割没有空格的语言单词,如日语:
const segmenter = new Intl.Segmenter('ja', { granularity: 'word' });
const segments = segmenter.segment('これは日本語のテキストです');
Array.from(segments).map((segment) => segment.segment);
// ['これ', 'は', '日本語', 'の', 'テキスト', 'です']
我不懂日文,所以不能判断分割是否准确,但看起来相当可信。
与字符串拆分或正则表达式相比,这更准确,正确处理非拉丁字符和标点,代码更少,无需额外检查和测试。浏览器内置大量语言支持,你不必担心这点。
深入了解 Intl API
Intl API 提供大量创建自然语言构造的实用工具,如列表、日期、货币、数字等。总体来说使用简单,但它使用了你可能不熟悉的精确术语 (如使用 “字形” 而不是 “字符”, 后者太模糊), 刚开始可能有点难搞。如果从未使用过可以查看 MDN 上的 Intl 介绍。
Polypane 的下个版本会有跨语言的文本测量选项,并显示选中文本的句子数。