サロゲートペアだけじゃなかった、日本語の難しさIPAmj明朝で解決した話
拡張漢字(サロゲートペア)を倒して外字は終わったと思っていた。ところが「囬」という一字が豆腐になった。原因はコード範囲ではなくフォントのカバレッジ。NGWの明朝をIPAmj明朝に切り替えるまでの話。
「外字は、もう終わった」はずだった
NGWの帳票では、𠮷(つちよし)のようなサロゲートペア——Unicodeの基本多言語面(BMP)の外にある拡張漢字——を、素直には出せないという壁があった。これを、フォントのグリフを純PHPでSVGに起こして帳票に差し込む、という作り込みで越えてきた。詳しくはサロゲートで豆腐になる問題と外字をSVGで差し込むに書いた。
BMPの外まで出せるようになったのだから、もう外字は怖くない。そう思っていた。ところが、である。
囬。あっさり豆腐になった
きっかけは、利用者からの相談だった。「うちに"囬"さんがいる。でも今は、"回"で代用している」。実在の氏名に、この一字が必要だったのだ。
さっそく「囬」を帳票に入れてみたら、PDFで豆腐(□)になった。
囬 はサロゲートペアではない。U+56EC、BMPのど真ん中にいる、コードの上ではごく普通の漢字だ。サロゲート対策は完璧なはずなのに、範囲の内側にいる字が出ない。話が違う。
原因は、コード範囲ではなくフォントのカバレッジ
調べてわかった。豆腐になる原因は、実は2種類ある。
- コードがフォントの扱える範囲の外にある — サロゲートペアがこれ。前回SVG差込みで解決済み。
- コードは範囲の内側なのに、そのフォントにその字の形(グリフ)が入っていない — 囬 はこっちだった。
NGWの明朝はMS明朝を使っていた。そしてMS明朝には、囬 の字形が入っていない。範囲うんぬん以前に、フォントがその字を持っていなかったのだ。
日本語の難しさは、サロゲートペアだけじゃなかった。「その字がフォントに入っているか」という、もう一段地味で、もっと根の深い問題があった。
慌てて変える前に、「囬は本当に必要か」を考える
フォントを別のものに変えれば囬 は出る。だが、ここで飛びつくと危ない。心配なのは逆方向——いま普通に出ている常用漢字や人名用漢字が、フォントを変えたせいで出なくなることだ。それでは本末転倒になる。
そこで、切り替える前に影響範囲を数えた。
- 常用漢字(約2,100字)→ MS明朝に100%あった。
- 人名用漢字(約860字)→ こちらも100%。
つまり、住民の名前や決裁で日常的に使う字は、MS明朝でひとつ残らず足りていた。一方の囬 は、常用にも人名用にも入っていない、「回」のごく稀な異体字だった。実務でまず出会わない。
囬さん、ごめんなさい。あなたは、本当にレアな一字でした。
それでも、保険はかけておく
とはいえ、である。戸籍や地名には、公式リストの外にある異体字が実際に現れる。「まず出ない」と「絶対に出ない」は違う。役所の帳票は、一字でも豆腐にした時点で公文書として失格になる世界だ。NGWは内部の文書管理なので、これまでは「レアだから」で切り捨てていた。だが、何か解決策があるはずだ。
そこでNGWは、明朝をIPAmj明朝に切り替えた。IPAmj明朝は、戸籍や住民基本台帳のために整備された文字情報基盤(約6万字)を収めたフォントで、囬 もちゃんと入っている。
ここで効いたのが、これまでの地味な下ごしらえだった。帳票(PDF出力)の処理は、以前にひとつの共通関数へ集約してあった。おかげでフォントの切り替えは、帳票side を一切触らず、明朝の指定を差し替える一点だけで全帳票に行き渡った。過去の集約が、こういうときに効く。


新しく出るようになった字を、並べてみる
参考までに、囬 の周辺(U+562Aあたり)で、MS明朝には無くIPAmj明朝で出るようになった字を並べてみる。
嘪嘫嘭嘮嘺嘾噅噈噊噑噒噕噖噗噘噙噚噟噥噧噮噰噳噷噹噽噾噿嚁嚂嚃嚉嚍嚎嚐嚖嚗嚘嚛嚜嚪嚯嚵嚻嚽嚿囆囇囒囔团囩囪囬囯囸囻囼圅圎圔圗圞圫圱圲圵圶圼坁坃坄坈坉坋坓坔坕坖块坘坚坣坬坲坶坸坽垀垍垎垏垐垑垒垖垘垛垥垦
見てのとおり、日常でまず見ない字ばかりだ。よく見ると 团(団)や 囯(国)、块(塊)のような中国の簡体字も混じっている。Unicodeの並びの上では、日本の戸籍用の字と中国由来の字が、この辺りに同居している。囬 が置かれていたのは、そういう場所だった。
それでも、この中のどれかが、いつか誰かの戸籍に本当に載っているかもしれない。「まず出ない」で妥協しない選択に意味があるのは、そのためだ。
本当のラスボスは、まだ倒していない
ここまでで外字はほぼ制圧した。だが、本当のラスボスは違うところにいる。カラーの絵文字だ。こいつはちょっと厄介なので、今回はやっつけないことにした。1文字の中に複数の色を持つ絵文字は、これまでの「グリフを1枚のSVGに起こして差し込む」やり方の延長では、素直に扱えない。
もっとも、役所の事務系の帳票に絵文字が要ることは、まず無い。倒すのは、また今度でいい。
AIとの協働作業での学び
- 問題は、こちらの想像ではなく現場から来た。 「囬さんがいて、今は回で代用している」という利用者の一言が、すべての起点だった。サロゲートペアを越えた達成感で外字は片付いた気になっていたが、実在の氏名という現場の要求が、問題はもう一層あると教えてくれた。設計者の思い込みより、現場の一人の名前のほうが正確だった。
- 原因の切り分けを、思い込みで飛ばさない。 「コード範囲の問題」と「フォントのグリフの問題」は別物だった。フォントを変える前に、常用・人名用が100%あるかを実際に数えて、安全を確かめてから動けた。慌てて差し替えていたら、足元を崩していたかもしれない。
- 過去の集約が、変更の一点化として効く。 出力処理をひとつの共通関数にまとめてあったから、フォント切替が事実上一箇所で済んだ。地味な整理は、こういう場面で利息を返す。
- 「まず出ない」と「絶対に出さない」の差を、役所の帳票は要求する。 囬 はレアな一字だった。それでも豆腐にしない側を選べたのは、公文書という重さゆえだ。