2026年5月29日金曜日

ローマ字をダダ打ちして、AIに日本語に変換してもらう[完成]

昨日の投稿の続きであります。

突然ですが皆様、ローマ字のダダ打ち、つまり漢字変換などというまだるっこしい作業を完全に放棄し、ただひたすらにローマ字だけを打ち込み続けるという、昨日のアイデアの続きです。
AIの力で一気に日本語へ変換させる魔法のシステムを構築いたしました。
私が30年もの長きにわたり愛用し、もはや身体の一部と化している『秀丸エディタ』用のマクロであります。
もちろん、コードを書いたのは私ではなく、AIエディタのCursor先生という次第です。

今回採用した頭脳は、Gemini AIのモデルの中でも最速かつ最安を誇る「gemini-3.1-flash-lite」。
こいつを使って、秀丸マクロから直接GoogleのAPIを叩き、流し込んだローマ字を自然な日本語に変換してもらおう、という目論見です。
昨今流行りのローカルLLMなどという、PCのストレージを無駄に圧迫する得体の知れない代物をインストールする必要など一切ありません。我々のような一庶民が、一日数十万字も猛烈に入力するわけでもないのですから、APIの利用料金など、路傍の石にも等しい微々たるものであります。私は有料枠のAPIを設定しましたが、多分無料でも十分行けると思います。ただ混雑しているときは待たされるので、有料枠のAPIを使ったほう良い、私からのささやかなアドバイスです。普通の人だったら一月使って数十円のレベルです。

ウチのブログをご覧になっているような、DIY精神あふれる方々なら全く問題ないでしょう。
ご興味のある方は、ぜひこの秀丸エディタと以下のマクロの組み合わせを試してみてください。秀丸エディタを持っていないんで、サクラエディタでやりたい場合はどうすればいいか?とかそういう事はもうAIに聞いてくれ。

使い方は極めてシンプル。

  1. 取得したGemini API KeyをWindowsの環境変数(Gemini_API_KEY)に設定。
  2. 以下のコードを「romaji_convert.mac」とでも名付けて秀丸のマクロフォルダに放り込み、マクロ登録。
  3. あとは適当なショートカットキーに割り当てておけば、キー一発で呪文が発動します。

日夜、文章書きという名の終わらない作業と格闘している同好の士に、是非ともおすすめしたい一品なのでした。このままでも全然使えますが、あとは自分が使いやすいように勝手にコードを改変して使ってください。
さあ、今日もひたすらキーボードを叩くとしましょう。

romaji_convert.mac
// -------------------------------------------------------------
// ローマ字一括変換マクロ (Gemini API 直接呼び出し)
// 対象: 秀丸エディタ Ver 9.40 以上 / Windows 10 以上
//
// 環境変数 Gemini_API_KEY に API キーを設定して使用します。
// 参考: GoogleGeminiに問い合わせ.mac (秀まるお氏)
// -------------------------------------------------------------

$api_key = getenv("Gemini_API_KEY");
$model   = "gemini-3.1-flash-lite";

if ($api_key == "") {
    message "環境変数 Gemini_API_KEY が設定されていません。\n秀丸を再起動するか、システムの環境変数設定を確認してください。";
    endmacro;
}

if (!selecting) {
    selectline;
}

$romaji = getselectedtext();
if ($romaji == "") {
    message "変換対象が選択されていません。";
    endmacro;
}

delete;

#http = createobject("Msxml2.XMLHTTP");
if (#http == 0) {
    #http = createobject("Microsoft.XMLHTTP");
    if (#http == 0) {
        message "XMLHTTPオブジェクトの生成に失敗しました。";
        insert $romaji;
        endmacro;
    }
}

$url = "https://generativelanguage.googleapis.com/v1beta/models/" + $model + ":generateContent?key=" + $api_key;

callmethod #http, "open", "POST", $url, false;
callmethod #http, "setRequestHeader", "Content-Type", "application/json";

jsmode "WebView2";
js {
    try {
        let romaji = hidemaru.getVar("$romaji");
        let obj = {
            system_instruction: {
                parts: [{
                    text: "あなたはローマ字を日本語に変換する専用ツールです。入力されたローマ字(ヘボン式/訓令式)を、音に忠実に自然な漢字かな交じり文に変換してください。助詞・語尾・接続詞は変えないこと。変換後のテキストのみ出力し、説明・挨拶・補足は一切出力しないこと。"
                }]
            },
            contents: [{
                parts: [{ text: romaji.trim() }]
            }],
            generationConfig: {
                temperature: 0.1,
                maxOutputTokens: 1024
            }
        };
        hidemaru.setVar("$post", JSON.stringify(obj));
    } catch (e) {
        message("JSON生成エラー:\n" + e.message);
        hidemaru.setVar("$post", "");
    }
}

if ($post == "") {
    insert $romaji;
    endmacro;
}

callmethod #http, "send", $post;
if (!getresultex(10)) {
    message "API送信に失敗しました。";
    insert $romaji;
    endmacro;
}

$resp = getpropstr(#http, "responseText");
#code = getpropnum(#http, "status");
if (#code != 200) {
    message "APIエラー (code=" + str(#code) + ")\n" + $resp;
    insert $romaji;
    endmacro;
}

jsmode "WebView2";
js {
    try {
        let obj = JSON.parse(hidemaru.getVar("$resp"));
        let answer = obj.candidates[0].content.parts[0].text.trim();
        hidemaru.setVar("$answer", answer);
    } catch (e) {
        message("JSON解析エラー:\n" + e.message);
        hidemaru.setVar("$answer", "");
    }
}

if ($answer == "") {
    insert $romaji;
    endmacro;
}

insert $answer;

endmacro;