// ==UserScript== // @name DeepL Document Translator // @namespace deeplx.net/gm-deepl // @version 1.0.1 // @author deeplx.net // @description You can use it to translate DeepL documents。 // @license MIT // @copyright https://t.me/chatwithares_bot // @icon data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAADPElEQVRYhb2XX0hTcRTHv+eaoaa5EFwsGGoIRkYLeigpsMIlKDihhxgJ7bG9aJBg9DD3EBQEuR6qp/yXvvSgPQzmFcwHM8iHljoxcjYGjqY93GXG5sjTgyHu3rt5r5t933Z+Z7/v53d+557dAVnIYLEZsvk+ANB+jbc2f7eTgA4wJGb0/VwQ3f8FwFDbWM+81QugQrYUIrBbCoz3HQiAwdJYwUnuBbg+Ux6D+oR8ckt+XygnALJya75zZnQLh4s8kn9UypSXl9H8lNXGnBwhgg1AgVZzACBCPbaSNwvLq2LxtWV/2jxVY0uDhZPC073KrUN+yhda1a5FkAeO1lpdnKRPauZdzjbMigMYeuaC+YRRD4CFk1vfDKeud8gXDskDBNjUdrDbGtDlvAUAMJuMKC0pRrOjUw8EWOB2AD27Y4oKpGs0syn1xDorkFZKgDSamplVAM2KA7DbGrICUDwFBeUnOwBlFcKRKLwT00gkNtH7xov7j1/CbrPC3mKF2XQcc1+CiK1v7OUnJdaCnt0BxVNQetr6Dcopl1bbvdEGs8mIF69HcOn8WQAM78QHPHo+KE8PxQJiZU4BgO1+sLdsg+zW5RtOzC0GMwJo7oFMCq9E8WJwVBVsL+UEoPToEcTWf6U0ajgSlZ9eVYo5oFddzjbcaWtFs6MTzY5O2G0NKC0phndiGuGVaG4Bmq5dRNOVOsx9WcbcYhDPH96D2WTE8KiIcOQ7AGB4dFzXATQDNF2tw5DHlRKbmpmF88ETxYw4EIAzNVUpn8ORqO5RrKZ9T8Kpj5+zNgdUJmGhsaoSoAvyeDgSRTgS/ddg7+H2vEIikdRlRkz98bWgLyWmlmg43XibwS6AK3Q5pHWGRExuKTDWI19SfSOKry35C8uq35LAxwBYsvJm8tBGUav01TupzraHDDWNFZzH7/RWg4gmAXJL8z5VY80AOyA6roUYbmlB7Nayb8aX0t3auZY8jgGoT2sOmpQWRIfWfTUDAED8x5IUXw1OFpZV96frDxLy7sZXlxa17rmvHyNp0ReSAuJtguAAKJSyyJzxf0BOAHZAAr6+WGCskghuALqMcwKwAzIvdtMf4RwB/bnY77/qL0WZNmzvXT5nAAAAAElFTkSuQmCC // @icon64 data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAMAAACdt4HsAAAAOVBMVEVHcEwPK0cPK0YPK0YPK0YPK0YPK0YPK0YPK0YPK0f///8AIT8ADjU4TGJndIPW2t7r7vCUnqi8w8msDOqtAAAACnRSTlMAO/T/q95SyX8W0MSMfAAAAexJREFUWIW1l9uWgyAMRUexXgj3///YCVgpKhALq+ehqw+T3RBOQubv79fauqKHhbHX0B4/Ma9xaoveVha1NhzEZ//RMn8bPrGLpq9KsY7XeCzF+jh8zoQHzY9KsS2FcF8KmrDdDn8pBYFYX/V49FWtFDMZHhClK02dw0AIgAJhzJ9jPv2RddqqEgGtScQLzb0qhLut0uqD5Zwg3BssuX2Q+g2wRcBSB5g3wIkmAIsAI0op1AHg+CHL8ggCICOAa5XNog5AgjNGWxkycSpTCQLAAKSUAML6+zAWUEKkqVAAz/AfQlhfUKOk1doltngAeEvs57ha8zkA2yr6ivOGDMJhVLxVaAGg4qWKNgAcANcIEEcVZMMRcDABqL07XMMtgNLcQ5w2OrEkDYAwEkE4/G3nv0nJvnAi3pxS+BlGk9n9c+opAiAwb26cCrWzMtOORDtH42D6sqGdIXoXs28YKJ+ZqBtHWvdQZZ1jnR3dZ3L1LwHSl5UJS8RnHsft9LSDslZV4l+59/m0WQEUX/fy6jnUh0rUUt74hgcrSn13Pm0pWZFbb31No5a0oPKqVVyvrsove9UF78E5HmWfIK5XevcupfPal1vsSJ2s2QI4/dvRBMBzLJ2AjzVbAahp7ATsLdYDCO7uA6A1OwE/1D8U3Cg7PPY0qQAAAABJRU5ErkJggg== // @homepage https://t.me/chatwithares_bot // @homepageURL https://t.me/chatwithares_bot // @website https://t.me/chatwithares_bot // @supportURL https://t.me/chatwithares_bot // @match https://www.deepl.com/** // @match https://www5.deepl.com/** // @require https://registry.npmmirror.com/tampermonkey-jquery/1.0.0/files/dist/jquery-3.7.1.min.js // @require https://registry.npmmirror.com/ajax-hook/3.0.3/files/dist/ajaxhook.min.js // @require https://registry.npmmirror.com/i18n-js/4.4.3/files/dist/browser/index.js // @connect doc.deeplx.net // @grant GM_addStyle // @grant unsafeWindow // @run-at document-start // @downloadURL https://update.greasyfork.icu/scripts/497640/DeepL%20Document%20Translator.user.js // @updateURL https://update.greasyfork.icu/scripts/497640/DeepL%20Document%20Translator.meta.js // ==/UserScript== (function (ajaxHook, i18nJs, $) { 'use strict'; var _GM_addStyle = /* @__PURE__ */ (() => typeof GM_addStyle != "undefined" ? GM_addStyle : void 0)(); var _unsafeWindow = /* @__PURE__ */ (() => typeof unsafeWindow != "undefined" ? unsafeWindow : void 0)(); const originalFetch = _unsafeWindow.fetch; _unsafeWindow.fetch = async (...args) => { const [resource, config] = args; const response = await originalFetch(resource, config); if (response.status === 200 && resource.includes("method=getClientState")) { const json = await response.json(); json.result.featureSet.translator.service = "pro"; json.result.featureSet.translator.formality = true; json.result.featureSet.documentTranslation.sizeLimits.doc = 20; json.result.featureSet.documentTranslation.sizeLimits.docx = 20; json.result.featureSet.documentTranslation.sizeLimits.pdf = 20; json.result.featureSet.documentTranslation.sizeLimits.pptx = 20; json.result.featureSet.documentTranslation.sizeLimits.xlsx = 20; json.result.featureSet.documentTranslation.sizeLimits.txt = 1; json.result.featureSet.documentTranslation.sizeLimits.html = 5; json.result.featureSet.documentTranslation.sizeLimits.xlf = 10; json.result.featureSet.documentTranslation.sizeLimits.xliff = 10; return new Response(JSON.stringify(json), { status: response.status }); } return response; }; const key = "last-DocumentIdAndKey"; const rootURL = "https://doc.deeplx.net"; const baseURL = `${rootURL}/api`; const donateURL = `https://taobao.starxg.com/open/go?id=ad514f848fe040548e61a51f06d167e4`; const lkxResourceId = "2"; const getLastDocumentIdAndKey = () => { const item = sessionStorage.getItem(key); try { if (item) { return JSON.parse(item); } } catch { } return null; }; const setLastDocumentIdAndKey = (e) => { sessionStorage.setItem(key, JSON.stringify(e)); }; const i18n = new i18nJs.I18n({ en: { NotWork: `The plugin doesn't seem to be working, click “OK” to refresh the page.`, WeChat: "WeChat", HelpText: "Do you need help?", WeChatVerify: "WeChatVerify", CancelDownload: `Cancel, I'm not downloading.`, ScanTip: 'Scan the QR code with WeChat and click "获取资源". (Free)', AutoDownloadTip: "The page will download automatically after getting the resource", CantScan: `I don't have WeChat or can't verify.`, DownloadAfter: 'The download is about to start, remember to click "Leave" or "Confirm" in the pop-up window.', ManuallyClose: "This window will close automatically after a few seconds, or manually click Cancel.", DownloadComplete: `Click "Cancel" when the download is complete.`, DocLimit: "File limit 20MB/1,000,000 characters", NewVersionAvailable: "Please refresh the page to update to the latest version", TranslateError: "Translation failed, please refresh the page to retranslate", TelegramNotice: `DeepL may be updated in the near future, please join the Telegram channel.` }, zh: { NotWork: "插件似乎没有生效,点击 “确定” 刷新页面。", WeChat: "微信", HelpText: "有任何问题请联系我", WeChatVerify: "微信验证", CancelDownload: `取消,我不下载。`, ScanTip: "微信扫码,然后点击“获取资源”。(完全免费)", AutoDownloadTip: "获取资源后页面会自动下载", CantScan: `我没有微信或不能完成验证`, DownloadAfter: "下载即将开始,弹窗记得点击“离开”或“确认”。", ManuallyClose: "此窗口将在几秒后自动关闭,或手动点击取消。", DownloadComplete: `下载完成后可以点击“取消”`, TranslateError: `翻译失败,请刷新页面重新翻译`, DocLimit: "文件限制20MB/100万字符", NewVersionAvailable: "请刷新页面更新到最新版", TelegramNotice: `DeepL 可能会在近期更新,请加入 Telegram 频道。` } }); i18n.enableFallback = true; const getI18nextLng = () => { return _unsafeWindow.localStorage.getItem("i18nextLng") === "zh" ? "zh" : "en"; }; const t = (scope, options) => { i18n.locale = getI18nextLng(); return i18n.t(scope, options); }; ajaxHook.proxy({ onRequest: (config, handler) => { if (config.url.startsWith("https://document-translation-pro.www.deepl.com/documentTranslation/upload")) { config.url = `${baseURL}/documentTranslation/upload` + config.url.substring(config.url.indexOf("?")); if (config.body instanceof FormData) { const e = config.body.get("file"); if (e) { const k = getLastDocumentIdAndKey() || {}; k.fileName = e.name; setLastDocumentIdAndKey(k); } } } else if (config.url.startsWith("https://document-translation-pro.www.deepl.com/documentTranslation")) { config.url = `${baseURL}/documentTranslation` + config.url.substring(config.url.indexOf("?")); try { const e = JSON.parse(config.body).params.documentIdAndKey; if (e) { setLastDocumentIdAndKey(Object.assign(getLastDocumentIdAndKey() || {}, e)); } } catch { } } else if (config.url.startsWith("https://api.deepl.com/jsonrpc")) { config.url = config.url.replace("https://api.deepl.com/jsonrpc", "https://www2.deepl.com/jsonrpc"); } if (config.url.startsWith("https://document-translation-free.www.deepl.com/documentTranslation/upload")) { if (confirm(t("NotWork"))) { location.reload(); return; } } handler.next(config); }, onError: (err, handler) => { handler.next(err); }, onResponse: (response, handler) => { handler.next(response); } }, _unsafeWindow); $(_unsafeWindow).on("load", () => { const timer = setInterval(() => { const e = $(".contents[role=tablist]"); if (e.length < 1) { return; } clearInterval(timer); e.append($(``).on("click", () => { location.href = "https://www5.deepl.com/translator/files"; })); if (getI18nextLng() === "zh") { e.append($(`
`)); e.append($(`
`)); } else { e.append($(`
`)); e.append($(`
`)); } }, 1e3); }); _GM_addStyle(` button[data-testid=doctrans-translation-with-edits-button]{ display:none; } .textUpper--qwA4g { color: #006494; font-size: 16px; font-style: normal; font-weight: 600; line-height: 22px; } .textLower--qKcBG { color: #6e6e6e; font-size: 14px; font-style: normal; font-weight: 400; line-height: 20px; } `); const downloadFile = (e, ticket, token) => { const $form = $("
").attr("action", `${baseURL}/documentTranslation/download?lkx-ticket=${ticket}&lkx-token=${token}&lkx-resourceId=${lkxResourceId}`).attr("method", "post").hide(); $form.append($("").attr("type", "hidden").attr("name", "documentId").val(e.documentId)); $form.append($("").attr("type", "hidden").attr("name", "documentKey").val(e.documentKey)); $form.append($("").attr("type", "hidden").attr("name", "fileName").val(e.fileName)); $form.append($("").attr("type", "hidden").attr("name", "expectsPro").val("true")); $(document.body).append($form); $form.trigger("submit"); }; const openTicketDialog = (k) => { let isDone = false; let isCancel = false; const $ele = $(`
${t("WeChatVerify")}
${t("ScanTip")}
${t("AutoDownloadTip")}

${t("DownloadAfter")}
${t("ManuallyClose")}
${t("CantScan")}
`); $ele.find(".tip").hide(); $ele.find(".qrcode-success").hide(); $(document.body).append($ele).css("overflow", "hidden"); $ele.on("click", ".close-scan-qr", function() { document.querySelectorAll(".scan-qr").forEach((e) => { var _a; (_a = e.parentNode) == null ? void 0 : _a.removeChild(e); }); document.body.style.overflow = "auto"; isCancel = true; }); $ele.on("click", ".cantverify", function() { if (getI18nextLng() === "zh") { window.open(`${rootURL}/deepl-translator/wx.png?r=${Math.random()}`, "_blank"); } else { $ele.find(".cantverify").hide(); skipVerify(); } return false; }); function skipVerify(ticket = "skip", token = "skip") { isDone = true; $ele.find(".tip").show(); $ele.find(".qrcode-success").show(); $ele.find(".qr-tip").hide(); setTimeout(function() { $ele.remove(); }, 1e3 * 10); downloadFile(k, ticket, token); } function loop(ticket) { if (isCancel || isDone) { return; } $.ajax({ url: `https://api.likexiang.com/openapi/experimental/resource/ticket/status?ticket=${ticket}`, dataType: "json", success: function(res) { isDone = res.status === "fetched"; if (isDone) { skipVerify(ticket, res.token); } }, complete: function() { setTimeout(function() { loop(ticket); }, 1e3); } }); } $.ajax({ url: `https://api.likexiang.com/openapi/experimental/resource/ticket/create`, dataType: "jsonp", data: { resourceId: lkxResourceId }, success: function(res) { $ele.find(".qrcode").prop("src", res.qrcode); loop(res.ticket); } }); }; $(_unsafeWindow).on("load", () => { const observer = new MutationObserver((mutations) => { mutations.forEach(function(mutation) { const ele = $(mutation.target).find("button[data-testid=doctrans-upload-result-download]"); if (ele.length > 0) { const e = ele.clone(); e.attr("data-testid", ""); e.on("click", () => { const k = getLastDocumentIdAndKey(); if (k) { e.text(t("DownloadComplete")); if (getI18nextLng() === "zh") { openTicketDialog(k); } else { downloadFile(k, "skip", "skip"); } } else { alert(t("TranslateError")); } }); ele.parent().append(e); ele.remove(); } }); }); observer.observe(document.body, { childList: true, subtree: true }); }); $(_unsafeWindow).on("load", () => { if (getI18nextLng() !== "zh") { $.ajax({ url: "https://api.ip.sb/geoip", dataType: "jsonp", success: function(res) { if (["TW", "HK", "CN"].includes(res.country_code)) { _unsafeWindow.location.href = location.origin + "/zh/translator"; } } }); } }); })(ah, I18n, jQuery);