您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Greasy Fork is available in English.
使用搜狗网页翻译接口将 lynda.com 的字幕译为中文
当前为
// ==UserScript== // @name lynda.com 字幕翻译 // @description 使用搜狗网页翻译接口将 lynda.com 的字幕译为中文 // @namespace https://github.com/journey-ad // @version 0.1 // @author journey-ad // @match *://www.lynda.com/* // @license MIT // @run-at document-end // @grant GM_xmlhttpRequest // ==/UserScript== (function () { "use strict"; // 监听历史记录变化,实现自动翻译每节课程 (function (history) { var pushState = history.pushState; history.pushState = function (state) { if (typeof history.onpushstate == "function") { history.onpushstate({ state: state }); } console.log("章节切换"); unsafeWindow.transTimer = window.setInterval(transText, 1000); // 用定时器检查待翻译文本是否已准备好 return pushState.apply(history, arguments); }; })(unsafeWindow.history); function transText() { if (mejs.players.mep_0.selectedTrack) { // 待翻译文本已准备好 unsafeWindow.clearInterval(unsafeWindow.transTimer); // 清除定时器 console.log("字幕文本可用"); var s = "", r = "", arr = [], num = 0, count = 0; mejs.players.mep_0.selectedTrack.entries.text.forEach(function (e) { s += e.replace(/\r?\n|\r/g, "") + "\n"; }); // 去除每条字幕的换行符并按行排列 // console.log(s); num = translate(s, function (data, index) { // 调用翻译方法并处理回调 count++; arr[index] = data; // 按原始下标放回 if (count >= num) { // 所有翻译文本已取回 r = arr.join(""); mejs.players.mep_0.selectedTrack.entries.text = r.split("\n"); // 翻译文本填回原处 // console.log(r.split('\n')); console.log(r); console.log("翻译完成"); } }); } } function translate(str, callback) { var KEY = "b33bf8c58706155663d1ad5dba4192dc"; // 硬编码于搜狗网页翻译js var textArr = [], count = 1; if (str.length > 5000) { //大于5000字符分块翻译 var strArr = str.split("\n"), i = 0; strArr.forEach(function (v) { textArr[i] = textArr[i] || ""; if ((textArr[i] + v).length < (i + 1) * 5000) { // 若加上此行后长度小于5000字符 textArr[i] += v + "\n"; } else { i++; // 超出则分块 } }); count = i + 1; // 记录块的数量 } else { textArr[0] = str; } var data = { from: "auto", to: "zh-CHS", client: "pc", fr: "browser_pc", text: null, pid: "sogou-dict-vr", useDetect: "on", useDetectResult: "on", oxford: "on", isReturnSugg: "on", needQc: 1, s: null }; textArr.forEach(function (text, index) { // 遍历每块分别进行翻译,在回调中拼接 data.text = text; data.s = md5("autozh-CHS".concat(text).concat(KEY)); // 签名算法 GM_xmlhttpRequest({ method: "POST", url: "https://fanyi.sogou.com/reventondc/translateV1", headers: { accept: "application/json", "content-type": "application/x-www-form-urlencoded; charset=UTF-8" }, data: serialize(data), onload: function onload(response) { var result = JSON.parse(response.responseText); // console.log(result); callback(result.data.translate.dit, index); // 执行回调 } }); }); return count; // 返回分块数量 } function serialize(obj) { return Object.keys(obj) .map(function (k) { return ( encodeURIComponent(k) + "=" + encodeURIComponent(obj[k]).replace("%20", "+") ); }) .join("&"); } function md5(str) { var k = [], i = 0; for (i = 0; i < 64;) { k[i] = 0 | (Math.abs(Math.sin(++i)) * 4294967296); } var b, c, d, j, x = [], str2 = unescape(encodeURI(str)), a = str2.length, h = [(b = 1732584193), (c = -271733879), ~b, ~c]; for (i = 0; i <= a;) { x[i >> 2] |= (str2.charCodeAt(i) || 128) << (8 * (i++ % 4)); } x[(str = ((a + 8) >> 6) * 16 + 14)] = a * 8; i = 0; for (; i < str; i += 16) { a = h; j = 0; for (; j < 64;) { a = [ (d = a[3]), (b = a[1] | 0) + (((d = a[0] + [ (b & (c = a[2])) | (~b & d), (d & b) | (~d & c), b ^ c ^ d, c ^ (b | ~d) ][(a = j >> 4)] + (k[j] + (x[([j, 5 * j + 1, 3 * j + 5, 7 * j][a] % 16) + i] | 0))) << (a = [7, 12, 17, 22, 5, 9, 14, 20, 4, 11, 16, 23, 6, 10, 15, 21][ 4 * a + (j++ % 4) ])) | (d >>> (32 - a))), b, c ]; } for (j = 4; j;) { h[--j] = h[j] + a[j]; } } str = ""; for (; j < 32;) { str += ((h[j >> 3] >> ((1 ^ (j++ & 7)) * 4)) & 15).toString(16); } return str; } })();