Unicodeでポなどがホと半濁点の記号に分離されても一つの文字として見えてしまう現象に関してざっくりまとめる
TL;DR
- Unicodeでは2つの文字符号位置を合わせて1つの文字を表す
Combining Character Sequence
という概念が存在する。 - 日本語の濁音と半濁音にも「かな」と「濁音」をバラバラに扱い足し合わせることができる。そのためmacOSなどでは分解されてしまうケースがある。(
ば
がは
ど
に別れてしまう) - Unicodeでは正規化する方法が定義されており、合成後の文字が定義されている場合はその文字に変換される(
は
ど
は合成後のば
が1文字として定義されているので、そちらに変換できる- ただしこの正規化は漢字の扱いにおいて留意する点があるため、統一化したい場合に問題ないかを認識しておく必要がある
Combining Characterとは
Combining Characterとは何かしら他の意味のある文字と組み合わせて使うための文字のことを指す。日本語だと濁音(゙
、UnicodeコードポイントはU+0399)、英字だとウムラウト( ̈
、コードポイントはU+0308 )などが当てはまる。
Combining Characterの使われ方とCombining Character Sequence
か
などのBase Characterとよばれるベースの文字とワンセットでつかうことで が
を表現することができる。このようにBase CharacterとCombining Charactorを合わせたものを Combining Character Sequence と呼ぶ。
また、が
のようにすでに「か」と「濁音」が一つとなってコードポイントが定義されているような文字のことをPrecomposed Characterと呼ぶ。
Combining Character Sequenceの問題点
上記のように組み合わせ次第で色々表現が可能となっているUnicodeの仕様だが、プログラムで解析するときに『ば
』と『は
+゙
』は別ものになってしまうので、「ばか」という文字列だったら除外する
のような処理をする場合に処理の書き方によってはCombining Character Sequenceで表現された文字はすり抜けてしまう危険がある。
1つの解決策としての正規化
Unicodeでは正規化という機構を用意しており、「分解」と「合成」という概念で処理をする。
「分解」はCombining Character Sequenceとして分解可能な文字を分解する処理、「合成」はCombining Character Sequenceが同一視できるPrecomposed Characterが存在すれば合成して一つの文字にすることを言う。
この「分解」と「合成」に関して分解後と分解前、合成後と合成前に同じものであるかのルールに関しても考え方が2つある。
ひとつは「Canonical Equivalent(正準等価)」という視覚的および機能的に等価な文字を等価と考える方法でもうひとつは「Compatibility Equivalent(互換等価)」という㌠
と サンチーム
を等価と考える広い解釈の2つがある。
正規化に関してはルールがいくつか存在するのですが、よく使われるのが Normalization Form Canonical Composition (略称:NFC)
があり、これは「正準等価によって分解され、再度正準等価で合成される。」というもの、なのでひらがなやカタカナと濁音を一つの文字コードに寄せる場合にはこのNFCを利用すれば一律Precomposed Characterに変換することができる。
NFCを使うときの困りポイントであるCJK互換漢字
ここまでの説明だと「NFCで一律正規化をかければすべてPrecomposed Characterになるので解決」となりそうなのですが、NFCでは今回のCombining Character Sequenceとは別の観点の問題としてCJK互換漢字の問題があります。
CJK(ChinaJapanKorea)互換漢字は日本・中国・韓国の漢字の類似する文字を統合するCJK統合漢字という概念があり、その互換性がある漢字のことを指す。
よく語られるのは神の字で「ネ申」と書くのが普通だが「示申」と書くケースがあり、この2つはCJK互換漢字の関係にあり、すべてCJK統合漢字である「ネ申」と書く神に集約される関係にある。
NFCを使うとCJK互換漢字はすべてCJK統合漢字に変換されるので、厳密に漢字を扱いたい場合は何も考えずにNFCを行うと漢字が置き換わってしまうので気をつける必要がある。
補足:Combining Character Sequenceの日本語訳について
この Combining Character Sequence
に関しては訳し方が年代によって変わっており、最近は「結合文字列」という表記をされることが多いが、物によっては直感的な認識を優先して「合成文字」と訳されるケースがある。
今回はその点に関して齟齬が起きづらいように英文ママの表現でざっくりまとめました。
詳しくは以下のリンクを参照すると日本語情報を調べるときに役立つと思います。
Unicode正規化 用語の混乱について 第4.2版 – ものかの
参考リンク
- Unicodeの特殊な文字 “結合文字列” – ものかの
- 文字コード地獄秘話 第3話:後戻りの効かないUnicode正規化 | ALBERT Engineer Blog
- 普通のUnicodeはNFCなのか – ものかの
- String#unicode_normalize (Ruby 3.0.0 リファレンスマニュアル)
- String.prototype.normalize() - JavaScript | MDN
- CJK互換漢字 - JIS X 0213 Wiki
なお、未見なのですが文字コード悩まされる事が多いので下記の本を読んでみたくなりました…(財布の関係でまだ未入手)