Slide 1

Slide 1 text

1 ソースコードのEUC-JP、 全部抜く⼤作戦 ⼤浦 優太郎 EC事業部 事業開発チーム BuriKaigi 2026 2026.01.10

Slide 2

Slide 2 text

2 ⾃⼰紹介 EC事業部 事業開発チーム 2022年 新卒⼊社 ⼤浦 優太郎 Oura Yutaro EC事業部でECサイト構築サービス「カラーミー ショップ byGMOペパボ」の開発‧運⽤に携わる。 1⽉から事業開発チームに参画。うなぎの浜松出 ⾝。 ● X : @yukyan_p ● Instagram: @yukyan_p

Slide 3

Slide 3 text

3 アジェンダ 1. はじめに 2. EUC-JP を倒すことの難しさ 3. 解決策 4. 実際の成果 5. まとめ

Slide 4

Slide 4 text

1. はじめに 4

Slide 5

Slide 5 text

はじめに 5 あけましておめでとうございます!

Slide 6

Slide 6 text

はじめに 6 2026年ですが プロダクト開発で EUC-JP と戦っている⼈いますか?

Slide 7

Slide 7 text

はじめに 7 私は戦っています!

Slide 8

Slide 8 text

はじめに 8

Slide 9

Slide 9 text

はじめに 9 Claude Code で編集していると

Slide 10

Slide 10 text

はじめに 10

Slide 11

Slide 11 text

はじめに 11 ⽂字化けしてしまう!

Slide 12

Slide 12 text

はじめに 12 ● Claude Code で編集した際に⽂字化け ● エディタの設定による⽂字化け ● GitHub でレビューする際に⽂字化け ところどころで、UTF-8 でないことによる開発体験の痛みがある UTF-8 前提のツールによる⽂字化け

Slide 13

Slide 13 text

2. EUC-JP を倒すことの難しさ 13

Slide 14

Slide 14 text

EUC-JP を倒すことの難しさ 14 Q. nkf -w で終わりなのでは?

Slide 15

Slide 15 text

EUC-JP を倒すことの難しさ 15 ● マルチバイト⽂字がコメントアウトだけであれば問題ないが... ● ソースコードの中にマルチバイトの⽂字列リテラルがあり、ロ ジックが、それがEUC-JPであることに依存している場合、最 終的な結果が変わってしまうことがある nkf -w で困ること

Slide 16

Slide 16 text

EUC-JP を倒すことの難しさ 16

Slide 17

Slide 17 text

EUC-JP を倒すことの難しさ 17

Slide 18

Slide 18 text

EUC-JP を倒すことの難しさ 18 Q. それならまずUTF-8で書いて mb_convert_encodingで UTF-8 から EUC-JP に 変換するようにしたら?

Slide 19

Slide 19 text

EUC-JP を倒すことの難しさ 19 ● UTF-8 は Unicode を使えるので111万⽂字ぐらい ● PHPがサポートしている EUC-JP は下記の⽂字集合の合成 US-ASCII + JIS X0201:1997(半⾓カナ) + JIS X0208:1990 + JIS X0212:1990 ⼤体 1万2千⽂字 UTF-8 -> EUC-JP で失われる情報がある https://www.php.net/manual/ja/mbstring.encodings.php

Slide 20

Slide 20 text

EUC-JP を倒すことの難しさ 20 ● UTF-8 でプログラム上で扱う⽂字列を記述すると、それを EUC-JP として扱おうとしたときに、失われる情報が出てくる (今後、⽂字を追加する場合などに) ● つまり、EUC-JP は EUC-JP のまま表現して取り扱いたい (EUC-JP に⼤きく依存した今回のケースにおいては) UTF-8 -> EUC-JP で失われる情報がある

Slide 21

Slide 21 text

3. 解決策 21

Slide 22

Slide 22 text

解決策 22 1. マルチバイト⽂字列リテラルを⼀つのファイルに追い出し、元々 直接⽂字列リテラルが書かれていた箇所はそれを参照するように する 2. 追い出し切ったら、コメントアウト以外は ASCII⽂字 ということ になる。 3. ASCII⽂字は EUC-JP と UTF-8 でバイト値が変わらないので⼀気に UTF-8 に変換できる i18n を参考にした解決策

Slide 23

Slide 23 text

解決策 23 1. マルチバイト⽂字列リテラルを⼀つのファイルに追い出し、元々 直接⽂字列リテラルが書かれていた箇所はそれを参照するように する 2. 追い出し切ったら、コメントアウト以外は ASCII⽂字 ということ になる。 3. ASCII⽂字は EUC-JP と UTF-8 でバイト値が変わらないので⼀気に UTF-8 に変換できる i18n を参考にした解決策

Slide 24

Slide 24 text

解決策 24

Slide 25

Slide 25 text

解決策 25 どうやって追い出すのか?

Slide 26

Slide 26 text

解決策 26 AIでスクリプトを書きます! Vibe Coding!

Slide 27

Slide 27 text

解決策 27 PHPトークナイザーを活用し、PHPソースコード内のコメ ントアウト以外のマルチバイト文字列をすべて EucjpStringLiterals.php に定数として定義し直すス クリプトを書いてください。 元々マルチバイト文字列箇所は、 EucjpStringLiterals.php に定義した定数を参照する 形に書き直してください。 プロンプト例

Slide 28

Slide 28 text

解決策 28 1. マルチバイト⽂字列リテラルを⼀つのファイルに追い出し、元々 直接⽂字列リテラルが書かれていた箇所はそれを参照するように する 2. 追い出し切ったら、コメントアウト以外は ASCII⽂字 ということ になる。 3. ASCII⽂字は EUC-JP と UTF-8 でバイト値が変わらないので⼀気に UTF-8 に変換できる i18n を参考にした解決策

Slide 29

Slide 29 text

解決策 29 どうやって「追い出し切ったか」を 判定するのか

Slide 30

Slide 30 text

解決策 30 PHPCodeSnifferを活⽤!

Slide 31

Slide 31 text

解決策 31 ● PHPコードの品質を管理するための静的解析ツール ● コードが PSR-12 などの標準ルールやに沿っているかを できる ● ルールは⾃分で作ることもできる。このルールを「ス ニフ」と呼ぶ PHPCodeSniffer とは

Slide 32

Slide 32 text

解決策 32 ● 「コメント以外にマルチバイト⽂字列がない」状態を 保証する仕組みが欲しい ● リポジトリに導⼊されていた PHPCodeSniffer を⽤い て、コメントアウト以外のマルチバイト⽂字列を検知 するスニフを作成 PHPCodeSniffer の活⽤⽅法

Slide 33

Slide 33 text

解決策 33 use PHP_CodeSniffer\Sniffs\Sniff; use PHP_CodeSniffer\Files\File; use PHP_CodeSniffer\Util\Tokens; /** * NonAsciiInCodeSniff * * コード内の非ASCII文字をチェックします(コメントは除外)。 */ class NonAsciiInCodeSniff implements Sniff {

Slide 34

Slide 34 text

解決策 34 … // PHPCSのTokens::$commentTokensを使用して、 // すべてのコメント関連トークンをスキップ if (isset($token['code']) && isset(Tokens::$commentTokens[$token['code']])) { continue; } … // 非ASCII文字が含まれていたら警告を出す if ($this->containsNonAscii($token['content'])) { $phpcsFile->addWarning( …

Slide 35

Slide 35 text

解決策 35 /** * 文字列に非ASCII文字が含まれているかをチェックします。 * * @param string $content チェック対象のコンテンツ * * @return bool */ private function containsNonAscii($content) { // 値がASCII文字の最大値である127 (0x7F) より大きいバイトをチェック return preg_match('/[^\x00-\x7F]/', $content) === 1; }

Slide 36

Slide 36 text

解決策 36 1. マルチバイト⽂字列リテラルを⼀つのファイルに追い出し、元々 直接⽂字列リテラルが書かれていた箇所はそれを参照するように する 2. 追い出し切ったら、コメントアウト以外は ASCII⽂字 ということ になる。 3. ASCII⽂字は EUC-JP と UTF-8 でバイト値が変わらないので⼀気 に UTF-8 に変換できる i18n を参考にした解決策

Slide 37

Slide 37 text

解決策 37 ● 追い出し先のファイルのみ EUC-JP を許容することになってしまう ● 追い出し先のファイルにすべてのマルチバイト⽂字列を置くので、メ ンテナンスコストが⾼そう ● ⼀旦追い出して開発体験を改善したあと、今後の運⽤⽅法を検討する ことになるだろう この⼿法の課題

Slide 38

Slide 38 text

4. 実際やってみたところ 38

Slide 39

Slide 39 text

実際やってみたところ 39 マルチバイト⽂字列の存在チェック

Slide 40

Slide 40 text

実際やってみたところ 40 変換スクリプトを実⾏

Slide 41

Slide 41 text

実際やってみたところ 41

Slide 42

Slide 42 text

はじめに 42 ソースコードからマルチバイト⽂字列を 追い出し切れた!! 🎉 あとは⼀気に変換するだけ!

Slide 43

Slide 43 text

6. まとめ 43

Slide 44

Slide 44 text

はじめに 44 ● EUC-JP を安全にソースコードから抜く⼿法を提⽰した ○ ⼀⽅で課題もある ● この⼿法は「EUC-JPをEUC-JPのまま取り扱いたい」場合の解決策 の⼀つとなる ● PHPCodeSniffer を使うことで、マルチバイト⽂字列リテラルが ソースコードにないことを保証する仕組みを作れる ● よりいい⽅法を模索していきたいので、情報お待ちしています! まとめ

Slide 45

Slide 45 text

45 Thank you!