Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
文字数の話の続き 〜Unicodeの楽しくない話〜
Search
しゅん🌙
July 05, 2023
Technology
280
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
文字数の話の続き 〜Unicodeの楽しくない話〜
前回の「文字数の話」に続き,実際に業務でアプリケーションを構築する際に起こりそうなUnicodeの問題について解説しています.
しゅん🌙
July 05, 2023
More Decks by しゅん🌙
See All by しゅん🌙
エンジニアのための”最低限いい感じ”デザイン入門
shunshobon
0
240
Rustで対戦型Tetrisを作った話
shunshobon
0
440
文字数の話 〜Unicodeの楽しい話〜
shunshobon
0
310
Haskellの並列・並行処理
shunshobon
1
470
Other Decks in Technology
See All in Technology
背中から、背中へ /paying forward to community
naitosatoshi
0
210
小さいから、全部わかる。— 常駐AI "xangi" のすすめ
sugupoko
0
220
本当の”仕事”を手放せる未来が見えた
mu7889yoon
0
210
5分でわかるDuckDB Quack
chanyou0311
4
300
AWS Summit Japan 2026の振り返りと2027へ向けて / AWS Summit Japan 2026 Recap and Prospects for 2027
kaminashi
1
180
Fabricをフル活用する AI Agent Hub -製造業特化AIエージェントの設計
iotcomjpadmin
0
190
Docker Desktop不要の時代が来る? WSL標準の「wslc」で Linuxコンテナを動かしてみた.
ueponx
0
520
10x Speed With QA Agent Platform - How we scaled adoption from individual effort to organizational capability
lycorptech_jp
PRO
0
110
Multi-Agent並列開発を 安全に回すための技術 / Technology for Safely Multi-Agent Parallel Development
tooppoo
0
250
AIで政治は変わるのか? — 中高生と考えたAI時代の民主主義(東海高校サタデープログラム)
eitarosuda
0
360
5分でわかる Amazon Connect_20260608
hwangbyeonghun
0
170
そこにあるから地図ができる~位置を示す"モノ"を愉しむ~ - Interface 2026年6月号GPS特集オフ会 / interface_202606_GPS_offline
sakaik
1
180
Featured
See All Featured
Refactoring Trust on Your Teams (GOTO; Chicago 2020)
rmw
35
3.5k
Cheating the UX When There Is Nothing More to Optimize - PixelPioneers
stephaniewalter
287
14k
Automating Front-end Workflow
addyosmani
1370
210k
Exploring the relationship between traditional SERPs and Gen AI search
raygrieselhuber
PRO
2
4.1k
Exploring the Power of Turbo Streams & Action Cable | RailsConf2023
kevinliebholz
37
6.5k
The Web Performance Landscape in 2024 [PerfNow 2024]
tammyeverts
12
1.2k
What’s in a name? Adding method to the madness
productmarketing
PRO
24
4.1k
Designing Experiences People Love
moore
143
24k
ピンチをチャンスに:未来をつくるプロダクトロードマップ #pmconf2020
aki_iinuma
128
56k
Embracing the Ebb and Flow
colly
88
5.1k
The SEO Collaboration Effect
kristinabergwall1
1
500
Understanding Cognitive Biases in Performance Measurement
bluesmoon
32
2.9k
Transcript
文字数の話の続き Unicodeの楽しい話
自己紹介 t 名前: しゅん t Twitter: @shun_shobon / GitHub: @shun-shobo
t 学校: 長野高専 電子情報工学科 5F t 得意: Web Frontend / Web Frontend Ops / A11y なE t 研究: ホログラフィ・ヒューマンインタフェースなE t 趣味: PCゲーム・自作キーボーd t 一言: コンピュータと人との関わり方を模索しています
Kloud L Tで話したUnicode の話の続きになります
前回のあらすじ
Unicodeの目的 Unicodeは全ての文字にユニークなIDを降ること目的としている. このユニークなIDのことをUnicodeでは Code Point(コードポイント) と呼ぶ. チ → U+30C1 ゃ
→ U+3083 𠮟 → U+20B9F ! → U+FF01
Code Pointの符号化方法 このCode Pointを相手に送る際には,特定の方式によってバイナリにすることで送信される. これにはいくつかの方式がある. j UTF-32 … どのCode Pointも4Byteで表r
j UTF-16 ... 小さなCode Pointは2Byte,大きいのは4Byty j UTF-8 ... なるべく小さなByteになるように1〜4Byteで表す ※ものすごい雑な解説なので詳しくは調べてください
JSの.lengthの挙動 JSの.lengthは文字列の内部表現であるUTF-16の2byte配列の要素数を数えているだけ. 4byteで表現される「𠮟」があるため,11文字だけど要素数が12なので.lengthは12を返す.
StringのIteratorを使う Stringがネイティブに実装しているIteratorの処理はCode Point単位で処理される. IteratorベースのSpread演算子を使えばCode Point単位に文字列を分割できる!
1Code Point = 1文字 ではない
異体字セレクタという存在 Unicodeには漢字や絵文字のバリエーションを表す異体字セレクタというものがある. 例えば「葛」と「葛󠄀」の違いや,「 」と「 」の違いなど. つまりCode Pointの数と直感的な文字数が一致しない場合がある. これらは基本となる文字にCode Pointを定義して,その文字の後に異体字セレクタという別 のCode
Pointをつけることによって表現される.
結合文字列という存在 意味的にはこの2つは等しいため,検索などでこの2つを異なる扱いをしてしまうと,直感に 反する可能性がある. Unicodeには結合文字列という,複数のCode Pointを使って1文字を表現することがある. 例えば「が」は,「U+304C」と「U+304B, U+3099」の2通りの表し方がある.
絵文字の合字 合字とは「f」を2回重ねたときに「ff」のように2つがくっついた状態で表示されること. 一部の絵文字はこの合字を利用して複雑な絵文字を表現している場合がある. それぞれの絵文字の間にZero Width Joiner(U+200D)という不可視の文字を入れることに よってその絵文字は合成されているということを表す. ※Zero Width Joinerを使わないで合成される場合もあり(一部の国旗の絵文字など)
自然な区切りを表す書記素クラスタ これまで見てきたように,Code Point単位で見ても異体字セレクタや結合文字,合字などの 概念によってUnicodeにおける「1文字」というのはかなり表現するのが難しい. それに「1文字」という表現は非常に曖昧で,Byte単位なのか,Code Point単位なのか, 「いわゆる直感的な1文字」なのかが分かりづらい. そこで,「いわゆる直感的な1文字」をUnicodeでは書記素クラスタと呼んでいる. 書記素クラスタでの分割アルゴリズムはUnicodeの仕様として標準化されており,この仕様 に従えば誰でも直感的な1文字で文字列を分割することができる(とはいえアルゴリズムは非
常に複雑).
今回はこれらの知識を踏ま えて,実際のアプリ開発で 起こりそうな問題について 解説します
アプリ開発で起きる 問題色々
文字数制限が直感と異なる問題 入力フォームなどで文字数を制限してる場合,Code Point単位で文字数を数えていると直感 と異なる場合がある. 例えば「 」は7つのCode Point(U+1F3F4, U+E0067, U+E0062, U+E0077,
U+E006C, U+E0073, U+E007F)で表現されるが,これを20文字(20Code Point)で制限してる場合, 「 」はこの制限に引っかかることになる. ユーザー名などの場合,Code Pointよりも書記素クラスタで制限したほうが良いかもしれな い(もちろんちゃんと議論して合意を取ろう). 20文字で制限している → 「 」はアウト?
フォントが異なる問題 実は一部の絵文字は白黒の記号とCode Pointを共有している. 例えば「⁉」と「 」はどちらもU+2049である. どちらが表示されるかはフォントの優先順位などで決まる. きちんと指定する場合,Emoji Variation Selector(EVS)という異体字セレクタの一種を後ろ につけることで絵文字自体のバリエーションを選択できる.
フォントの優先順位やバリエーションをきちんとしないと,ユーザーが白黒の☎を打ったつ もりなのに全く別のものが表示されてしまうかもしれない. 「⁉」と「 」,どっちが表示されて欲しい?
絵文字の合字の環境依存問題 一部の絵文字の合字は環境依存の場合がある.例えばWhatsAppには「◯」5つをZWJで接続 することで作られた五輪のマークの絵文字があった(現在は削除済みの模様). 使用している端末,フォント,アプリケーションによって合字の絵文字はうまく表示されな い場合がある.ユーザーは特定の絵文字を入力したつもりでも,アプリ側ではうまく表示さ れない可能性もある. UnicodeではRGI(Recommended for General Interchange)と呼ばれる多プラットホームで
サポートされている絵文字を定義しているため,これに沿わない絵文字を弾くといった実装 をする必要が出てくるかもしれない. WhatsApp → それ以外 → ◯◯◯◯◯
結合文字列と 検索で生じる問題
合成文字列で生じる問題 「が(U+304C)」と「が(U+304B, U+3099)」はCode Point上の表記は違うが意味的にも視覚 的にも完全に同一である.そのため,検索等でこの2つを同一視しないと直感と異なる振る舞 いをすることになる. 普段合成文字列なんて使わねーよと思う人もいると思うが,実はmacOSのFinder上でファイ ルの作成や名前の変更をした場合,合成文字列に自動変換されている. 「が」と「が」は意味的・視覚的に等しい
合成文字列で生じる問題 どちらも同じ意味の文字列なのに,合成文字列の方はうまくNGチェックに引っかからなく なってしまう.
解決策
Unicode正規化
Unicode正規化 Unicode正規化は意味的に等しい文字列(文字)を統一させる処理のこと. 例えば全て合成済文字にしたり,全て結合文字列にしたりなど. NFC → 全て合成済文字にする(分解してから合成する) NFD → 全て結合文字列にする NFKC
→ NFCと似ているが,互換性のある文字も正規化する NFKD → NFDと似ているが,互換性のある文字も正規化する
Unicode正規化の例 JavaScriptではString.prototype.normalize()で正規化が可能. NFCで処理すると「が(U+304B, U+3099)」を「が(U+304C)」にすることができる.
Unicode正規化の例 NFKC/NFKDで処理すると視覚的に異なっても,意味的に同じならば正規化される(互換等価 という,逆にNFC/NFDは正準等価という). 検索等の実装では便利だが,視覚的な表現が変わってしまう場合があるので気をつける必要 がある(下の例以外にも,半角・全角が変わったりする).
Unicode正規化とやらを すれば良いんだな!
...本当に?
Unicode正規化に おける問題点
CJK互換漢字という存在 UnicodeではCJK(中国・日本・韓国)で使われる漢字を統一的に扱うCJK統合漢字という物が ある.これはUnicodeに漢字を収録する際に,「ほぼ同じ」漢字をCJK間で統合し,同一の Code Pointを振るために作られた. 一方,Unicodeに収録する際に出典元となった各国の標準規格との互換性を保つために,一 部の漢字はCJK統合漢字とは別に単体のCode Pointが割り当てられている. これをCJK互換漢字という. CJK統合漢字
→ 「羽」(U+7FBD) CJK互換漢字 → 「羽」(U+FA1E)
正準等価でも見た目が変わってしまう このCJK互換文字は,CJK統合漢字と視覚的に異なるのにも関わらず,Unicode正規化にお いて正準等価であるため,NFC/NFDで見た目が置き換わってしまうという問題がある. つまり検索等の都合で闇雲に正規化してしまうと一部の漢字の見た目が変わる可能性があ る. 「羽」(U+FA1E) ↓ NFC/NFDで正規化 ↓ 「羽」(U+7FBD)
解決策
異体字セレクタを使う 実はCJK互換文字は異体字セレクタを使用した2Code Pointで表現が可能(例外あるかも). 事前にCJK互換文字を異体字セレクタを使用した表現に変換しておけば,Unicode正規化に 巻き込まれずに済む. 「羽」(U+FA1E) ↓ 異体字セレクタを使った表現に変換 ↓ 「羽︀」(U+7FBD,
U+FE00) ↓ Unicode正規化 ↓ 「羽︀」(U+7FBD, U+FE00)
まとめ
Unicodeムズすぎ!