如何将一个字符和一个“组合重音”组合成一个单一字符?

8

如何将一个字符和一个“组合音调”组合成一个单独的字符?

我正在将用户输入的短语提交到法英词典中进行查询。有时,由于大多数重音字符都有两种表示方式,因此词典查询会失败。例如:

  • é可以用一个字符完成:\xE9(带有锐音的拉丁小写字母e)。
  • 但是它也可以由两个字符表示:e + \u0301(组合式锐音符号)。

我总是想向词典提交前者(单个字符)。

目前,我通过替换每个两个字符的出现来实现等效的单个字符。但是是否有更简单(即一行)的方法在JavaScript或从输入字段获取时在浏览器中执行此操作?

function translate(phrase) {
    // Combine accents into a single accented character, if necessary.
    var TRANSFORM = [
        // Acute accent.
        [/E\u0301/g, "\xC9"], // É
        [/e\u0301/g, "\xE9"], // é

        // Grave accent.
        [/a\u0300/g, "\xE0"], // à
        [/e\u0300/g, "\xE8"], // è
        [/u\u0300/g, "\xF9"], // ù

        // Cedilla (no combining accent).

        // Circumflex.
        [/a\u0302/g, "\xE2"], // â
        [/e\u0302/g, "\xEA"], // ê
        [/i\u0302/g, "\xEE"], // î
        [/o\u0302/g, "\xF4"], // ô
        [/u\u0302/g, "\xFB"], // û

        // Trema.
        [/e\u0308/g, "\xEB"], // ë
        [/i\u0308/g, "\xEF"], // ï
        [/u\u0308/g, "\xFC"] // ü

        // oe ligature (no combining accent).
    ];
    for (var i = 0; i < TRANSFORM.length; i++)
        phrase = phrase.replace(TRANSFORM[i][0], TRANSFORM[i][1]);

    // Do translation.
    ...
}

你可以使用 replace 函数并将匹配简化为单个正则表达式 (.[\\u0300\\u0302]),然后检查匹配是否在所有选择的字典中。 - Alexei Levenkov
如果您正在寻找Java中的相同内容,请访问:https://docs.oracle.com/javase/9/docs/api/java/text/Normalizer.html - Christophe Roussy
1个回答

11
这被称为规范化, 看起来你想要NFC规范化:

字符按照规范等价分解再合成。

换句话说,它用单个字符替换任何组合字符。

ECMAScript 6已经内置了String.prototype.normalize,所以如果你只支持新版本浏览器,你可以直接使用以下代码:

phrase = phrase.normalize('NFC');

为了支持旧浏览器,看起来这个库可以满足你的需求:
https://github.com/walling/unorm 使用方法是phrase = UNorm.nfc(phrase)

谢谢!我在寻找答案时遇到了麻烦,因为我不知道该如何称呼它。 - Mike M. Lin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接