🎃

【JavaScript】NFD の濁音・半濁音を NFC に変換する

2024/06/13に公開

Unicode 正規化のためのメソッドは String.prototype.normalize である

> node
Welcome to Node.js v22.2.0.
Type ".help" for more information.

> 'が'.normalize('NFD').length
2
> "か\u{3099}".normalize('NFC').length
1
> '神'.normalize('NFC')
'神'
> '神'.normalize('NFD')
'神'

正規表現でひらがなやカタカナなどは Unicode プロパティとして定義されている

> regex = /\p{sc=Hiragana}/u;
/\p{sc=Hiragana}/u
> regex.test('はは')
true
> regex = /\p{sc=Katakana}/u;
/\p{sc=Katakana}/u
> regex.test('ハハ')
true

Intl.Segmenter を利用して書記素単位で処理する

const str = "ハ\u{309A}ハ\u{309A}と神";
console.log("パパと神" === convert_kana_to_nfc(str));

function convert_kana_to_nfc(str) {
  const locale = Intl.NumberFormat().resolvedOptions().locale;
  const segmenter = new Intl.Segmenter(locale);
  const iterator = segmenter.segment(str)[Symbol.iterator]();
  const regex = /[\p{sc=Hiragana}\p{sc=Katakana}][\u{3099}\u{309A}]/u;
  let ret = '';

  for (it of iterator) {
    if (regex.test(it.segment)) {
      ret += it.segment.normalize('NFC');
    } else {
      ret += it.segment;
    }
  }

  return ret;
}

Discussion