Greasy Fork

Greasy Fork is available in English.

选译替换器TransReplace

翻译选中的文本并替换

您需要先安装一个扩展,例如 篡改猴Greasemonkey暴力猴,之后才能安装此脚本。

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

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴Userscripts ,之后才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。

您需要先安装用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name        选译替换器TransReplace
// @namespace   vurses
// @license     Mit
// @author      layenh
// @match       https://web.telegram.org/*
// @match       https://webk.telegram.org/*
// @match       https://webz.telegram.org/*
// @match       https://fanyi.sogou.com/*
// @match       *://*/*
// @grant       GM.xmlhttpRequest
// @grant       GM_xmlhttpRequest
// @grant       GM.getValue
// @grant       GM_getValue
// @grant       GM.setValue
// @grant       GM_setValue
// @connect     fanyi.sogou.com
// @run-at      document-end
// @version     1.0
// @noframes
// @require     https://update.greasyfork.icu/scripts/533087/1572495/WbiSign.js
// @require     https://update.greasyfork.icu/scripts/534967/1583188/langSwitcher.js
// @description 翻译选中的文本并替换
// ==/UserScript==

// 获取cookie和secretCode
let sogouCookie = GM_getValue("sogouCookie", "");
let secretCode = GM_getValue("secretCode", "");
if (location.href.includes("fanyi.sogou.com")) {
  sogouCookie = document.cookie;
  GM_setValue("sogouCookie", sogouCookie);
  window.addEventListener("load", () => {
    secretCode = unsafeWindow.__INITIAL_STATE__.common.CONFIG.secretCode;
    GM_setValue("secretCode", secretCode);
  });
}
// 注入语言菜单
window.addEventListener("load", () => {
  document.documentElement.appendChild(createLangSwitcher(GM_setValue, GM_getValue));
});
// uuid生成
function uuidGen() {
  let t,
    n,
    r = "";
  for (t = 0; t < 32; t++) {
    (n = (16 * Math.random()) | 0),
      (8 !== t && 12 !== t && 16 !== t && 20 !== t) || (r += "-");
    const e = 3 & n,
      o = 16 === t ? 8 | e : n;
    r += (12 === t ? 4 : o).toString(16);
  }
  return r;
}
// 简易封装xhr
const gm_xhr = function (data) {
  return new Promise((resolve, reject) => {
    GM_xmlhttpRequest({
      method: "POST",
      url: "https://fanyi.sogou.com/api/transpc/text/result",
      data: JSON.stringify(data),
      headers: {
        "Content-Type": "application/json",
        Accept: "application/json, text/plain, */*",
      },
      cookie: sogouCookie,
      onload: resolve,
      onerror: reject,
    });
  }).then((response) => {
    return response.responseText;
  });
};
// 监听是否替换翻译文本
document.addEventListener("keydown", (event) => {
  if (event.shiftKey) {
    const activeElement = document.activeElement;
    console.log(activeElement)
    if (
      activeElement.tagName === "INPUT" ||
      activeElement.tagName === "TEXTAREA" ||
      activeElement.isContentEditable
    ) {
      const selectedText = window.getSelection().toString().trim();
      console.log(selectedText)
      if (selectedText) {
        // 初始语言类型,可以是auto
        const from = "auto";
        // 目标语言类型
        const to = GM_getValue("selectedLang", "zh-CHS");
        // 初始语言内容
        const text = selectedText;
        const keyS = SparkMD5.hash(
          "".concat(from).concat(to).concat(text).concat(secretCode)
        );
        const uuid = uuidGen();
        const data = {
          client: "pc",
          exchange: false,
          fr: "browser_pc",
          from,
          needQc: 1,
          s: keyS,
          text,
          to: GM_getValue("selectedLang", "zh-CHS"),
          uuid: uuid,
        };
        gm_xhr(data)
          .then((res) => {
            const translatedText = JSON.parse(res).data.translate.dit || "";
            if (translatedText === "") throw "api 错误";
            if (
              activeElement.tagName === "INPUT" ||
              activeElement.tagName === "TEXTAREA"
            ) {
              const start = activeElement.selectionStart;
              const end = activeElement.selectionEnd;
              const originalValue = activeElement.value;
              activeElement.value =
                originalValue.slice(0, start) +
                translatedText +
                originalValue.slice(end);
              // 可选:重新设置光标位置
              activeElement.selectionStart = activeElement.selectionEnd =
                start + translatedText.length;
              // ✅ 触发 input 事件(使得 Vue/React 等响应变化)
              const event = new Event("input", { bubbles: true });
              activeElement.dispatchEvent(event);
            } else if (activeElement.isContentEditable) {
              const selection = window.getSelection();
              if (!selection.rangeCount) return;
              const range = selection.getRangeAt(0);
              range.deleteContents();
              range.insertNode(document.createTextNode(translatedText));
              // 可选:移动光标到插入后的位置
              range.collapse(false);
              selection.removeAllRanges();
              selection.addRange(range);
            }
          })
          .catch((e) => {
            console.log(e);
            location.href = "https://fanyi.sogou.com";
          });
      }
    }
  }
});