Greasy Fork

Greasy Fork is available in English.

悬停翻译句子

鼠标悬停自动翻译句子

当前为 2024-08-12 提交的版本,查看 最新版本

// ==UserScript==
// @name         悬停翻译句子
// @namespace    http://tampermonkey.net/
// @version      1.1
// @description  鼠标悬停自动翻译句子
// @author       pipizhu
// @match        http*://*/*
// @grant        GM_setValue
// @grant        GM_getValue
// @grant        GM_registerMenuCommand
// @license 		 MIT
// ==/UserScript==
// Function to segment the text into sentences and wrap them in span tags with a green hover border color
function wrapTextNodes(parent) {
  // Create a document fragment to hold the new structure
  const fragment = document.createDocumentFragment();

  // Loop through child nodes
  while (parent.firstChild) {
    const child = parent.firstChild;

    if (child.nodeType === Node.TEXT_NODE) {
      // If the child is a text node, wrap each sentence
      const sentences = child.textContent.split(/(?<=\.)/);

      if (sentences) {
        sentences.forEach((sentence) => {
          const span = document.createElement("span");
          span.className = "sentence";
          span.textContent = sentence;
          fragment.appendChild(span);
          fragment.appendChild(document.createTextNode(" ")); // Add space between sentences
        });
      } else {
        fragment.appendChild(child.cloneNode(true)); // Preserve text if no sentences found
      }
    } else if (child.nodeType === Node.ELEMENT_NODE) {
      // If the child is an element, recurse into it
      // // Handle element nodes (like <a> tags)
      const newElement = document.createElement(child.tagName.toLowerCase());
      newElement.innerHTML = child.innerHTML;

      // Copy attributes from the original element
      for (const attr of child.attributes) {
        newElement.setAttribute(attr.name, attr.value);
      }

      // Recursively process child nodes
      // newElement.appendChild(processNode(child));
      fragment.appendChild(newElement);
    }

    // Remove the processed child node
    parent.removeChild(child);
  }

  // Return the wrapped structure
  return fragment;
}

// Get all <p> tags on the page
const paragraphs = document.querySelectorAll("p");

// Iterate through each <p> tag
paragraphs.forEach((paragraph) => {
  paragraph.appendChild(wrapTextNodes(paragraph));
});

// Add a style element to the document head for the hover effect
const style = document.createElement("style");
style.innerHTML = `
    .sentence {
        position: relative;
        transition: border-bottom-color 0.3s ease;
        cursor: pointer;
    }
    .sentence:hover {
        border-bottom: 2px solid #32CD32; /* Beautiful green */
    }
    .t-popover {
        position: absolute;
        color: black;
        top: 100%;
        width: 100%;
        left: 0;
        min-width: 300px;
        background-color: #fff;
        padding: 5px 10px;
        border: 1px solid #ccc;
        border-radius: 3px;
        box-shadow: 0 2px 10px rgba(0, 0, 0, 0.2);
        z-index: 1000;
        transform: translateY(10px);
        display: none;
    }
    .sentence:hover .t-popover {
        display: block;
    }
`;
document.head.appendChild(style);

// Apply the hover effect and translation using JavaScript
document.querySelectorAll(".sentence").forEach((span) => {
  const greenColor = "#32CD32"; // Beautiful green color

  // Create a popover element
  const popover = document.createElement("div");
  popover.className = "t-popover";
  span.appendChild(popover);

  span.addEventListener("mouseover", function () {
    this.style.borderBottomColor = greenColor;
    // Check if the popover already contains translated text
    if (popover.innerText.trim() !== "") {
      return; // If it does, do nothing
    }

    // Get the original text
    const originalText = this.innerText;
    console.log("span", this.innerText);
    translateText(originalText, "zh")
      .then((data) => {
        console.log("result ", data);
        // Show the translated text in the popover
        popover.innerText = data;
      })
      .catch((error) => {
        popover.innerText = "Translation failed";
        console.error("Error:", error);
      });
  });

  span.addEventListener("mouseout", function () {
    this.style.borderBottomColor = "transparent";
  });
});

const translateText = async (text, targetLanguage) => {
  return googleTranslate(text, targetLanguage);
  const url = `https://api.mymemory.translated.net/get?q=${encodeURIComponent(
    text,
  )}&langpair=en|${targetLanguage}&[email protected]`;

  try {
    const response = await fetch(url);

    if (!response.ok) {
      throw new Error("Network response was not ok");
    }

    const result = await response.json();
    const responseData = result.responseData;
    console.log("Translated Text:", result.responseData.translatedText);

    return responseData.translatedText;
  } catch (error) {
    console.error("There was a problem with the fetch operation:", error);
  }
};

const googleTranslate = async (text, targetLanguage) => {
  try {
    const url = `https://translate.googleapis.com/translate_a/t?client=gtx&sl=en&tl=${targetLanguage}&dt=t&q=${encodeURIComponent(text)}&format=html`;
    const response = await fetch(url, {
      method: "POST",
    });
    const data = await response.json();
    return data[0];
  } catch (error) {
    console.error("There was a problem with the fetch operation:", error);
  }
};