Google Auto Translate (Multilingual + Inline Translation)

Auto-translates pages using an iframe overlay and inline Google Translate.

目前为 2025-03-10 提交的版本。查看 最新版本

  1. // ==UserScript==
  2. // @name Google Auto Translate (Multilingual + Inline Translation)
  3. // @namespace https://greasyfork.org/en/users/1030895-universedev
  4. // @author UniverseDev
  5. // @license GPL-3.0-or-later
  6. // @version 1.1
  7. // @description Auto-translates pages using an iframe overlay and inline Google Translate.
  8. // @match *://*/*
  9. // @grant none
  10. // ==/UserScript==
  11.  
  12. (function () {
  13. "use strict";
  14.  
  15. const STORAGE_KEY = "userTranslateLang";
  16. const DEFAULT_LANG = "en";
  17.  
  18. const getUserLanguage = () => localStorage.getItem(STORAGE_KEY) || DEFAULT_LANG;
  19.  
  20. const setUserLanguage = (lang) => {
  21. localStorage.setItem(STORAGE_KEY, lang);
  22. location.reload();
  23. };
  24.  
  25. const detectPageLanguage = () =>
  26. document.documentElement.lang || document.querySelector("html")?.getAttribute("lang") || null;
  27.  
  28. const isAlreadyTranslated = () => {
  29. return document.querySelector("body").classList.contains("translated-ltr") ||
  30. document.querySelector("body").classList.contains("translated-rtl");
  31. };
  32.  
  33. const canEmbedIframe = (url) => {
  34. const iframe = document.createElement("iframe");
  35. iframe.style.display = "none";
  36. iframe.src = url;
  37.  
  38. return new Promise((resolve, reject) => {
  39. iframe.onload = () => resolve(true);
  40. iframe.onerror = () => reject(false);
  41.  
  42. document.body.appendChild(iframe);
  43.  
  44. setTimeout(() => {
  45. document.body.removeChild(iframe);
  46. }, 2000);
  47. });
  48. };
  49.  
  50. const createTranslateOverlay = async (targetLang) => {
  51. const pageLang = detectPageLanguage();
  52. if (pageLang && pageLang.toLowerCase() === targetLang.toLowerCase()) {
  53. return;
  54. }
  55.  
  56. const translateUrl = `https://translate.google.com/translate?hl=${targetLang}&sl=auto&tl=${targetLang}&u=${encodeURIComponent(location.href)}`;
  57.  
  58. const canEmbed = await canEmbedIframe(translateUrl);
  59. if (!canEmbed) {
  60. return;
  61. }
  62.  
  63. if (document.getElementById("googleTranslateIframe")) return;
  64. const iframe = document.createElement("iframe");
  65. iframe.id = "googleTranslateIframe";
  66. iframe.src = translateUrl;
  67. Object.assign(iframe.style, {
  68. position: "fixed",
  69. top: 0,
  70. left: 0,
  71. width: "100vw",
  72. height: "100vh",
  73. border: "none",
  74. zIndex: 99999,
  75. backgroundColor: "#fff",
  76. visibility: "hidden", // Hide initially
  77. });
  78. document.body.appendChild(iframe);
  79.  
  80. iframe.onload = () => iframe.style.visibility = "hidden"; // Hide iframe after translation
  81. };
  82.  
  83. const insertGoogleTranslateWidget = () => {
  84. if (document.querySelector("script[src*='translate_a/element.js']")) {
  85. return;
  86. }
  87.  
  88. const translateDiv = document.createElement("div");
  89. translateDiv.id = "google_translate_element";
  90. Object.assign(translateDiv.style, {
  91. position: "fixed",
  92. bottom: "10px",
  93. right: "10px",
  94. zIndex: 100000,
  95. visibility: "hidden", // Hide initially
  96. });
  97. document.body.appendChild(translateDiv);
  98.  
  99. const script = document.createElement("script");
  100. script.src = "//translate.google.com/translate_a/element.js?cb=googleTranslateInit";
  101. document.body.appendChild(script);
  102.  
  103. script.onload = () => translateDiv.style.visibility = "hidden"; // Hide widget after translation
  104. };
  105.  
  106. window.googleTranslateInit = () => {
  107. new google.translate.TranslateElement(
  108. { pageLanguage: "auto", includedLanguages: getUserLanguage(), autoDisplay: true, multilanguagePage: true },
  109. "google_translate_element"
  110. );
  111.  
  112. const targetLang = getUserLanguage();
  113. const iframe = document.querySelector("iframe.goog-te-banner-frame");
  114. if (iframe) {
  115. const iframeDocument = iframe.contentDocument || iframe.contentWindow.document;
  116. const langSelect = iframeDocument.querySelector("select.goog-te-combo");
  117. if (langSelect) {
  118. langSelect.value = targetLang;
  119. langSelect.dispatchEvent(new Event("change"));
  120. }
  121. }
  122. };
  123.  
  124. const autoTranslateIfNeeded = async () => {
  125. const targetLang = getUserLanguage();
  126. const pageLang = detectPageLanguage();
  127.  
  128. if (document.readyState === "complete" && (!pageLang || pageLang.toLowerCase() !== targetLang.toLowerCase()) && !isAlreadyTranslated()) {
  129. await createTranslateOverlay(targetLang);
  130. } else {
  131. await insertGoogleTranslateWidget();
  132. }
  133. };
  134.  
  135. setTimeout(autoTranslateIfNeeded, 1000);
  136. window.addEventListener("load", autoTranslateIfNeeded);
  137. })();