Inline-Translator

在每个段落之后加上中文翻译

Verze ze dne 21. 04. 2024. Zobrazit nejnovější verzi.

K instalaci tototo skriptu si budete muset nainstalovat rozšíření jako Tampermonkey, Greasemonkey nebo Violentmonkey.

You will need to install an extension such as Tampermonkey to install this script.

K instalaci tohoto skriptu si budete muset nainstalovat rozšíření jako Tampermonkey nebo Violentmonkey.

K instalaci tohoto skriptu si budete muset nainstalovat rozšíření jako Tampermonkey nebo Userscripts.

You will need to install an extension such as Tampermonkey to install this script.

K instalaci tohoto skriptu si budete muset nainstalovat manažer uživatelských skriptů.

(Už mám manažer uživatelských skriptů, nechte mě ho nainstalovat!)

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

(Už mám manažer uživatelských stylů, nechte mě ho nainstalovat!)

// ==UserScript==
// @id             Inline-Translator
// @name           Inline-Translator
// @version        0.1
// @namespace      12425
// @author         12425
// @description    在每个段落之后加上中文翻译
// @license        MIT
// @include        http://*
// @include        https://*
// @grant          GM_registerMenuCommand
// @grant          GM_xmlhttpRequest
// ==/UserScript==


'use strict';

(function() {

GM_registerMenuCommand("翻译成双语网页", () => {
  const root = document.body;
  if (root.classList.contains('_myscript_translated')) {
    return;
  }
  root.classList.add('_myscript_translated');
  translate(root);
});


const TranslationTags = new Set([
  "blockquote",
  "h1",
  "h2",
  "h3",
  "h4",
  "h5",
  "h6",
  "ol",
  "p",
  "ul",
]);


function fetch(text, callback, arg1, arg2) {
  GM_xmlhttpRequest({
    method: 'GET',
    url: `https://translate.googleapis.com/translate_a/single?client=gtx&sl=auto&tl=zh&dt=t&q=${encodeURIComponent(text)}`,
    onload: function(resp) {
      let json = null;
      try {
        json = JSON.parse(resp.responseText);
      } catch {
        return;
      }

      const data = json[0].map(function(item) {
        return item[0];
      }).join('');
      if (text !== data) {
        callback(data, arg1, arg2);
      }
    },
  });
}


function simplify(node) {
  let array = [];
  array.push(extractAttrs(node));
  Array.from(node.querySelectorAll('*')).forEach(function(el) {
    array.push(extractAttrs(el));
  });
  return array;
}


function extractAttrs(node) {
  let attributes = {};
  Array.from(node.attributes).forEach(attr => {
    attributes[attr.name] = attr.value;
    node.removeAttribute(attr.name);
  });
  return attributes;
}


function resumeAttrs(node, attrs) {
  Object.keys(attrs).forEach(key => {
    node.setAttribute(key, attrs[key]);
  });
}


function updateNode(data, node, attrs) {
  const tag = node.tagName.toLowerCase();
  let newNode = document.createElement(tag);
  newNode.innerHTML = data;
  node.insertAdjacentElement('afterend', newNode);
  resumeAttrs(newNode, attrs[0]);
  let i = 1;
  Array.from(node.querySelectorAll('*')).forEach(function(el) {
    resumeAttrs(el, attrs[i]);
    i++;
  });
  if (node.parentNode.tagName !== 'SMALL') {
    const smallNode = document.createElement('small');
    node.insertAdjacentElement('afterend', smallNode);
    smallNode.appendChild(node);
  }
}


function translate(node) {
  const tag = node.tagName.toLowerCase();
  if (!tag) {
    return;
  }
  if (!TranslationTags.has(tag)) {
    Array.from(node.children).forEach(translate);
    return;
  }
  const attrs = simplify(node.cloneNode(true));
  fetch(node.innerHTML, updateNode, node, attrs);
}


})();