MathJaxの数式を含むWebページをGoogle翻訳する
現状のまとめ
方法1
以下2つのブックマークレットを登録しておき、「1つ目実行」→「ページを翻訳」→「2つ目実行」
javascript:document.querySelectorAll(".MathJax, .mjx-chtml, .MathJax_Preview, .MathJax_CHTML").forEach(e=>{e.parentNode.removeChild(e)}),document.querySelectorAll('script[type="math/tex"]').forEach(e=>{let t=e.innerText||e.textContent,a="$"+t+"$",r=document.createElement("span");r.className="replaced",r.innerHTML=a,e.parentNode.replaceChild(r,e)});
javascript:MathJax.Hub.Config({tex2jax:{inlineMath:[["$","$"]]}}),Array.prototype.forEach.call(document.querySelectorAll(".replaced"),e=>{MathJax.Hub.Typeset(e)});
方法2
以下のブックマークレットを登録して実行する
翻訳後3秒後決め打ちでタイプセットが走るので、適宜調整が必要
javascript:!function(){document.querySelectorAll(".MathJax, .mjx-chtml, .MathJax_Preview").forEach(function(e){e.parentNode.removeChild(e)}),document.querySelectorAll('script[type="math/tex"]').forEach(e=>{var t=e.innerText||e.textContent,a=document.createElement("span");a.className="replaced",a.innerHTML="$"+t+"$",e.parentNode.replaceChild(a,e)});let e=document.createElement("script");e.type="text/javascript",e.src="//translate.google.com/translate_a/element.js?cb=googleTranslateElementInit",document.body.appendChild(e),window.googleTranslateElementInit=()=>{new google.translate.TranslateElement({pageLanguage:"en",layout:google.translate.TranslateElement.FloatPosition.TOP_LEFT,completionCallback(){console.log("done")}},"google_translate_element")},setTimeout(()=>{MathJax.Hub.Config({tex2jax:{inlineMath:[["$","$"]]}}),Array.prototype.forEach.call(document.querySelectorAll(".replaced"),e=>{MathJax.Hub.Typeset(e)})},3000)}();
問題点
- アクセシビリティ等をガン無視している
- 2回呼びだすと壊れるなどコードが雑
- KaTeX使ってるサイトだと対処不可
- MathMLをTeX記法に変換できるライブラリがあるようなのでMathML→TeX数式混ぜた文書→翻訳→タイプセット で行けるかも?
- https://www.npmjs.com/package/mathml-to-latex
- displaymathなど確認していない形式が多い
- AsciiMathなど、MathJaxが対応していてもTeX以外の記法は無視している
- 長くて一度に翻訳されないサイト、数式表示が動的なサイトだとうまくいかない(?未検証)
-
スマホからだと置換ができないコード修正したらできるようになった
追記:3つ上の修正に伴い方法1のブックマークレット修正
(Notionからコピペする時に肝心の目標が消えていたので追記)
Codeforcesの問題文(例:CF R921 div2 D)をGoogle翻訳拡張等で翻訳しようとするとレイアウトが崩れるので、うまく翻訳してくれるブックマークレットを作ることが目標
innerHTMLをテキストで置き換えるのを検討してみる
改行が無駄に入るのと同じ数式が連続するのが邪魔
Assistive MathMLの設定がtrueだと後ろにMathMLの情報を埋め込んでしまうっぽい
MathJaxの設定を書き換えても反映されない
typesetしなおす必要がある
javascript: (() => {
MathJax.Hub.Queue(
() => {
/* assistive MathMLの設定を切る */
MathJax.Hub.Config({
menuSettings: { assistiveMML: false },
});
},
["Reprocess", MathJax.Hub] /* 設定を反映して再度タイプセット */,
() => {
Array.prototype.forEach.call(
/* 問題文内のp,liをテキストで置き換える */
document.querySelector(".problem-statement").querySelectorAll("p, li"),
(p) => {
p.innerHTML = p.innerText;
MathJax.Hub.Typeset(p);
}
);
}
);
})();
一応それらしい結果は得られた
ただ上・下付き文字や括線などは反映されない
やっぱり数式を表示したい
TeX数式がソースの中にあるのでこれを使ってみる
CFデフォルトの$$$で囲んでから翻訳し、それから再度タイプセットする
javascript: (() => {
document.querySelectorAll('.mjx-chtml,.MathJax_Preview').forEach((elem) => {
elem.parentNode.removeChild(elem);
});
document.querySelectorAll('script[type="math/tex"]').forEach((elem) => {
const text = elem.innerText || elem.textContent;
const newText = '$$$' + text + '$$$';
const newElem = document.createElement('span');
newElem.innerHTML = newText;
elem.parentNode.replaceChild(newElem, elem);
});
})();
javascript: (() => {
Array.prototype.forEach.call(
/* 問題文内のp,liをテキストで置き換える */
document.querySelector(".problem-statement").querySelectorAll("p, li"),
(p) => {
p.innerHTML = p.innerText;
MathJax.Hub.Typeset(p);
}
);
}
)();
悪くはないが、うまくいかないところが多い
translate=”no”属性をつけて$$$で囲んでみる
javascript: (function () {
document.querySelectorAll(".mjx-chtml,.MathJax_Preview").forEach((elem) => {
elem.parentNode.removeChild(elem);
});
document.querySelectorAll('script[type="math/tex"]').forEach((elem) => {
const text = elem.innerText || elem.textContent;
const newText = "$$$" + text + "$$$";
const newElem = document.createElement("span");
newElem.setAttribute("translate", "no");
newElem.innerHTML = newText;
elem.parentNode.replaceChild(newElem, elem);
});
})();
javascript: (() => {
Array.prototype.forEach.call(
/* 問題文内のp,liをテキストで置き換える */
document.querySelector(".problem-statement").querySelectorAll("p, li"),
(p) => {
p.innerHTML = p.innerText;
MathJax.Hub.Typeset(p);
}
);
}
)();
これは駄目、そもそも翻訳がおかしい
$マーク3つで囲む記法だと翻訳が上手くいかないことが多い。
3つではなく1つで囲むよう変更
置き換えたspanタグにreplacedクラスを設定
javascript: (() => {
document
.querySelectorAll(".MathJax, .mjx-chtml, .MathJax_Preview, .MathJax_CHTML")
.forEach((elem) => {
elem.parentNode.removeChild(elem);
});
document.querySelectorAll('script[type="math/tex"]').forEach((elem) => {
const text = elem.innerText || elem.textContent;
const newText = "$" + text + "$";
const newElem = document.createElement("span");
newElem.className = "replaced";
newElem.innerHTML = newText;
elem.parentNode.replaceChild(newElem, elem);
});
})();
javascript: (() => {
MathJax.Hub.Config({
tex2jax: {
inlineMath: [["$", "$"]],
},
});
Array.prototype.forEach.call(document.querySelectorAll(".replaced"), (p) => {
MathJax.Hub.Typeset(p);
});
})();
かなりうまくいく、これでよさそう
追記:上のスニペットで消すclassに.MathJax
を追加、下のスニペットでMathJax.Hub.Queue
に渡す関数内で実行していたのを変更
1ボタンでやりたい
Google翻訳をJSから呼び出したい
javascript: (() => {
const s = document.createElement("script");
s.type = "text/javascript";
s.src =
"//translate.google.com/translate_a/element.js?cb=googleTranslateElementInit";
document.body.appendChild(s);
window.googleTranslateElementInit = () => {
new google.translate.TranslateElement(
{
pageLanguage: "en",
layout: google.translate.TranslateElement.FloatPosition.TOP_LEFT,
completionCallback: () => {
console.log("done");
},
},
"google_translate_element"
);
};
})();
これで翻訳機能を呼び出せる
翻訳完了のコールバックがないのでタイミングがわからない
翻訳完了後のタイプセットの時間を決め打ちしたやつ。うまくいかないこともあるがボタン1回でOK
だいぶ無理やりやっているのでまともな方法があれば知りたい
javascript: (() => {
document
.querySelectorAll(".MathJax, .mjx-chtml, .MathJax_Preview")
.forEach((elem) => {
elem.parentNode.removeChild(elem);
});
document.querySelectorAll('script[type="math/tex"]').forEach((elem) => {
const text = elem.innerText || elem.textContent;
const newText = "$" + text + "$";
const newElem = document.createElement("span");
newElem.className = "replaced";
newElem.innerHTML = newText;
elem.parentNode.replaceChild(newElem, elem);
});
const s = document.createElement("script");
s.type = "text/javascript";
s.src =
"//translate.google.com/translate_a/element.js?cb=googleTranslateElementInit";
document.body.appendChild(s);
window.googleTranslateElementInit = () => {
new google.translate.TranslateElement(
{
pageLanguage: "en",
layout: google.translate.TranslateElement.FloatPosition.TOP_LEFT,
completionCallback: () => {
console.log("done");
},
},
"google_translate_element"
);
};
setTimeout(() => {
MathJax.Hub.Config({
tex2jax: {
inlineMath: [["$", "$"]],
},
});
Array.prototype.forEach.call(
document.querySelectorAll(".replaced"),
(p) => {
MathJax.Hub.Typeset(p);
}
);
}, 3000);
})();
かなりのゴリ押しなのでもう少しまともな方法も探したい
とりあえずGistに上げてみた
方法2の方でGoogle翻訳が上手く呼べていないことがある
直すところ
- Google翻訳のところがうまく動かないことがある
-
修正済み.replaced
をタイプセットしていくところでMathJax.Hub.Queue
の中でTypeset
呼び出してる、多分途中でいろいろ変更しているうちに別のコードと混ざった? - ディスプレイ数式だと死ぬ