🤖

公式ドキュメントで機械翻訳が変にならない方法

2023/11/22に公開
2

はじめに

プログラミングの学習において、英語のドキュメントなどを読む必要に迫れる場合がありますが、ページ翻訳機能ではしばしば、主語や目的語が抜けたおかしな文章になってしまします。

Chromeによるページ翻訳Chromeでの標準のページ翻訳

この記事では、プログラミングのドキュメントで起こりえる翻訳の崩壊の原因と解決策について共有します。

おすすめの解決策は三つ目のクローム拡張機能の利用です。

対象読者

プログラムの英語ドキュメントを読む必要があるが、
英語が母国語ほど得意でない人

想定環境

Chromeブラウザ、
他Chromiumならおそらく参考になる

この記事で得られる情報

  • 翻訳の崩壊の原因
  • 解決方法

ちなみに、
DeepLもしくはEdgeブラウザのユーザーの場合、それほど頻繁にこの問題に直面するわけではないでしょうが、一部重要なWebページ(例えばGitHubのIssue)でも正常に翻訳できない場合があるかと思います。

実際のところ、
webページの書き方は様々であるため、特殊なwebページには対応できない可能性があります。そういったwebページを発見された場合は、後述の拡張機能の参考にしたいので、コメントなどでご連絡いただけると幸いです。

なぜ上手く翻訳できないのか

プログラマー向けドキュメントの翻訳が上手くいかない原因は、html要素のcodeタグにあります。
一般的に、codeタグ内は翻訳サービスに無視されます。実際、Chromeのページ翻訳では、code要素は翻訳対象外になるようです。

この仕様は、貼り付けたソースコードなどのコードブロックを翻訳してほしくない場合うまくいきます。
しかし文章中にcode要素を利用した場合は、翻訳機能はcode要素のスキップされた文章を受け取るため、問題のある翻訳が完成します。

下記の解決策1、2、3では、この問題のアプローチについて言及しています。

解決策1:Edgeブラウザに乗り換える

はじめに考慮すべき解決策として、他ブラウザを利用する方法があります。
私、いぬいが使用して確認したところ、Edgeブラウザでは完ぺきではないですが、code要素も翻訳してくれます。(いぬいはEdgeブラウザの翻訳の細かい仕様を理解していません。)

問題点

とは言え、ブラウザの乗り換えは安易にできることではないと思います。
また、codeタグのdisplayプロパティがblockまたはinline-blockの場合、Edgeブラウザの翻訳もうまく機能しないようです。

next.jsのドキュメントがそれにあたります。
https://nextjs.org/docs

解決策2:置き換えスクリプトを使う

解決策の一つは、下記のjavascriptでcodeタグをspanタグに置き換えてしまうことです。

使い方

下記はミニファイされたスクリプトです。
スクリプトをブックマークのURLとして一度保存します。
ブックマークをクリックしてスクリプトを実行できます。

javascript:document.querySelectorAll('code').forEach(function(e){e.parentNode&&!['pre','div'].includes(e.parentNode.tagName.toLowerCase())&&function(t,n){for(let o=e.attributes.length-1;o>=0;--o){n.attributes.setNamedItem(e.attributes[o].cloneNode())}const i=getComputedStyle(e);for(let o=0;o<i.length;++o){t.style.setProperty(i[o],i.getPropertyValue(i[o]))}e.parentNode.replaceChild(t,e)}(function(){const t=document.createElement('span');while(e.firstChild){t.appendChild(e.firstChild)}return t}(),document.createElement('code'))});

解説

コードのミニファイを戻すと下記のようになっています。

CodeToSpan
document.querySelectorAll('code').forEach(function(e) {
  if (e.parentNode && !['pre', 'div'].includes(e.parentNode.tagName.toLowerCase())) {
    (function(t, n) {
      for (let o = e.attributes.length - 1; o >= 0; --o) {
        n.attributes.setNamedItem(e.attributes[o].cloneNode());
      }
      const i = getComputedStyle(e);
      for (let o = 0; o < i.length; ++o) {
        t.style.setProperty(i[o], i.getPropertyValue(i[o]));
      }
      e.parentNode.replaceChild(t, e);
    })(
      (function() {
        const t = document.createElement('span');
        while (e.firstChild) {
          t.appendChild(e.firstChild);
        }
        return t;
      })(),
      document.createElement('code')
    );
  }
});

ポイントを絞って説明します。

  • スキップする親タグの指定
if (e.parentNode && !['pre', 'div'].includes(e.parentNode.tagName.toLowerCase())) {

ここでは、親タグがpreかdivの場合に置き換えをスキップする処理をしています。
これは文章中以外でのコードタグ、つまりコードブロック内を翻訳しないための処理です。編集することで、スキップする親タグを変更できます。

  • 属性の引継ぎ
for (let o = e.attributes.length - 1; o >= 0; --o) {
  n.attributes.setNamedItem(e.attributes[o].cloneNode());
}
  • スタイルの引継ぎ
const i = getComputedStyle(e);
for (let o = 0; o < i.length; ++o) {
  t.style.setProperty(i[o], i.getPropertyValue(i[o]));
}

解決策3:クローム拡張機能:CodeToSpanを使う

私、いぬいの作成した拡張機能です!!!

javascriptの問題点として、手動で何度もコードを実行する必要があります。また、置き換え条件やレイアウトの継承について、細かい制御などは行っていません。この拡張機能では、ページの変更の監視と、その他の細かい調整を行ってくれます。
https://chromewebstore.google.com/detail/codetospan-for-translatio/ebnohmjaodacnofjhknnjjnchanjleng?utm_source=zenn&utm_medium=article&utm_campaign=how_to_fix_machine_translation

https://github.com/devInui/CodeToSpan

最近のバージョンアップで、codeタグinline以外のdisplayプロパティで記述されたNext.jsのドキュメントなどでも適切な置き換えが可能になりました。
https://nextjs.org/docs

たぶん大体のWebページでうまくいくと思っています。上手く動かなければ、コメント等などからご連絡いただけると幸いです。

その他の原因と解決策

原因

一部のwebページでは、コードブロックを記述する際に、codeタグではなくspanタグが使われています。そしてspanタグは基本的に翻訳されるため、コードブロックの内容が崩壊してしまいます。

解決策

ほとんどの場合、コードブロックはpreタグの中で記述されています。そのため、preタグのtranslate属性を変更することで簡単に対処できます。
CodeToSpanを利用している場合、オプションページから設定を変更してください。
JavaScriptを利用する場合、下記のtranslate="no"を付与するミニファイされたコードを利用してください。前述と同様にブックマークとして保存することで、このレアケースに対応できます。

javascript:document.querySelectorAll('pre').forEach(function(e){e.setAttribute('translate','no')});

短いので解説は省略します。

最後に

半分くらい自身の作成した拡張機能の宣伝になってしまっています。
前半を書いている時は拡張機能がバージョン1.0でうまく動作しないwebページもあったのです。その時は解決策1と2も有用だったのです、、、

この記事で、少しでもいぬいのようなプログラミング初学者の負担が減らせればうれしです。
もし、CodeToSpanが機能しないページがあれば、コメントしていただけると助かります。

Discussion

腰痛エンジニア腰痛エンジニア

私も翻訳時にコード要素による表示崩れに困っていました。

いぬいさんの作成した拡張機能はとても便利で助けられています。
今後も使わせていただこうと思いました。
作成してくださりありがとうございます!

いぬいいぬい

コメントありがとうございます!!
この拡張機能が役立っていると聞いて、嬉しいです!

この拡張機能のフィードバックをもらうのは実は初めてで、とても励みになりました。