「Translation_javascript」の編集履歴(バックアップ)一覧はこちら
Translation_javascript - (2026/04/08 (水) 22:36:42) の1つ前との変更点
追加された行は緑色になります。
削除された行は赤色になります。
#javascript(){{
function IstranslationOn() {
return (localStorage["translationCheck"] || "") === "true";
}
// 連続する同一リンクの統合(content 内で処理)
function mergeAdjacentSameHrefAnchors(content, separator = ' ') {
if (!content) return;
// 先に全アンカーを配列化しておく(DOM操作で要素が削除されても安全)
const anchors = Array.from(content.querySelectorAll('a'));
for (let i = 0; i < anchors.length; i++) {
const a = anchors[i];
if (!a.isConnected) continue; // 既に削除済みならスキップ
let hrefA = a.getAttribute('href');
if (!hrefA) continue;
// 正規化(相対URL対応)
try { hrefA = new URL(hrefA, document.baseURI).href; } catch (e) { /* そのまま比較 */ }
let next = a.nextElementSibling;
while (next && next.tagName === 'A') {
let hrefNext = next.getAttribute('href');
if (!hrefNext) break;
try { hrefNext = new URL(hrefNext, document.baseURI).href; } catch (e) { /* そのまま比較 */ }
if (hrefA === hrefNext) {
// 本文を結合(innerHTML を結合する。必要なら textContent に変更)
// 末尾・先頭の空白を整理して余分なスペースを作らない
const left = a.innerHTML.trim();
const right = next.innerHTML.trim();
a.innerHTML = left + separator + right;
const toRemove = next;
next = next.nextElementSibling;
toRemove.remove();
} else {
break;
}
}
}
}
async function loadDictionary() {
const res = await fetch("https://tgr55al.github.io/assault_lily-ga4-graph/terms.json");
return await res.json();
}
async function translationFunc() {
if (!IstranslationOn()) {
return;
}
// 対象コンテント(優先順)
const content = document.getElementById("content")
|| document.querySelector(".atwiki-content")
|| document.body;
// ページ内のすべてのルビを削除し、平文に変える
document.querySelectorAll("ruby").forEach(ruby => {
ruby.querySelectorAll("rt, rp").forEach(el => el.remove());
ruby.querySelectorAll("rb").forEach(rb => {
while(rb.firstChild) { rb.parentNode.insertBefore(rb.firstChild, rb); }
rb.remove();
});
while(ruby.firstChild) { ruby.parentNode.insertBefore(ruby.firstChild, ruby); }
ruby.remove();
});
document.querySelectorAll("rb, rt").forEach(el => {
while(el.firstChild) { el.parentNode.insertBefore(el.firstChild, el); }
el.remove();
});
// ここで連続する同一リンクを統合しておく(ルビ削除後にDOMが安定しているため)
mergeAdjacentSameHrefAnchors(content, ' ');
// 和英置換辞書
const replaceDict = await loadDictionary();
// 長い文字列優先でソートして処理
const sortedEntries = Object.entries(replaceDict)
.sort((a, b) => b[0].length - a[0].length);
// テキスト置換
const walker = document.createTreeWalker(
content,
NodeFilter.SHOW_TEXT,
{
acceptNode: function(node) {
const tag = node.parentNode.nodeName;
if (tag === "SCRIPT" || tag === "STYLE" || tag === "NOSCRIPT") {
return NodeFilter.FILTER_REJECT;
}
return NodeFilter.FILTER_ACCEPT;
}
}
);
let node;
while (node = walker.nextNode()) {
let text = node.textContent;
let changed = false;
for (let [ja, en] of sortedEntries) {
const regex = new RegExp(ja, "g");
if (regex.test(text)) {
text = text.replace(regex, " " + en + " ");
changed = true;
}
else if (regex.test(text.replace(/\s/g, ''))) {
text = text.replace(/\s/g, '').replace(regex, " " + en + " ");
changed = true;
}
}
if (changed) {
node.textContent = text;
}
}
}
// ページ読み込み後に実行
if (document.readyState === "loading") {
document.addEventListener("DOMContentLoaded", translationFunc);
} else {
translationFunc();
}
}}
#javascript(){{
function IstranslationOn() {
return (localStorage["translationCheck"] || "") === "true";
}
// 連続する同一リンクの統合(content 内で処理)
function mergeAdjacentSameHrefAnchors(content, separator = ' ') {
if (!content) return;
// 先に全アンカーを配列化しておく(DOM操作で要素が削除されても安全)
const anchors = Array.from(content.querySelectorAll('a'));
for (let i = 0; i < anchors.length; i++) {
const a = anchors[i];
if (!a.isConnected) continue; // 既に削除済みならスキップ
let hrefA = a.getAttribute('href');
if (!hrefA) continue;
// 正規化(相対URL対応)
try { hrefA = new URL(hrefA, document.baseURI).href; } catch (e) { /* そのまま比較 */ }
let next = a.nextElementSibling;
while (next && next.tagName === 'A') {
let hrefNext = next.getAttribute('href');
if (!hrefNext) break;
try { hrefNext = new URL(hrefNext, document.baseURI).href; } catch (e) { /* そのまま比較 */ }
if (hrefA === hrefNext) {
// 本文を結合(innerHTML を結合する。必要なら textContent に変更)
// 末尾・先頭の空白を整理して余分なスペースを作らない
const left = a.innerHTML.trim();
const right = next.innerHTML.trim();
a.innerHTML = left + separator + right;
const toRemove = next;
next = next.nextElementSibling;
toRemove.remove();
} else {
break;
}
}
}
}
// 連続するテキストノードを結合する
function mergeAdjacentTextNodes(root) {
const walker = document.createTreeWalker(
root,
NodeFilter.SHOW_TEXT,
null
);
let node;
while (node = walker.nextNode()) {
let next = node.nextSibling;
// 連続する textNode をまとめる
while (next && next.nodeType === Node.TEXT_NODE) {
node.textContent += next.textContent;
const toRemove = next;
next = next.nextSibling;
toRemove.remove();
}
}
}
async function loadDictionary() {
const res = await fetch("https://tgr55al.github.io/assault_lily-ga4-graph/terms.json");
return await res.json();
}
async function translationFunc() {
if (!IstranslationOn()) {
return;
}
// 対象コンテント(優先順)
const content = document.getElementById("content")
|| document.querySelector(".atwiki-content")
|| document.body;
// ページ内のすべてのルビを削除し、平文に変える
document.querySelectorAll("ruby").forEach(ruby => {
ruby.querySelectorAll("rt, rp").forEach(el => el.remove());
ruby.querySelectorAll("rb").forEach(rb => {
while(rb.firstChild) { rb.parentNode.insertBefore(rb.firstChild, rb); }
rb.remove();
});
while(ruby.firstChild) { ruby.parentNode.insertBefore(ruby.firstChild, ruby); }
ruby.remove();
});
document.querySelectorAll("rb, rt").forEach(el => {
while(el.firstChild) { el.parentNode.insertBefore(el.firstChild, el); }
el.remove();
});
// ここで連続する同一リンクを統合しておく(ルビ削除後にDOMが安定しているため)
mergeAdjacentSameHrefAnchors(content, ' ');
// テキストノードを結合
mergeAdjacentTextNodes(content);
// 和英置換辞書
const replaceDict = await loadDictionary();
// 長い文字列優先でソートして処理
const sortedEntries = Object.entries(replaceDict)
.sort((a, b) => b[0].length - a[0].length);
// テキスト置換
const walker = document.createTreeWalker(
content,
NodeFilter.SHOW_TEXT,
{
acceptNode: function(node) {
const tag = node.parentNode.nodeName;
if (tag === "SCRIPT" || tag === "STYLE" || tag === "NOSCRIPT") {
return NodeFilter.FILTER_REJECT;
}
return NodeFilter.FILTER_ACCEPT;
}
}
);
let node;
while (node = walker.nextNode()) {
let text = node.textContent;
let changed = false;
for (let [ja, en] of sortedEntries) {
const regex = new RegExp(ja, "g");
if (regex.test(text)) {
text = text.replace(regex, " " + en + " ");
changed = true;
}
else if (regex.test(text.replace(/\s/g, ''))) {
text = text.replace(/\s/g, '').replace(regex, " " + en + " ");
changed = true;
}
}
if (changed) {
node.textContent = text;
}
}
}
// ページ読み込み後に実行
if (document.readyState === "loading") {
document.addEventListener("DOMContentLoaded", translationFunc);
} else {
translationFunc();
}
}}
表示オプション
横に並べて表示:
変化行の前後のみ表示: