英語の教育コンテンツを日本語で学びたい。テキストは翻訳すればいい。でも、スライド画像の中に書かれた英語テキストはどうするのか。
これ、意外と誰も解決していない問題なんですよね。
きっかけ — Anthropic Academyを日本語で読みたかった
Anthropic Academyに「Claude Code in Action」というコースがある。Claude Codeの使い方を体系的に学べる、全20レッスンの無料コースです。
ただし、全編英語。
テキスト部分はClaude Codeに頼んで日本語に翻訳してローカル保存すればいい。実際やってみたら、chrome-devtools MCPでブラウザからコンテンツを取得→翻訳→Markdown保存、という流れで21ファイル分がサクッと完了しました。
問題はここからです。コース内には16枚のスライド画像がある。フロー図、シーケンス図、コード付き解説図。これらの画像内テキストは全部英語のまま。
「画像の中の英語も日本語にしたい」
そう思ったのが、この検証の始まりでした。
既存の選択肢を考える
画像内テキストの翻訳って、実はローカライゼーション業界でもまだ発展途上の領域です。
主要な翻訳管理ツール(Crowdin、Transifex)は画像内テキスト翻訳に未対応。対応しているSmartcatは月額$669〜。ImageTranslate.aiのようなOCR+インペインティング方式もあるけど、ラスター画像の加工なので品質に限界がある。
僕が検討した選択肢は4つ。
| 手法 | アプローチ | 予想される品質 |
|---|---|---|
| OCR+インペインティング | AIが画像内テキストを認識→消去→翻訳テキストを書き込み | ラスター劣化あり |
| Pencil MCP | デザインツールで画像を再作成 | UIモック向き、図表は苦手 |
| mermaid.js / D2 | テキスト記法で図を定義→PNG出力 | 構造図向き、デザイン制御は限定的 |
| HTML+SVG+Playwright | HTMLで図を再構築→ブラウザでPNG出力 | 完全制御、ただし初回工数が高い |
結論を先に言うと、HTML+SVGが圧倒的に最適でした。でも、そこに至るまでの試行錯誤が面白かったので、順を追って書きます。
検証1: Pencil MCPで再作成してみた
最初に試したのはPencil MCP。自然言語でUIデザインを生成できるツールで、以前のジャーナルでも紹介しました。
フロー図の基本レイアウトは作れた。色もそこそこ合わせられる。でも、矢印やフローの接続線でつまずきました。SVGパスを手書きする必要があり、元画像の「反復」ループ矢印のような曲線は再現しづらい。
「方向性は合ってるけど、このツールでは限界がある」
開始15分で判断して、次の手法に切り替えました。
検証2: HTML+SVGで「フルリビルド」する
同じフロー図を今度はHTML+SVGで書き直す。CSSでレイアウトを組み、SVGで矢印を描く。
最初のバージョンは30分ほどで形になりました。矢印も曲線も自由に描ける。でも、ここからが長かった。
色が全然違う
「なんか色味が違うな」と思って原画と並べてみると、背景色からカードの色まで全部ずれていました。
そこでPillow(Pythonの画像処理ライブラリ)で原画のピクセルカラーを抽出するアプローチに切り替えました。
from PIL import Image
img = Image.open('original.png')
r, g, b = img.getpixel((x, y))[:3]
hex_color = f'#{r:02x}{g:02x}{b:02x}'
結果がこれです。
| 要素 | 原画カラー | 最初の設定 | 差 |
|---|---|---|---|
| 背景 | #f5f7f3(緑がかった白) | #f5f0eb(暖色系) | 色相が真逆 |
| Step1 | #e2d3b0(明るいベージュ) | #d4c5a9(やや暗い) | 彩度不足 |
| Step2 | #cc946f(ブラウン) | #b89b71(やや薄い) | 明度ずれ |
| 言語モデル背景 | #ffffff(白) | #ffddd0(ピンク) | 完全に別の色 |
人間の目で「だいたい合ってる」と思った色が、ピクセル単位では全然違う。特に「白背景がピンクになっていた」のは衝撃でした。ピクセルカラー抽出は必須工程だと学びました。
線の位置、1本ずつ指摘が入る
色を合わせた後も、細かい修正が延々と続きました。
– 「T字矢印の元が言語モデルのカードとつながっていない」
– 「反復の矢印は辺の角じゃなくて中央から」
– 「反復のテキストがアシスタントの枠の外にある」
– 「カード間の矢印の先端が折れている」(SVGのmarker-endが原因。手動に切り替えて解決)
– 「反復カーブとアシスタントの枠が接してしまっている」
– 「おしい、こんどは離れてしまいました」
原画を何度も見比べて、1本ずつ矢印の位置を直していく。地味だけど、この精度が最終品質を決めるんですよね。
「安直だけど天才的」なアイデアとその結末
1枚目が形になったところで、ふと思いました。
「原画を背景に敷いて、テキスト部分だけ矩形で塗りつぶして日本語を上書きすれば、一瞬で完璧じゃない?」
色も矢印もレイアウトも100%原画のまま。テキストだけ差し替え。これは天才的だと思って実装してみたんですが…
テキストのはみ出し問題が発生しました。
英語と日本語ではテキストのサイズが違う。塗りつぶし矩形を少し大きくすると矢印まで消える。小さくすると英語テキストの端が見える。"records' of undefined"の一部がはみ出す。何度マスクサイズを調整しても、どこかから英語テキストの端が顔を出す。
結局、フルリビルド + ピクセル色抽出のハイブリッドが最も実用的だという結論に落ち着きました。
スキルとして「覚えさせる」
1枚目の作業中に交わした指摘——色の一致、矢印の接続ルール、ラベルの配置——これを毎回繰り返すのは非効率です。
そこで、Claude Codeの「スキル」機能を使って、ここまでの全指摘をルールとして記録しました。
– カラー: ピクセル抽出必須、目視推測NG
– 矢印: 辺の中央から出入り、ぴったり接する
– マーカー: SVGのmarker-endは折れるので手動推奨
– カーブ: 枠線・テキストと重ならない余白確保
– ラベル: コンテナの内側に配置
– 出力: DPR=2で原画同サイズのPNG
スキルを読み込んで2枚目(シーケンス図)に取り掛かると、明らかに精度が上がっていました。色の問題は発生しない。矢印の基本ルールも守れている。ただ、新しい課題も出てきます。
「矢印は以前の課題点を解決できています。これはこれで良い改善です」
こうやってOKをもらったら即スキルを更新。NGだったら原因を分析してルールを追加。「指摘→修正→スキル更新→次の画像で検証」 というループが回り始めました。
getBoundingClientRectという転換点
スキルで品質は安定してきたものの、SVG矢印の座標合わせだけはずっと苦しんでいました。
注釈カードからコード内のハイライトに曲線矢印を描く画像。矢印の始点と終点の座標を手動で計算していたんですが、何度やってもコードテキストの上を矢印が通過してしまう。CSS座標からの計算、ビューポートスケーリングの影響、display: flexによるSVG配置のずれ——原因の切り分けに延々と時間を取られました。
5回連続で座標修正を繰り返した後、ユーザー(つまり僕)がヒントを出しました。
「ちなみに、ポイントとしてはcy=150付近、上の赤の付近と人間は思っていますよ?」
これをきっかけに、JavaScriptのgetBoundingClientRect()でブラウザ上の要素の実座標を取得するアプローチに切り替えました。
// ブラウザ上で実行して要素の正確な座標を取得
document.querySelectorAll('.annotation').forEach(el => {
const r = el.getBoundingClientRect();
console.log(`right=${r.right}, centerY=${(r.top+r.bottom)/2}`);
});
結果:
– Card1: right=390, centerY=150 ← 人間の感覚通り
– Highlight1: left=468, centerY=68
これで矢印を描いたら、一発で正確に接続されました。
「これですよ!よくたどり着きました!」
この発見でスキルに最大の学びが追加されました: 「SVG矢印の座標は絶対に目視推測しない。getBoundingClientRect()で実座標を取得してから描画する」
そこから先は加速した
getBoundingClientRectをスキルに組み込んだ後、残りの画像は明らかにペースが上がりました。
次のフロー図(PreToolUse/PostToolUse)では、HTML作成後すぐにJavaScriptで全カードの座標を取得→矢印を一発で正確に配置。座標合わせの苦戦がゼロに。
2カラム型(左:テキスト + 右:コード)の画像では「一発OKパターン」が出始めました。スキルに蓄積されたルール通りに作ると、修正が「テキストカラーの微調整」くらいしか残らない。
画像のタイプ仕分けも効率化に貢献しました。16枚を3カテゴリに分類:
| タイプ | 枚数 | 手法 |
|---|---|---|
| 図表・フロー | 10枚 | HTML+SVGフルリビルド |
| コード+注釈 | 4枚 | HTML+SVGフルリビルド(コード部分は英語のまま) |
| イラスト | 1枚 | スキップ(手描き風は再構築困難) |
| 完了済み | 2枚 | — |
ワークフローの最終形はこうなりました:
1. Pillowで原画のピクセルカラーを抽出 → 正確な配色
2. HTML+SVGで構造を再構築 → CSSレイアウト + SVGで矢印
3. getBoundingClientRectで要素座標を取得 → 矢印を一発配置
4. ブラウザでプレビュー確認 → 微調整ループ
5. OKなら即スキル更新 → 次の画像で精度が上がる
6. Playwrightで一括PNG出力 → DPR=2、1920×1080
16枚すべてのHTMLソースはGit管理可能。テキストを差し替えれば英語版も即座に生成できます。
スキルの蓄積によって、1枚目で30分+修正10回かかった作業が、後半では数分+修正1-2回まで短縮されました。 これがClaude Codeのスキル機能の真価だと思います。
検証3: mermaid.js と D2 — テキスト記法の可能性
「フルリビルドは確実だけど工数が高い。もっと軽い方法はないか?」
そう考えて、図をテキスト記法で定義できるmermaid.jsとD2も検証しました。
mermaid.js
シーケンス図とフロー図の2枚をmermaid記法で再現。テキストを差し替えるだけで日英切替ができるか検証しました。
良い点: テキストファイル(.mmd)のテキストを書き換えるだけでi18n完了。CLIで一括PNG出力も可能。
問題点: 日本語の長いテキストでNote要素がオーバーフロー。レイアウトは完全自動で制御不可。元のスライドデザイン(2カラム構成、カスタム配色、ロゴ)は再現できない。
D2
同じ2枚をD2でも再現。
良い点: mermaidより柔軟なスタイル制御。背景色・太字なども指定可能。
致命的な問題: シーケンス図をネイティブサポートしていない。汎用グラフとして描画されるので、時系列の表現が完全に失われる。
比較結果
| 観点 | HTML+SVG | mermaid.js | D2 |
|---|---|---|---|
| デザイン再現度 | 完全一致 | 構造のみ | 構造のみ |
| レイアウト制御 | CSS全機能 | 自動のみ | 限定的 |
| 日本語対応 | 完全 | オーバーフローあり | 良好 |
| i18n切替の手軽さ | テンプレ変数差替 | テキストのみ | テキストのみ |
| シーケンス図 | SVGで自由 | ネイティブ対応 | 未サポート |
結論: 教育コンテンツのスライド画像には、HTML+SVG+Playwrightが最適。 mermaid/D2は技術ブログ内の補助図としてなら使えるけど、スライドのデザイン品質を求める用途には向かない。
テンプレート化しようとして気づいたこと
16枚のHTMLから頻出パターンを抽出して、汎用テンプレートにしようと考えました。実際に4種類のテンプレートを作り、Playwrightで品質チェックも通しました。
でも、ふと立ち止まりました。
「これ、Anthropicが作ったデザインの模倣だよな」
配色(#f5f7f3の緑がかった白背景、#cc946fのブラウンカード)、レイアウト構成、ロゴの配置位置。これらはAnthropicのオリジナルデザインです。それを「汎用テンプレート」として持ち出すのは、意図しなくてもデザインの転用になる。
テンプレートのHTMLファイルは削除しました。残したのは「パターン分類の知見」だけです。
| パターン | 特徴 | 例 |
|---|---|---|
| 2カラム分離型 | 左:テキスト説明 + 右:コード/ターミナル | SDK紹介、フック定義 |
| カードフロー型 | 番号付きステップ + 補足情報 | 操作手順 |
| シーケンス図型 | 参加者+ライフライン+矢印 | メッセージ交換フロー |
| 注釈付きコード型 | 注釈カード → コードハイライト | 設定ファイル解説 |
パターンを知っていること自体には価値がある。 次に別のコースをローカライズするとき、「この画像は注釈付きコード型だから、SVG矢印の座標計算が必要」と事前に判断できる。でも、デザインの実装は毎回オリジナルから忠実に再構築すべきです。
HTML+SVGアプローチの競合優位性
OCR+インペインティング方式と比較すると、HTML+SVG再構築のメリットは明確です。
| 観点 | OCR+インペインティング | HTML+SVG再構築 |
|---|---|---|
| 出力品質 | ラスター(劣化あり) | ベクター(無劣化、任意解像度) |
| テキスト編集 | 再生成が必要 | HTMLソースを直接編集 |
| 日本語テキスト長変更 | レイアウト崩壊リスク | CSSで自動調整 |
| 再現性 | 毎回微妙に異なる | 決定的(同じ入力→同じ出力) |
| バージョン管理 | 画像差分管理困難 | テキストベースでGit管理 |
| ランニングコスト | API/GPU費用 | 初回構築後は追加コスト極小 |
弱みもあります。写真やスクリーンショットには使えない。初回のHTML構築コストが高い(今回は16枚で数時間)。手描きイラストの再現は困難。
でも、教育コンテンツの図表——フロー図、シーケンス図、コード付き解説スライド——に限れば、この手法が現状最適だと僕は考えています。
振り返り
今回の検証で確立したワークフロー:
1. Pillowでピクセル色抽出 → 正確な配色
2. HTML+SVGでフルリビルド → 完全なレイアウト制御
3. chrome-devtoolsでリアルタイム確認 → 微調整の効率化
4. Playwrightで一括PNG出力 → 高品質バッチ生成
最初は「原画を背景にテキストだけ上書きすれば一瞬で終わる」と思っていました。実際にはそんなに甘くなかった。でも、フルリビルドという遠回りに見えた方法が、結果的に最も堅牢で、テキストベースでGit管理でき、任意の言語に差し替えられる方法になりました。
テンプレート化で著作権の壁にぶつかったのも収穫です。技術的にできることと、やっていいことは違う。パターンの分類知見だけを持ち帰って、デザインの実装は毎回オリジナルに忠実に。これが正しい姿勢だと思います。
ローカライゼーション産業は717億ドル(2024年)の市場がありながら、画像内テキスト翻訳はまだ大半のツールが未対応。HTML+SVG再構築アプローチは、特に教育コンテンツの多言語展開において、まだ誰もやっていないポジションにいる気がしています。
この記事が参考になったら
Share