マガジン

ブラウザの自動翻訳でゲームUIが壊れる問題を防ぐ

遊びをつくる

執筆にClaudeを使用しています。

活版のような抽象的な字形とローラーを並べ、太さや間隔を検討する写真風イメージ。
記事のテーマをもとに制作したAI生成イラスト。

ChromeやEdgeには、外国語のページを検出すると自動で翻訳を実行する機能があります。日本語で作ったゲームを海外からアクセスした人が開いたとき、あるいはブラウザの言語設定によっては日本語のページでも翻訳が走ることがあります。この翻訳処理はDOMを書き換えるため、ゲームのUIテキストが消える、ボタンが反応しなくなる、レイアウトが崩れるといった症状を引き起こします。 問題の核心は、ブラウザの翻訳エンジンがテキストノードを独自の要素で包んだり、属性値を上書きしたりする点にあります。JavaScriptでDOM要素を参照しているゲームは、翻訳後に要素が見つからなくなったり、想定外のテキストが入力として処理されたりして動作が止まります。「自分の環境では問題ない」と思っていても、プレイヤーのブラウザ設定次第で再現する厄介なバグです。 この記事では、なぜ翻訳がゲームを壊すのかを具体的に説明し、HTMLとJavaScriptそれぞれで取れる対策を手順とともに示します。

この記事の目次
  1. なぜ翻訳エンジンはUIを壊すのか
  2. 最も確実な対策:翻訳を無効化するmeta指定
  3. 部分的に翻訳を止めたい場合の属性指定
  4. JavaScriptで動的に生成するテキストへの対処
  5. 動作確認の方法
  6. 次の行動
  7. 参考資料

なぜ翻訳エンジンはUIを壊すのか

Chromeの翻訳機能(Google翻訳を利用)は、ページ内のテキストノードを検出して内容を書き換えます。このとき、単純にテキストを差し替えるだけでなく、<font>タグや独自の属性を挿入することがあります。たとえば <span>スタート</span> が翻訳後に <span><font>Start</font></span> のような構造に変わると、そのspanのテキストを textContent で取得しているコードの挙動が変わります。

さらに深刻なのが、Reactや独自のUIフレームワークを使っているケースです。仮想DOMとの差分検出が走ったとき、翻訳エンジンが挿入したノードをフレームワークが認識できず、描画が崩壊することがあります。また、data-属性やvalue属性に日本語を入れている場合、翻訳エンジンがそこに触れるかどうかはブラウザのバージョンや設定によって変わります。つまり「たまに壊れる」という再現性の低さが、このバグを見落としやすくしています。

Canvas要素に描いたテキストは翻訳エンジンの対象外ですが、HTML要素で組んだUIは原則としてすべて対象になります。

最も確実な対策:翻訳を無効化するmeta指定

ページ全体の翻訳をオフにするには、<head>に次の1行を追加します。

html
<meta name="google" content="notranslate">

これはGoogleの翻訳エンジンに対して「このページを翻訳しない」と伝える公式の指定です。Chromeのアドレスバーに翻訳の提案が表示されなくなり、自動翻訳も実行されません。

Microsoftの翻訳(Edgeの組み込み機能)に対しては、<html>タグに translate="no" 属性を加えるのが標準的な方法です。

html
<html lang="ja" translate="no">

translate 属性はHTML5の仕様に含まれており、対応しているブラウザであればGoogle翻訳以外の翻訳エンジンにも効果があります。両方を組み合わせて書くのが現時点でのベストプラクティスです。

html
<!DOCTYPE html>
<html lang="ja" translate="no">
<head>
  <meta name="google" content="notranslate">
  ...
</head>

この指定だけで、大半の自動翻訳によるUI崩壊を防げます。ゲームを公開する前にこの2行が入っているかを確認する習慣をつけておくと安心です。

部分的に翻訳を止めたい場合の属性指定

ゲームのUIは翻訳させたくないが、説明文やヘルプテキストは翻訳してもよい、という場合は要素ごとに制御できます。翻訳を止めたい要素に translate="no" を付けます。

html
<div id="game-ui" translate="no">
  <button id="btn-start">スタート</button>
  <span id="score">0</span>
</div>
<p class="description">このゲームの遊び方...</p>

translate="no" は子要素にも継承されます。ゲームキャンバスやUIコンテナを囲む親要素に一括で指定すれば、内側すべてに効きます。逆に、翻訳を許可したい子要素だけ translate="yes" で上書きすることもできます。

ただし、この属性への対応度はブラウザや翻訳エンジンのバージョンによって異なります。確実に止めたいゲームUIには、ページ全体の notranslate 指定と組み合わせて使うのが安全です。

JavaScriptで動的に生成するテキストへの対処

テキストをJavaScriptで動的に挿入しているケースでは、meta指定だけでは不十分なことがあります。特に、外部APIや設定ファイルからテキストを取得してDOMに反映する構造では、翻訳エンジンが書き換えた後のDOMを読んでしまうことがあります。

この場合、次の方針で設計を見直すと問題を起きにくくできます。

  1. 表示テキストをDOMのテキストノードとして持たない。テキストをCanvasに描画するか、CSSの content プロパティで指定する。ゲームUIの多くはCanvas描画に移行することで翻訳の影響を受けなくなります。
  1. テキストを取得する参照をIDやクラスに頼らない。翻訳後にclassが変わることは少ないですが、テキストノードの内容で分岐するロジックは翻訳後に誤動作します。テキストではなく data- 属性や変数の状態で制御するように変えます。
  1. MutationObserverで変更を検知して戻す。翻訳エンジンによる変更を検知し、元の値に戻す方法もありますが、実装コストが高く翻訳エンジンとの競合が起きやすいため、最後の手段として検討します。

多くのブラウザゲームにとって、現実的な対処順序は「①ページ全体にnotranslateを指定 → ②それでも問題が残るUI要素にtranslate="no"を追加 → ③どうしても解決しない動的テキストはCanvas描画に切り替える」です。

動作確認の方法

対策を入れたあとは、意図どおりに翻訳が止まっているかを確認します。Chromeで確認する場合は、ブラウザの言語設定を日本語以外(英語など)に一時的に変更するか、拡張機能「Google 翻訳」を使って手動で翻訳を実行し、UIの見た目とJavaScriptの動作を確認します。

言語設定の変更は Chrome の「設定 → 言語」から行えます。変更後にページを再読み込みすると翻訳の提案バーが表示されることがあり、そこで「翻訳する」を押したときに何も変化しないことを確認できます。notranslate が効いていれば提案バー自体が出ない場合もあります。

Edgeでの確認は「設定 → 言語 → 翻訳の設定」から翻訳を強制的に実行する操作を試みることで行えます。どちらのブラウザでも、UIが崩れず、ボタンが機能し、スコアが正常に動くかを実際にゲームをプレイしながら確認するのが確実です。

次の行動

まず手元のゲームHTMLの <html> タグと <head> を開き、translate="no" と <meta name="google" content="notranslate"> の両方が入っているかを確認してください。まだ入っていなければ追加し、Chromeで言語設定を英語に変えて翻訳が走らないことを実機で確認してから公開してください。アソバースにZIPやHTMLを投稿する前のチェックリストにこの2点を加えておくと、公開後のトラブルを未然に防げます。

参考資料

  • Google 検索セントラル(robots メタタグと翻訳制御の公式ドキュメント)
  • HTML Living Standard(translate 属性の仕様、WHATWG)
  • MDN Web Docs(translate グローバル属性)