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
文字とはなにか - PHPの文字コード処理について -
Search
てきめん tekimen
PRO
January 12, 2024
2.4k
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
文字とはなにか - PHPの文字コード処理について -
PHPカンファレンス北海道2024
てきめん tekimen
PRO
January 12, 2024
More Decks by てきめん tekimen
See All by てきめん tekimen
フロントエンドとバックエンドで「1文字」を揃えよう
youkidearitai
PRO
0
840
ChatGPTを使ってRaspberry Pi Picoの処理系を書いた
youkidearitai
PRO
0
97
PHP Internals わいわい #3 PIEを使ってみよう
youkidearitai
PRO
0
73
grapheme_strrev関数が採択されました(あと雑感)
youkidearitai
PRO
1
350
Limit of code point for grapheme cluster in programming language side.
youkidearitai
PRO
0
95
Unicodeどうしてる? PHPから見たUnicode対応と他言語での対応についてのお伺い
youkidearitai
PRO
2
3.7k
PHP 8.5の裏話
youkidearitai
PRO
0
160
CJK and Unicode From a PHP Committer
youkidearitai
PRO
0
390
PHP Internals わいわい #3 mb_*関数を作ってみよう
youkidearitai
PRO
0
170
Featured
See All Featured
The Cost Of JavaScript in 2023
addyosmani
55
10k
Principles of Awesome APIs and How to Build Them.
keavy
128
18k
Ethics towards AI in product and experience design
skipperchong
2
340
SEO in 2025: How to Prepare for the Future of Search
ipullrank
3
3.7k
My Coaching Mixtape
mlcsv
0
190
Designing for Timeless Needs
cassininazir
1
430
State of Search Keynote: SEO is Dead Long Live SEO
ryanjones
0
240
Dominate Local Search Results - an insider guide to GBP, reviews, and Local SEO
greggifford
PRO
0
250
The Success of Rails: Ensuring Growth for the Next 100 Years
eileencodes
47
8.2k
Code Review Best Practice
trishagee
74
20k
Stop Working from a Prison Cell
hatefulcrawdad
274
21k
Have SEOs Ruined the Internet? - User Awareness of SEO in 2025
akashhashmi
0
410
Transcript
文字とはなにか - PHPの文字コード処理について -
自己紹介 てきめん • https://tekitoh-memdhoi.info • X: @youkidearitai • https://github.com/youkideari tai
• サイボウズ株式会社の正社員 オレ
コンピューターで文字を表すの基本 • コンピューターは数値しか扱えません • そこで、とある数値をAなどと紐づけていきました • それが文字コードです • 文字コードに照らし合わせて文字を表示してくれる のがフォントですね
Unicodeがよい • ざっくり言ってしまうとUnicodeはいいぞ • 文字化けから開放してくれたぞ!ってなる • 絵文字も使えるぞ 🎉🎉
Unicodeって何? • 世界中のすべての文字を収録しようというもの – ISO/IEC 10646 という工業規格があって、Unicodeと等 しくなるようになっています • JIS
X 0221が現在の日本の工業規格(JIS)での規格です – Unicodeのバージョンに伴って、収録されていく文字が 増えています
UnicodeとJIS X 0221との関係 Unicode ISO/IEC 10646 JIS X 0221 同期
日本版 ※各仕様書を読んだらこの図になりましたが「プログラマのための文字コード技術入 門」もほぼ同じ図になっていました
Unicodeのバージョンについて • 現在最新版は15.1です。 • 2024年ではUnicode 16.0に むけて作業が進められていま す – http://blog.unicode.org/
2023/11/utc-177-highlig hts.html
絵文字の存在 • バージョンなんてどうでも良くね?と思いがちです が、実はそうもいかないのです • みなさんはこんなことはありませんか? – 私の推しマークは です、時々違う方がいます。気をつ 🩵
けてくださいなどと呼びかけているアイドルさん – 🙇 と♂♀が分割してた
スマートフォンは絵文字を入力しやすい • スマートフォンならば簡単に絵文字を選んで入力す ることができます • 新しいスマートフォンほど新しい絵文字を入力しやす くなります • その一方で、大切に長くスマートフォンを使っている 人もいます
その結果起こること • Unicodeのバージョンに気を使う必要があります – 古いスマートフォンでは絵文字が見えなかったり、分か れて見えたりします – 新しいスマートフォンでは当たり前のように新しい Unicodeのバージョンの絵文字が使えます
🩵はどうでしょうか • https://emojipedia.org/ja/%E6%B0%B4%E8% 89%B2%E3%81%AE%E3%83%8F%E3%83%BC %E3%83%88 • どうやらUnicode 15.0で入ったようです – 2023年現在の最新バージョンは15.1です
– かなり新しい絵文字です – 古いスマートフォンでは見えないでしょうね…
🙇と♂♀が分割してた • このケースの場合、土下座をしている人と♂や♀の マークが分割して見えることがあります • 対応している機種であれば、「 」、「 」と表示され 🙇♂️ 🙇♀️
ます • いきなりですがPHPでmb_strlenしてみましょう
mb_strlenした結果 • 1文字のハズなのに、4とでましたね – つまり、4つのコードポイントがあるということになります – mb_str_splitもしてみましょう
mb_str_splitした結果 このように、4つのコードポイントに分かれていること がわかりますし、 と♂が別れています 🙇
コードポイントとは • UnicodeでいうコードポイントとはU+1234などと 記す符号位置で、16進数で表します • mbstringではこの単位で測っていきます
コードポイントは? 2コードポイント目がU+200D、4コードポイント目 がU+FE0Fです
それぞれの意味 • U+200Dはゼロ幅接合子などと呼ばれてお り、Zero Width Joinerの略でZWJと言います • U+FE0Fは異体字セレクタと言い、U+FE00から U+FE0Fまでの範囲16文字を使って絵文字のバリ エーションを表現します
• https://www.unicode.org/glossary/#variation _selector
mbstringでのUnicodeの対応方針 • mbstringでは、(大体が)内部でUTF-32として扱 い、コードポイントごとに計算しています – 近頃ここで内部でUTF-8を使っている箇所があ り、統一されていないことを突っ込まれました。
異体字セレクタについて • 漢字でも使われています – Ideographic Variation Sequence(漢字(表意文字)異体 字シーケンス、IVS)と呼ばれています – 範囲はU+E0100からU+E01EFです
– 組み合わせを定義するのがIVS、字形を定義するデータ ベースをIVD(Ideographic Variation Database)といいま す – https://www.unicode.org/reports/tr37/
漢字の異体字セレクタについて • 例えば「邉」 CJK UNIFIED IDEOGRAPH-9089 – https://glyphwiki.org/wiki/u908a-ue0104 – https://747.github.io/vsselector/#!/ja/9089
– 邉 邉󠄀 邉󠄁 邉󠄂 邉󠄃 邉󠄄 邉󠄅 邉󠄆 邉󠄈 邉󠄉 邉󠄊 邉󠄋 邉󠄌 邉󠄍 邉󠄎 … • 游ゴシック体で表示させました • すべて違う異体字です • 同じ漢字に見えるのもあれば違うのもありますね
絵文字に戻っておさらいしましょう
mb_str_splitした結果 見えないほうはそのようにちがうわけですね ゼロ幅接合子 (ZWJ) U+200D (絵文字の)異体字セレクタ U+FE0F
どうすれば1文字として測れますか?
ICUというライブラリを使います • Grapheme cluster(グラフィム、書記素クラスター)単位で測れば 良い – それを格納しているのがICU – 結局データベースから測らないといけないのです •
PHPではintl拡張に入っています – --enable-intlとしてコンパイルしましょう – grapheme_strlenを使えば測れます • https://www.php.net/grapheme_strlen
PCRE(preg系関数)も使えます • PCREも書記素クラス ター単位での検出がで きます • \Xを使用します • https://www.pcre.or g/original/doc/html/
pcrepattern.html
grapheme_strlenした結果 このようにして、書記素クラスターを正しく数えるこ とができるわけですね
濁音・半濁音の場合
アイヌ語の を考えてみましょう ト゚ • ト゚ はアイヌ語のカタカナだそうです – トゥというみたいですね – Unicodeには単独のコードポイントは存在しません
• アイヌ語の濁音・半濁音はすべてこの様になっています • したがって、「ト」と「゚」の組み合わせで表現します – U+30C8とU+309Aの組み合わせです – 本当は単独のコードポイントにしたかったそうですね (ユニコード戦記を参照ください)(JIS X 0213では1面5区94点)
を正確に測る ト゚ • このように、grapheme_strlenを使って書記素クラ スターとして測ることになります。
本来の濁音と半濁音 • JIS X 0201ではガのように文字と濁音が別々(いわゆる半角カ ナ) • JIS X 0208ではガのように、独立した文字も収録された
• Unicodeでは独立した文字も別にできたりする – ガが果たしてU+30ACなのか、U+30ABとU+3099の両方なのかが一見 するとわからない – それを統一するのが「正規化」と呼ばれる
正規化の方法 • 正規化方式D(NFD) – $ sapi/cli/php -r 'var_dump(Normalizer::normalize("ガ", Normalizer::NFD));' string(6)
"ガ" # カと濁音が分割されている • 正規化方式C(NFC) – $ sapi/cli/php -r 'var_dump(Normalizer::normalize("ガ", Normalizer::NFC));' string(3) "ガ" • 正規化方式KD(NFKD) – $ sapi/cli/php -r 'var_dump(Normalizer::normalize("ガ", Normalizer::NFKD));' string(6) "ガ" # カと濁音が分割されている • 正規化方式KC(NFKC) – $ sapi/cli/php -r 'var_dump(Normalizer::normalize("ガ", Normalizer::NFKC));' string(3) "ガ" • PHPではintlの Normalizerクラスを使 います • 正規化方式も4種あるの でその時適切な正規化 方式を選択する必要が あります
正規化で戸惑う例 • 例えばハングルの「アニョハセ ヨ」(こんにちは)を正規化 D(NFD)をすると、ハングルの 音節がバラバラに分解されて しまいます(ちゃんと表示できる 場合もありますが) • 参考:
https://www.unicode.org/c harts/normalization/ \
まとめ • Unicodeにはバージョンがあることがわかりました • バージョンによって絵文字が表示されないことがわかりました • ZWJ、異体字セレクタなどで必ずしも1コードポイントに収まらないことがわかりました • 濁音・半濁音は色々な方法の組み合わせがあることがわかりました •
PHPのUnicodeの対応具合がわかりました – mbstringでは1コードポイントごと、intlとPCREでは書記素クラスターとして測れる • 正規化は複雑すぎる、触れないでおければ幸せ • Unicodeは知ることが多いことがわかり、わからないことがわかりました – たとえば、不正なバイトシーケンスとか喋ってないですね? – あなたが知っていることがあったら、教えてください!
提案 • PHPのGrapheme関数には、文字列の処理関数が少ないように見 えます • 少なくとも、mb_str_split相当の書記素クラスターごとにarrayで返 却できるとarray関数で処理できてよいのではと思いますがどうで しょう? • つまり、grapheme_str_splitが必要なのではないかということです
– 絵文字などを「一文字」として配列として分割するというものです – ポジティブなフィードバックをいただければRFCとPoCを作ろうかと思いま す
参照 • http://www.unicode.org/L2/L2016/16181-gender-zwj-sequences.pdf • https://ja.wikipedia.org/wiki/%E3%82%BC%E3%83%AD%E5%B9%85%E6%8E%A5 %E5%90%88%E5%AD%90 • https://www.unicode.org/glossary/#variation_selector • https://www.unicode.org/glossary/#ideographic_variation_sequence
• https://www.unicode.org/reports/tr37/ • https://ja.wikipedia.org/wiki/%E7%95%B0%E4%BD%93%E5%AD%97%E3%82%B B%E3%83%AC%E3%82%AF%E3%82%BF#%E7%A8%AE%E9%A1%9E • https://emojipedia.org/ja/emoji-15.0 • https://747.github.io/vsselector/#!/ja/9089 • https://glyphwiki.org/wiki/u908a-ue0104 • https://www.php.net/grapheme_strlen