1. 技術文書の一括翻訳で手戻りが増えた記録
背景
「週末レイトレーシング」第2編と第3編の英語版を作成するため,日本語版のMarkdownをローカルのTranslateGemmaで英訳しました。対象は各編の目次を含む27ファイルで,翻訳先は公開前のディレクトリである en/raytracing/_2/ と en/raytracing/_3/ です。記事には通常の本文だけでなく,frontmatter,数式,Rustのコードブロック,画像参照,HTML要素,Vueコンポーネントが含まれています。
ローカル翻訳には,文書を外部へ送信せずに処理できることと,クラウドAPIの使用量を気にせず一括処理できることへの期待がありました。既存のTranslateGemmaの記事で扱ったような短いテキストでは,訳文を確認して必要な箇所だけ直す運用が成立していました。その経験から,長い技術文書でも同じように処理できると考えたことが,今回の見積もり違いでした。
翻訳ではなく文書変換だった
今回の作業で求められたのは,日本語を英語へ置き換えることだけではありません。自然言語の部分を翻訳しながら,次の要素を一文字単位で維持する必要がありました。
- frontmatterのキーと値
- 見出しの階層
- Markdownのリンク先と画像参照
- fenced code blockの境界と中身
- インラインコード
- 数式の区切りと数式本体
- HTML要素とVueコンポーネント
TranslateGemmaは翻訳結果だけを返すことには従いましたが,文書構造を保ったまま自然言語だけを変換する処理系ではありませんでした。英文として一見自然な出力が得られても,VitePressの記事として同一の構造を保っているとは限りませんでした。結果的に,翻訳を自動化することは難しく,相当の手数が後工程で発生することになりました。
実際に発生した問題
文書の一部が欠落した
ファイル全体を一度に渡した翻訳では,frontmatterが出力されない例と,末尾の見出しや内容が欠落する例がありました。出力が文法的に自然であるため,先頭と末尾を原文と比較しなければ欠落に気づきにくい状態でした。
さらに,第2編と第3編の index.md では,frontmatterの description に英題のコロンが引用符なしで入りました。その結果,YAMLの解析エラーが発生します。frontmatterをデータとして検証する必要がある問題です。
特に大きな問題は画像参照です。第2編の 11.md と第3編の 14.md では,原文にそれぞれ7個あった画像参照のうち6個が翻訳結果から消えていました。文章だけを通読すると意味がつながって見えるため,精読しなければ発見できませんでした。
Markdownとコンポーネントが書き換えられた
<ClientOnly> ブロックがコードブロックとして囲まれ,Vueコンポーネントとして解釈されない形に変わる例がありました。また,<a> 要素の構文が壊れた箇所もありました。これらは翻訳品質の問題ではなく,ページの表示や動作を損なう構造破損です。
コードフェンスやタグは視覚的に目立つため人手でも発見できますが,長い記事が多数あると見落としやすくなります。ビルドが成功した場合でも,コンポーネントが単なるコードとして表示されるなど,意図したページになっているとは限りません。
数式の区切りが失われた
インライン数式の $...$ からドル記号が消え,数式の内容だけが通常の文章として残る例がありました。数式そのものが似た文字列として残っていると,単純な通読では異常を見逃しやすくなります。その後,数式を変更しないよう指示を追加して再翻訳しましたが,すでに翻訳したファイルを原文と再度照合する作業が必要になりました。
識別子と意味が変わった
原文中の -offset が offset に変わるなど,コードに近い記号列から文字が落ちる例がありました。また,「C++ 原典」が実在する書名を想起させる「C++ Primer」に置き換えられる例もありました。流暢な英語に見えますが,原文にない固有名詞を補ったものであり,意味の保持という点では誤訳です。
この種の誤りは構文検査では検出できません。原文と訳文を理解したうえで対照する必要があり,翻訳結果に対する信頼度を大きく下げました。
検証によって増えた工程
当初は,ローカルで各ファイルを翻訳し,訳文を軽く確認すれば完了すると見込んでいました。しかし,構造破損が見つかった後は,作業が次の流れに変わりました。
- 原文と訳文の見出し数を比較する
- 画像参照,リンク,コードフェンス,コンポーネントを比較する
- 数式の区切りが保持されているか確認する
- 欠落した要素を原文から復元する
- 指示を変更して再翻訳する
- 再翻訳によって別の箇所が変わっていないか確認する
- 原文と訳文を読み,意味上の誤りを修正する
自動検査は,画像数や区切り文字の不一致を見つけるうえでは有効でした。しかし,検査に合格したことは,訳文の意味が正しいことを保証しません。反対に,数式やコードを保護するためにプロンプトを複雑にしても,モデルがすべての制約を一貫して守る保証はありません。そのため,機械的な検査と人間による対照確認の両方が必要になりました。
総時間では遅くなった
翻訳を生成する時間だけを見れば,ローカルモデルには費用や回数を気にせず実行できる利点があります。しかし,公開可能な記事を得るまでの時間は,工程にかかるすべての時間の合計で評価する必要があります。今回は厳密なストップウォッチ比較を行っていません。それでも,欠落の調査,検査方法の追加,部分的な再翻訳,画像参照の復元,原文との再照合が発生したため,最初からGPT-5.6 Solや6 Astraのような高性能なクラウドモデルで文書構造を確認しながら翻訳する場合より,総時間は明らかに長くなりました。
クラウドモデルを使っても校閲は必要です。ただし,今回のように出力をほとんど信用できず,全ファイルを構造と意味の両面から再監査する状態になると,一括翻訳によって節約したはずの時間が失われます。推論速度やAPI費用だけではなく,検出と修復を含む総作業時間を比較すべきでした。
原因の整理
今回の結果は,ローカルモデル一般が翻訳に使えないことを意味しません。主な原因は,モデルと作業単位の組み合わせにありました。
- 短文翻訳向けの運用を,構造化された長文へそのまま拡張した
- Markdown全体を自然言語と同じ入力として渡した
- 翻訳対象と変更禁止領域を構文的に分離しなかった
- 少数の試験ファイルで不変条件を確認する前に一括処理した
プロンプトで「コードや数式を変更しない」と指示するだけでは,構造の保持を保証できません。確実に保護するには,Markdownを解析し,翻訳対象の本文だけをモデルへ渡し,frontmatter,コード,数式,リンク先,タグを処理後に合成する仕組みが必要です。
今後の使い分け
TranslateGemmaは,短い文章,クリップボード上のテキスト,外部へ送信できない内容の下訳には引き続き有用です。一方,公開する技術文書のファイル単位の一括翻訳には,少なくとも次の条件が必要です。
- 最初に代表的な1ファイルだけを翻訳し,品質と構造を確認する
- 翻訳前後でfrontmatter,見出し,画像,リンク,コードフェンス,数式,タグの不変条件を検査する
- コード,数式,URL,コンポーネントを翻訳入力から分離する
- 固有名詞と専門用語の対訳を固定する
- 最終的に原文と訳文を意味の単位で対照する
これらの保護機構を用意しない場合は,高性能なモデルが原文と文書全体を確認しながら直接翻訳する方が,総時間と信頼性の両面で有利です。
結論
既存記事で述べた「実用的な翻訳品質」は,短い日常的なテキストを対象とした評価でした。今回の作業により,その評価を長い技術Markdownの一括翻訳へそのまま適用できないことが分かりました。
ローカルで生成できることと,確認せず公開できることは別です。今回もっとも時間を要したのは翻訳そのものではなく,出力を信用できないと判明した後の全件確認と修復でした。今後はモデルの出力速度ではなく,検証と手戻りを含む総時間を基準として翻訳方法を選択します。