概要
Twitterに投稿するとCJK互換漢字が対応する統合漢字に化けるので、投稿時に化けないStandard Variant形式と互換漢字とを相互変換するページを作成した: 互換漢字-異体字セレクタ コンバータ
はじめに
Twitterで「社」(U+FA4C)、「羽」(U+FA1E)などの一部の旧漢字を投稿しようとすると、「社」(U+793E)、「羽」(U+7FBD)に化ける。
Twitterに次の文字列を投稿すると
神(U+FA19)と神(U+795E) 福(U+FA1B)と福(U+798F) 羽(U+FA1E)と羽(U+7FBD) 既(U+FA42)と既(U+65E2) 梅(U+FA44)と梅(U+6885) 社(U+FA4C)と社(U+793E) 練(U+FA57)と練(U+7DF4) 者(U+FA5B)と者(U+8005)
こうなる:
CJK互換漢字がCJK統合漢字に化ける:
— にせねこ (@nixeneko) 2019年3月16日
神(U+FA19)と神(U+795E)
福(U+FA1B)と福(U+798F)
羽(U+FA1E)と羽(U+7FBD)
既(U+FA42)と既(U+65E2)
梅(U+FA44)と梅(U+6885)
社(U+FA4C)と社(U+793E)
練(U+FA57)と練(U+7DF4)
者(U+FA5B)と者(U+8005)
左側の字が右側の字と同じになっている。
これは一体どういうことなのだろうか? 実は、Unicodeの問題である。
CJK互換漢字
これらの化ける文字は、UnicodeにおいてCJK互換漢字という領域に収録されている。互換漢字に対し、基本となる漢字はCJK統合漢字と呼ばれる。CJKはChina, Japan, Koreaの略で、各国で微妙に字体が違っても、同一とされた*1漢字は国に関わらず一つとし、原則として重複収録はしない方針となっている。
しかし、CJK互換漢字は名前の通り、互換性を保つために収録された漢字である。それまでの文字コード等との互換性を保つ関係*2で「同じ文字を重複して収録した」扱いであり、CJK統合漢字の中に対応する漢字をもつ。
Unicode正規化
ここで、Unicodeは検索等の利便性のために、「Unicode正規化(normalization)」という処理を提供している。これは、記号付きのアルファベットなど、二種類以上のコード列で表すことができる文字列を適切に比較したりするために重要な処理である。しかし、CJK互換漢字に対してUnicode正規化を行うと、対応するCJK統合漢字に「化けて」しまう*3。
Twitter投稿時のUnicode正規化
Twitterは、2015年から投稿時にUnicode正規化を行うようになった*4。そのため、CJK互換漢字をTwitterに投稿すると対応するCJK統合漢字に置換されてしまい、CJK互換漢字を投稿することはできなくなった。
Standardized Variant
とはいっても、Unicode正規化によってCJK互換漢字が化けてしまうと困る。そういった場合のために、Unicodeの異体字セレクタという仕組みを使ってCJK互換漢字相当の漢字を表現できる枠組みが作られた(2013年9月制定のUnicode 6.3)。これによって表現されたものをStandardized Variantとよぶ。これは、Unicode Character DatabaseのStandardizedVariants.txtの後半に定義されている。
この仕組みを使うと、Unicode正規化を行っても化けないため、Twitter等にCJK互換漢字の字形の漢字を投稿することができる(ただし、正しい形で表示されるかは環境による)。
互換漢字↔Standardized Variant変換器
CJK互換漢字はともかく、Standardized Variant形式を入力することは不便なので、CJK互換漢字とStandardized Variant形式を相互に変換するページを作成した。
TwitterにCJK互換漢字に含まれる字形を投稿したい場合等に利用していただきたい。
Standardized Variantの実際の表示
Standardized Variant:
— にせねこ (@nixeneko) 2019年3月16日
神︀(U+795E U+FE00)と神(U+795E)
福︀(U+798F U+FE00)と福(U+798F)
羽︀(U+7FBD U+FE00)と羽(U+7FBD)
既︀(U+65E2 U+FE00)と既(U+65E2)
梅︀(U+6885 U+FE00)と梅(U+6885)
社︀(U+793E U+FE00)と社(U+793E)
練︁(U+7DF4 U+FE01)と練(U+7DF4)
者︀(U+8005 U+FE00)と者(U+8005)
Standardized Variantで表現されたものは、環境によるが互換漢字の字形で表示される。手元のWindows 10環境では、Firefoxでは互換漢字の字形で表示されたが、Chromeではそうはならなかった。

ちなみに、ちゃんと変換できているかなどは、
などのページで確認できる。
*1:細かい字体の違いを無視し同一とみなすことを包摂(unification)という。
*2:「ラウンドトリップ変換(round-trip conversion)の確保」といい、既存の文字コード(Shift_JISなど)からUnicodeに変換し、その後元の文字コードに再度変換したときに、内容(文字コード列)が同一になるように保証されている。
*3:Unicode正規化における等価性は正準等価と互換等価という2種類がある(Unicodeの等価性 - Wikipedia)のだが、CJK互換漢字については正準等価となっている。正準等価は見た目も機能としても同じものに対して適用されるべきものなので、互換漢字という見た目が異なるものに対して適用されているので問題となっている。Unicode正規化には種類があり、互換等価については対象としないものもあるが、正準等価は常に対象になる。
*4:厳密な時期はこちらで推定されている: TwitterにUnicode正規化が導入された時刻の推定 by zeeksphere - Togetter