はじまり
「虫眼鏡みたいなのかざしたら、レンズの下の文章が翻訳されるツール、パソコンで作って!」
妻が唐突にまたなにか言い出しました。
わぁわぁと仕様や必要性を熱弁していた気もしますが、正直私はあまり聞いていませんでした。
返事はこうでした。
「ィヤッ」
妻は「せっしやくわ~~~ん!」と謎の言葉(呪詛?)を残してその場を後にしました。
私が極度の面倒くさがりで、食い下がっても無駄な事を知っているのです。
それが一年近く前の話。
最近AIでアプリを作ることに楽しさを覚えた私が、妻に「何かアイデアない?」と訊くと、再度その翻訳アプリの事を持ち出しました。
正直PCアプリは気乗りしません。
気乗りしない理由
私は普段Webアプリを作っています。ブラウザという共通基盤の上で動くものは気楽です。HTMLとCSSとJavaScript(あるいはその仲間たち)を書いて、デプロイすれば全員に届く。
一方、Windowsデスクトップアプリはどうでしょうか。
- WPF。令和にWPF。XAMLを書くのか。私はXAMLが好きではありません
- 透明なウィンドウを常に最前面に表示。言葉にすると簡単そうですが、Win32 APIの沼の匂いがします
- 画面をキャプチャしてOCR。これはもう明らかに面倒くさい
- 配信とアップデート。Webならデプロイ一発で全ユーザーに届きますが、デスクトップアプリは……
つまり、技術的に「できない」わけではないが、「楽しくなさそう」というのが正直な感想でした。
ましてやWPFです。WPF。時代はBlazorかMAUIかと言われている中で、WPF。
(結果的にWPFが最適解だったのですが、それは後の話です)
ただ、自分から尋ねた手前、詳細を(今度はちゃんと)聞いてみることにしました。
クライアントの要件定義
「ゲーム本編は日本語化されててもリリースノートが英語だったり、そもそもやりたいゲームが日本語対応してなかったりするんだよね~。
日本語化パッチもないとかさ。ゲーム画面だとコピペもできないし、今私がどうやってるか知ってる?
SSが入るフォルダと、Google画像翻訳のページ開いたブラウザをサブモニタに置いてといて、SS撮ってはブラウザに投げてるんだよ。
超~めんどうなんだよね~。スマホならGoogleレンズで一発でできることが、PCでできないわけないじゃん! なのにそんなアプリ見つからないの!
AIに聞いてやってみたらSS撮ってOCR加工してDeepLとかの翻訳サイトに投げるとこを自動化とか、結局ブラウザ頼りだったり別窓開くとかだったりで全然実用的じゃなかったし……。
虫眼鏡みたいなツールで、『あ、ここ翻訳したい』って時にドラッグしたら、そのレンズの中をパパッとその場で翻訳するようなツールがなぜないのか!!」
そう、妻はゲーマーなのです。
妻はこう続けました。
「セリフが出る場所が固定のゲームだったら、そこに虫眼鏡固定して置いておけば自動で翻訳し続けてくれたら最高っすね。
これで日本語化されてないゲームも遊べるようになる!!」
ははーん……。
私はおそるおそる言いました。
「それはツールを動かしたり、下の画像が変更されるたびに翻訳を走らせるってこと……?
すごい事考えるねきみ……」
「エヘッ」
妻は何故か照れていましたが、決して褒めて言ったわけではありません。
妻が書いてくれた仕様書(と呼んでいいのか)がこちらです。
技術的な壁
話を聞いて、やりたいことは理解しました。技術的に分解するとこうなります。
- 画面キャプチャ — ウィンドウの下にある画面を撮る
- OCR — 画像からテキストを読み取る
- 翻訳 — 読み取ったテキストを翻訳する
- オーバーレイ表示 — 翻訳結果をその場に表示する
1と2は実はそこまで難しくありません。WindowsにはWindows.Graphics.Captureという画面キャプチャAPIがあり、Windows.Media.OcrというOCRエンジンも標準搭載されています。どちらもローカルで動作し、完全無料です。
問題は3の翻訳です。
ブラウザでGoogle翻訳を使うぶんにはタダですが、あれはGoogleがブラウザユーザー向けに無料提供しているだけです。アプリからプログラム経由で翻訳APIを叩くと、1文字ごとにお金がかかります。しかもGoogle Translation APIの料金は100万文字あたり$20。ゲームのテキストを片っ端から翻訳していたら、あっという間にとんでもない請求が来ます。
これを妻に説明したところ——
妻「はぁ~!? ブラウザからなら翻訳無料なのに、アプリからだと毎回お金とられるってこと!? 理不尽!!
家のネット回線契約だとデータ量無制限なのに、モバイル回線だとバカ高くなるくらい理不尽~~~!!」
そうはいうがな……。
転機
ここで「じゃあ無理だね」となってもおかしくなかったのですが、私はある可能性に気づきました。
Gemini 2.5 Flash-Lite。GoogleのAIモデルです。
このモデル、翻訳用途に使うと従来のGoogle Translation APIより約6倍安い。しかもAIなので単語ごとのカタコト翻訳ではなく、文脈を理解した自然な翻訳ができます。1回の翻訳リクエストにかかるコストを計算してみると——安い。とても安い。
さらに考えてみると:
- OCRはローカルで完全無料(Windows標準機能)
- 同じテキストが何度も出る(ゲームのUIテキストなど)。キャッシュすればAPI呼び出しを大幅に減らせる
- ユーザー間でキャッシュを共有すれば、同じゲームを遊ぶ人同士で翻訳結果を使い回せる
- 課金はSteam DLCに任せれば、決済システムを自分で作る必要がない
つまりこういうアーキテクチャが成り立ちます:
[画面キャプチャ] → [ローカルOCR(無料)] → [キャッシュ確認]
↓ ミス
[Gemini API(激安)]
↓
[キャッシュ保存]
コストの大部分を占める翻訳APIが激安で、OCRは無料で、キャッシュでAPI呼び出しをさらに半減できるなら——これ、ユーザーが手頃な価格で使えるサービスにできるのでは?
「できる気がしてきたから、とりあえずやってみるね」
私は妻に伝えました。
その数時間後、妻が言いました。
「『このジャンルのおすすめゲーム教えて』って訊くたびに全部のAIが必ずあげてきたタイトルあってさ~。
日本語化されてないし、日本語化パッチもないから諦めてたけど、ちょうどセールだったから買ったわ!!
プレイできるかはきみにかかってるからよろしくね~~~!!」
私「(白目)」
判断が早すぎます👺
しかしこれで後にはひけなくなりました。
実装
技術スタック
┌──────────────────────────────────────────────┐
│ クライアント (C# / WPF / .NET 7.0) │
│ │
│ 画面キャプチャ: Windows.Graphics.Capture │
│ OCR: Windows.Media.Ocr (ローカル) │
│ Steam統合: Steamworks.NET │
└──────────────────┬───────────────────────────┘
│ HTTPS + HMAC-SHA256
↓
┌──────────────────────────────────────────────┐
│ バックエンド (Cloud Functions / Python) │
│ │
│ 翻訳: Gemini 2.5 Flash-Lite API │
│ キャッシュ: Firestore │
└──────────────────────────────────────────────┘
結局WPFを選びました。「透明なウィンドウを常に最前面に表示する」という要件には、AllowsTransparency="True" と Topmost="True" を組み合わせるWPFが最も素直だったのです。令和にWPFと言ったな。撤回します。WPFはこの用途において最適解でした。
透過ウィンドウ
「虫眼鏡」を実現するにあたって、最初にぶつかった問題がこれでした。
- ウィンドウの中央は透過して、下のゲーム画面が見える
- でも透過部分をクリックしたら、ゲーム側にクリックが通る(クリックスルー)
- ヘッダーやボタンはクリックできる
WPFの IsHitTestVisible="False" を使い分けて実現しました。最小化するとドラッグハンドルだけが残り、ゲームの邪魔になりません。
OCR
Windows.Media.Ocr はWindowsに標準搭載されているOCRエンジンで、ローカルで動作します。ネットワーク不要で数十msで結果が返ります。
ただし弱点もあります:
- Windowsの言語パックをインストールしないと認識できない言語がある
- 手書きフォントやデザインフォントに弱い
後者は妻から「読めてないよこれ。何この文字化け」とフィードバックをいただき、高精度モードを追加することになりました。キャプチャした画像をそのままGemini APIに投げて、OCRと翻訳を一発でやらせます。OCR言語パックも不要。手書きもいける。ただしクレジット消費は10倍です。
2階層キャッシュ
コスト削減の要です。
翻訳リクエスト
↓
[L1: ローカルキャッシュ] → ヒット → 即返却、クレジット消費なし
↓ ミス
[L2: Firestoreキャッシュ] → ヒット → 返却、クレジット消費なし
↓ ミス
[Gemini API] → 翻訳 → L1 + L2に保存
同じゲームをプレイするユーザーは同じテキストに遭遇します。L2(サーバー)キャッシュにより、あるユーザーの翻訳結果が別のユーザーにも使われます。ヒット率は50-70%。1,000クレジット買ったユーザーが実際にAPIを叩くのは300〜500回程度です。
Steamでの配信
課金システムをSteamのゲーム内決済に委ねることで、自前の決済システムを作る必要がなくなりました。
| パック | 翻訳回数 | 価格 |
|---|---|---|
| Pack S | 1,000回 | ¥100 |
| Pack M | 5,000回 | ¥500 |
| Pack L | 20,000回 | ¥1,500 |
Steam手数料30%は大きいですが、決済・配信・アップデートのインフラを個人で構築するコストを考えれば合理的です。
クライアントによる受け入れテスト
開発中、妻による非公式QAテストが定期的に実施されました。テスト項目は事前に合意されたものではなく、リアルタイムに発生します。
| テストケース | 結果 | クライアントのフィードバック |
|---|---|---|
| 英語RPGのダイアログ翻訳 | PASS | 「お、読める」 |
| フォントサイズ+3 | PASS | 「これくらいがいい」 |
| 3時間連続使用 | PASS | 「落ちないね」 |
| Alt+Tab時の動作 | FAIL → 修正 | 「消えたんだけど。どこいった」 |
| 中国語ゲームの翻訳 | PASS | 「中国語もいけるんだ」 |
| 自動翻訳で画面移動 | FAIL → 修正 | 「まだ前の画面の翻訳出てる。遅い」 |
| ウィンドウ位置の復元 | FAIL → 修正 | 「昨日と同じ位置にしたのに覚えてない」 |
| 手書きフォントのゲーム | FAIL → 高精度モード追加 | 「読めてないよこれ。何この文字化け」 |
| 翻訳結果がはみ出る | FAIL → 修正 | 「文字が枠の外に出てる」 |
| 戦闘中にオーバーレイが邪魔 | → 最小化機能追加 | 「邪魔。隠せるようにして」 |
特に「消えたんだけど。どこいった」は再現が難しく、Graphics Capture APIのセッション管理周りの問題でした。デバッグに丸2日かかりました。
プロのQAエンジニアと比較した、クライアント(妻)のバグレポートの特徴:
| 項目 | プロQA | 妻 |
|---|---|---|
| 再現手順 | 詳細 | 「なんかおかしい」 |
| 期待動作 | 明記 | 「普通に動いてほしい」 |
| 環境情報 | OS/バージョン付き | 「このパソコン」 |
| 優先度 | P0-P3 | 「今すぐ直して」か「まあいいけど」 |
| スクリーンショット | 添付 | 「ほら、見て」(画面を指差す) |
しかし、テストの網羅性は恐ろしく高い。プロのQAが「正常系」「異常系」と分類して考えるところを、クライアントは「ゲームを普通に遊ぶ」だけで自然にエッジケースを踏み抜いていきます。
「3時間ぶっ通しで使ってメモリリークを発見」は、テスト計画書では書けてもなかなか実行しないテストです。
命名
最後に妻は謎のこだわりを見せました。
「ルーペは拡大鏡だし、正しくはレンズなんだろうけど、日本語のツール名は『翻訳ルーペ』じゃなきゃだめだから!!
テケテケン♪ ほんやくる~~ぺ~~~、だから!!!
あ、英語名はTranslate LensでもTranslate Glassでもなんでもいいです」
こうして 翻訳ルーペ(Translation Lens) が誕生しました。
リンク
- Steam: https://store.steampowered.com/app/3652400/Translation_Lens/
- 対応言語: 英語、日本語、中国語(簡体字/繁体字)、韓国語、ドイツ語、フランス語、スペイン語
初回20回分の無料翻訳が付いています。ゲームのテキストはコピペできないので翻訳サイトに貼れない——そんな悩みをお持ちの方、ぜひお試しください。
なお、AIで5分で書いた記事ですが、妻のチェックに20分かかりました。
妻「半分ぐらいは架空の妻ですね」
