🍡

カタカナをローマ字に変換するクラス

に公開

Packagistで探せばあるんだろうけど、ライブラリの依存関係とか考えると導入するよりも自作した方が良いかもと思ってGeminiに書いてもらったものを手直しした。

もっと短く書ける気もするけど動くので十分かなと思う。

<?php
declare(strict_types=1);

class Text
{
    /**
     * カタカナをローマ字に変換します。
     *
     * @param string $value カタカナの文字列
     * @return string ローマ字に変換された文字列
     */
    public static function convertKanaToRomaji(string $value): string
    {
        // カタカナをローマ字に変換するためのマッピング
        $map = [
            'ア' => 'a', 'イ' => 'i', 'ウ' => 'u', 'エ' => 'e', 'オ' => 'o',
            'カ' => 'ka', 'キ' => 'ki', 'ク' => 'ku', 'ケ' => 'ke', 'コ' => 'ko',
            'サ' => 'sa', 'シ' => 'shi', 'ス' => 'su', 'セ' => 'se', 'ソ' => 'so',
            'タ' => 'ta', 'チ' => 'chi', 'ツ' => 'tsu', 'テ' => 'te', 'ト' => 'to',
            'ナ' => 'na', 'ニ' => 'ni', 'ヌ' => 'nu', 'ネ' => 'ne', 'ノ' => 'no',
            'ハ' => 'ha', 'ヒ' => 'hi', 'フ' => 'fu', 'ヘ' => 'he', 'ホ' => 'ho',
            'マ' => 'ma', 'ミ' => 'mi', 'ム' => 'mu', 'メ' => 'me', 'モ' => 'mo',
            'ヤ' => 'ya', 'ユ' => 'yu', 'ヨ' => 'yo',
            'ラ' => 'ra', 'リ' => 'ri', 'ル' => 'ru', 'レ' => 're', 'ロ' => 'ro',
            'ワ' => 'wa', 'ヲ' => 'wo', 'ン' => 'n',
            'ガ' => 'ga', 'ギ' => 'gi', 'グ' => 'gu', 'ゲ' => 'ge', 'ゴ' => 'go',
            'ザ' => 'za', 'ジ' => 'ji', 'ズ' => 'zu', 'ゼ' => 'ze', 'ゾ' => 'zo',
            'ダ' => 'da', 'ヂ' => 'ji', 'ヅ' => 'zu', 'デ' => 'de', 'ド' => 'do',
            'バ' => 'ba', 'ビ' => 'bi', 'ブ' => 'bu', 'ベ' => 'be', 'ボ' => 'bo',
            'パ' => 'pa', 'ピ' => 'pi', 'プ' => 'pu', 'ペ' => 'pe', 'ポ' => 'po',
            'ャ' => 'ya', 'ュ' => 'yu', 'ョ' => 'yo', // 小さいヤユヨ
            'ー' => '', // 長音記号(単純な例です。前の文字の母音を繰り返すなどします)
            // その他の特殊なカタカナ
            'ヴ' => 'vu',
            'ァ' => 'a', 'ィ' => 'i', 'ゥ' => 'u', 'ェ' => 'e', 'ォ' => 'o',
            'ヮ' => 'wa', // 小さいワ
            'ヵ' => 'ka', // 小さいカ
            'ヶ' => 'ke', // 小さいケ
            'キャ' => 'kya', 'キュ' => 'kyu', 'キョ' => 'kyo',
            'ギャ' => 'gya', 'ギュ' => 'gyu', 'ギョ' => 'gyo',
            'シャ' => 'sha', 'シュ' => 'shu', 'ショ' => 'sho',
            'ジャ' => 'ja', 'ジュ' => 'ju', 'ジョ' => 'jo',
            'チャ' => 'cha', 'チュ' => 'chu', 'チョ' => 'cho',
            'ヂャ' => 'ja', 'ヂュ' => 'ju', 'ヂョ' => 'jo',
            'ヒャ' => 'hya', 'ヒュ' => 'hyu', 'ヒョ' => 'hyo',
            'ビャ' => 'bya', 'ビュ' => 'byu', 'ビョ' => 'byo',
            'ピャ' => 'pya', 'ピュ' => 'pyu', 'ピョ' => 'pyo',
            'ミャ' => 'mya', 'ミュ' => 'myu', 'ミョ' => 'myo',
            'リャ' => 'rya', 'リュ' => 'ryu', 'リョ' => 'ryo',
        ];
        $kogakiMoji = ['ァ', 'ィ', 'ゥ', 'ェ', 'ォ', 'ャ', 'ュ', 'ョ'];

        $romaji = '';
        $length = mb_strlen($value, 'UTF-8');
        for ($i = 0; $i < $length; $i++) {
            $char = mb_substr($value, $i, 1, 'UTF-8');
            if (in_array($char, $kogakiMoji)) {
                // 小書き文字は前の文字と結合するため、スキップ
                continue;
            }

            $charNext = mb_substr($value, $i + 1, 1, 'UTF-8');
            // 次の文字が小書き文字の場合
            if ($charNext && in_array($charNext, $kogakiMoji)) {
                $char = $char . $charNext; // 小書き文字を結合
            }

            $romaji .= $map[$char] ?? $char;
        }

        // 小さい「ッ」は後ろの文字を2回繰り返す
        $romaji = preg_replace_callback('/ッ(.)/', function ($matches) {
            return $matches[1] . $matches[1];
        }, $romaji);

        return $romaji;
    }
}

Discussion