てきとうなさいと べぇたばん

【PHP】grapheme関数に大文字・小文字の判定のロケールを追加することが可決されました

TOP > てきとうにこらむ > プログラミング日記 > 【PHP】grapheme関数に大文字・小文字の判定のロケールを追加することが可決されました

grapheme関数にロケールを追加するプルリクエスト

grapheme関数に$localeを追加しました

大文字・小文字を判定するのにロケールがないということで、ロケールを追加しました。

あらまし

grapheme関数に特に大文字・小文字の判定にロケールがないため、特定の地域の大文字・小文字判定ができなくなってるという問題が発生していました。例えば、トルコ語の「İ(U+0130)」を小文字と判定できなかったり、ドイツ語の「ß(U+1E9E)」の小文字である「ss」を小文字と判定できなかったりという問題がありました。

そこで、ロケールを追加しようということになったのですが、PHP Internalsのメーリングリストで情報交換をした結果とICUやUnicodeの仕様を見ると、様々なパラメーターを追加することができるということがわかりました。これをLocale Data Markup Language(LDML)といい、https://www.unicode.org/reports/tr35/ で参照することができます。

ここで、一つ重要なできごとがありました。なんとマッチの強さ(match strength)を指定することができる、ということがわかったのです。当初は$localeだけでなく$strengthもあったのですが、$localeだけでマッチの強さを指定することができることがわかりました。

では、このマッチの強さはどこに効いてくるのでしょうか。日本語だと、IVSといった異体字の判定に使えます。異体字はUnicode上は同じ文字だけれども、字形が違う文字のことを指します(例えば渡邉さんのなべの字なんかが有名ですね)。実は、grapheme関数では今まで異体字の違いを判定することができませんでした。

そこで、$localeにその構文を付け加えることができることを発見したのです。https://www.unicode.org/reports/tr35/tr35-collation.html#Combining_Rules によれば、ja_JP-u-ks-identic で異体字であるところまで調べることができます。ksがBCP47 Key、identicがBCP Valueとなっていて、これでマッチの強さをidenticalに持っていくことができるため、異体字の判定に使えるようになった、ということです。

<?php

$nabe = '邊';
$nabe_E0101 = "邊\u{E0101}";
var_dump(grapheme_levenshtein($nabe, $nabe_E0101)); // result is 0
var_dump(grapheme_levenshtein($nabe, $nabe_E0101, locale: "ja_JP-u-ks-identic")); // result is 1
var_dump(grapheme_strpos($nabe, $nabe_E0101)); // result is 0
var_dump(grapheme_strpos($nabe, $nabe_E0101, locale: "ja_JP-u-ks-identic")); // result is false

それが、このRFCにでてきたこれということになります。ちょうど、Unicode 16.0では日本の文字情報基盤を取り込んでいるため、一応ユースケースとして考えられると思います。

とはいえ、難しいのでは?

はい、難しいことは認めます。PHPユーザーから見て、Unicodeの仕様書を読んで漢字を判定してくださいというのは海の中から一枚の紙を見つけろというものでしょう。どうしてこうなったのかといえばもう、国際化の妥協の賜物ということにさせてください。

調べれば調べるほど、この方法しかなかった、という結論にしかたどり着くことができませんでした。複雑になることよりも、できないことをできるようにすることのほうが正しい、と感じたのです。

感想

このRFCの結論にたどり着くまでには、様々な悶着がありました。また、表音文字から名前を変えるべきだ、とする主張もありましたが、最終的には日本語の漢字ですらロケールには影響があるため、表音文字だけを尊重するようなことはできない、というふうに言い張ったのが効いたでしょうか。

このRFCのプルリクエストを読んで見れば、ぼくがいかに表音文字と表意文字との妥協点?を見つけるのに苦労してるかわかっていただけるかなと思います。https://github.com/php/php-src/pull/18792

ともあれ、PHP 8.5の機能追加はぼくサイドではマージされたら終わりです。ありがとうございました。

2025/08/12 20:58