GoogleTranslateEngine

googleTranslateEngine

بۇ قوليازمىنى بىۋاسىتە قاچىلاشقا بولمايدۇ. بۇ باشقا قوليازمىلارنىڭ ئىشلىتىشى ئۈچۈن تەمىنلەنگەن ئامبار بولۇپ، ئىشلىتىش ئۈچۈن مېتا كۆرسەتمىسىگە قىستۇرىدىغان كود: // @require https://update.greatest.deepsurf.us/scripts/465512/1185486/GoogleTranslateEngine.js

  1. class TranslateMachine {
  2. constructor() {
  3. this.sessionStorage = {
  4. getItem: async function (key) {
  5. document.defaultView.localStorage.getItem(key);
  6. },
  7. setItem: async function (key, value) {
  8. document.defaultView.localStorage.setItem(key, value);
  9. }
  10. };
  11. this.transdict = {
  12. 谷歌翻译: this.translate_gg.bind(this),
  13. 谷歌翻译mobile: this.translate_ggm.bind(this)
  14. };
  15. this.remove_url = true;
  16. this.show_info = true;
  17. this.fullscrenn_hidden = true;
  18. this.globalProcessingSave = [];
  19. }
  20.  
  21. async init(args1, args2, args3) {
  22. // let rule = {
  23. // name: 'WhatsApp',
  24. // selector: this.baseSelector('nav', 0, '*').bind(this),
  25. // textGetter: this.baseTextGetter.bind(this),
  26. // textSetter: this.baseTextSetter.bind(this)
  27. // };
  28. let rule = null;
  29. if (args1 != null && args2 != null && args3 != null) {
  30. rule = {};
  31. rule.name = '';
  32. rule.selector = this.baseSelector(args1, args2, args3).bind(this);
  33. rule.textGetter = this.baseTextGetter.bind(this);
  34. rule.textSetter = this.baseTextSetter.bind(this);
  35. }
  36. let main = async (_) => {
  37. if (!rule) return;
  38. const choice = '谷歌翻译';
  39. const temp = [...new Set(rule.selector())];
  40. for (let i = 0; i < temp.length; i++) {
  41. const now = temp[i];
  42. if (this.globalProcessingSave.includes(now)) continue;
  43. this.globalProcessingSave.push(now);
  44. const text = this.remove_url ? this.url_filter(rule.textGetter(now)) : rule.textGetter(now);
  45. if (text.length == 0) continue;
  46. if (await this.sessionStorage.getItem(choice + '-' + text)) {
  47. rule.textSetter(now, await this.sessionStorage.getItem(choice + '-' + text));
  48. this.removeItem(this.globalProcessingSave, now);
  49. } else {
  50. this.pass_lang(text)
  51. .then((lang) => this.transdict[choice](text, lang))
  52. .then((s) => {
  53. let result = s['result'];
  54. let origin = s['origin'];
  55. rule.textSetter(now, result);
  56. this.removeItem(this.globalProcessingSave, now);
  57. });
  58. }
  59. }
  60. };
  61. this.PromiseRetryWrap(null).then(() => {
  62. document.js_translater = setInterval(main, 200);
  63. });
  64. }
  65.  
  66. ReviseDom(dom, text, OldText = null) {
  67. this.baseTextSetter(dom, text, OldText);
  68. }
  69.  
  70. pause() {
  71. clearInterval(document.js_translater);
  72. document.js_translater = null;
  73. }
  74.  
  75. resume() {
  76. if (document.js_translater !== null) {
  77. clearInterval(document.js_translater);
  78. }
  79. this.init();
  80. }
  81.  
  82. removeItem(arr, item) {
  83. const index = arr.indexOf(item);
  84. if (index > -1) arr.splice(index, 1);
  85. }
  86.  
  87. baseSelector(selector, parent = 0, childSelector = null) {
  88. return () => {
  89. let items = document.querySelectorAll(selector);
  90. let filteredItems = [];
  91. if (parent !== 0) {
  92. items = Array.prototype.slice.call(items);
  93. items = items.map((item) => {
  94. let currentNode = item;
  95. for (let i = 0; i < parent; i++) {
  96. currentNode = currentNode.parentNode;
  97. }
  98. return currentNode;
  99. });
  100. }
  101. for (let i = 0; i < items.length; i++) {
  102. if (childSelector !== null) {
  103. let childNode = items[i].querySelector(childSelector);
  104. if (childNode !== null) {
  105. filteredItems.push(childNode);
  106. continue;
  107. }
  108. }
  109. const node = items[i].querySelector('[data-translate]');
  110. if (node === null || node.parentNode !== items[i]) {
  111. filteredItems.push(items[i]);
  112. }
  113. }
  114. return filteredItems;
  115. };
  116. }
  117.  
  118. baseTextGetter(e) {
  119. return e.innerText;
  120. }
  121.  
  122. baseTextSetter(e, text, OldText = null) {
  123. if ((text || '').length == 0) text = '翻译异常';
  124. let original = e.innerText;
  125. if (OldText !== null) {
  126. original = OldText;
  127. }
  128. e.innerText = text;
  129. let name = '谷歌翻译';
  130. $(e).attr('data-translate', name);
  131. $(e).css('color', '#40c2af');
  132. $(e)
  133. .parent()
  134. .before("<div data-translate='" + name + "' style='white-space:pre-wrap;'>" + original + '</div>');
  135. let height = $(e).parent().height();
  136. $(e)
  137. .parent()
  138. .css('height', height + 20 + 'px');
  139. }
  140.  
  141. url_filter(text) {
  142. return text.replace(/(https?|ftp|file):\/\/[-A-Za-z0-9+&@#/%?=~_|!:,.;]+[-A-Za-z0-9+&@#/%=~_|]/g, '');
  143. }
  144.  
  145. async pass_lang(raw) {
  146. try {
  147. const result = await this.check_lang(raw);
  148. if (result == 'zh') return new Promise(() => {});
  149. return result;
  150. } catch (err) {
  151. console.log(err);
  152. return;
  153. }
  154. }
  155.  
  156. async check_lang(raw) {
  157. const options = {
  158. method: 'POST',
  159. url: 'https://fanyi.baidu.com/langdetect',
  160. data: 'query=' + encodeURIComponent(raw.replace(/[\uD800-\uDBFF]$/, '').slice(0, 50)),
  161. headers: {
  162. 'Content-Type': 'application/x-www-form-urlencoded'
  163. }
  164. };
  165. const res = await this.Request(options);
  166. try {
  167. let r = res.responseText;
  168. if (typeof r == 'string') {
  169. r = JSON.parse(r).lan;
  170. } else {
  171. r = r.lan;
  172. }
  173. return r;
  174. } catch (err) {
  175. console.log(err);
  176. return;
  177. }
  178. }
  179.  
  180. guid() {
  181. return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
  182. let r = (Math.random() * 16) | 0,
  183. v = c == 'x' ? r : (r & 0x3) | 0x8;
  184. return v.toString(16);
  185. });
  186. }
  187.  
  188. async Translate(raw, sourceLang, targetLang, Record = true) {
  189. let text = await this.sessionStorage.getItem('谷歌翻译' + '-' + raw);
  190. if (text && text != '') {
  191. return new Promise(async (resolve) => {
  192. resolve(text);
  193. });
  194. }
  195. const options = {
  196. method: 'POST',
  197. url: 'https://translate.google.com/_/TranslateWebserverUi/data/batchexecute',
  198. data: `f.req=${encodeURIComponent(JSON.stringify([[['MkEWBc', JSON.stringify([[raw, sourceLang, targetLang, true], [null]]), null, 'generic']]]))}`,
  199. headers: {
  200. 'content-type': 'application/x-www-form-urlencoded',
  201. Host: 'translate.google.com'
  202. },
  203. anonymous: true,
  204. nocache: true
  205. };
  206. return await this.BaseTranslate(
  207. '谷歌翻译',
  208. raw,
  209. options,
  210. function (res) {
  211. var slicedRes = res.slice(res.indexOf('['));
  212. var parsedRes = JSON.parse(slicedRes);
  213. var extractedRes = parsedRes[0][2];
  214. if (typeof extractedRes == 'string') {
  215. extractedRes = JSON.parse(extractedRes);
  216. }
  217. let original = extractedRes[1][4][0];
  218. var finalRes = extractedRes[1][0][0][5]
  219. .map(function (item) {
  220. return item[0];
  221. })
  222. .join('');
  223. return { finalRes, original };
  224. },
  225. Record
  226. );
  227. }
  228.  
  229. async translate_gg(raw) {
  230. const options = {
  231. method: 'POST',
  232. url: 'https://translate.google.com/_/TranslateWebserverUi/data/batchexecute',
  233. data: 'f.req=' + encodeURIComponent(JSON.stringify([[['MkEWBc', JSON.stringify([[raw, 'auto', 'zh-CN', true], [null]]), null, 'generic']]])),
  234. headers: {
  235. 'content-type': 'application/x-www-form-urlencoded',
  236. Host: 'translate.google.com'
  237. },
  238. anonymous: true,
  239. nocache: true
  240. };
  241. return await this.BaseTranslate('谷歌翻译', raw, options, function (res) {
  242. var slicedRes = res.slice(res.indexOf('['));
  243. var parsedRes = JSON.parse(slicedRes);
  244. var extractedRes = parsedRes[0][2];
  245. if (typeof extractedRes == 'string') {
  246. extractedRes = JSON.parse(extractedRes);
  247. }
  248. let original = extractedRes[1][4][0];
  249. var finalRes = extractedRes[1][0][0][5]
  250. .map(function (item) {
  251. return item[0];
  252. })
  253. .join('');
  254. return { finalRes, original };
  255. });
  256. }
  257.  
  258. async translate_ggm(raw) {
  259. const options = {
  260. method: 'GET',
  261. url: 'https://translate.google.com/m?tl=zh-CN&q=' + encodeURIComponent(raw),
  262. headers: {
  263. Host: 'translate.google.com'
  264. },
  265. anonymous: true,
  266. nocache: true
  267. };
  268. return await this.BaseTranslate('谷歌翻译mobile', raw, options, (res) => /class="result-container">((?:.|\n)*?)<\/div/.exec(res)[1]);
  269. }
  270.  
  271. tk(a, b) {
  272. var d = b.split('.');
  273. b = Number(d[0]) || 0;
  274. for (var e = [], f = 0, g = 0; g < a.length; g++) {
  275. var k = a.charCodeAt(g);
  276. 128 > k ? (e[f++] = k) : (2048 > k ? (e[f++] = (k >> 6) | 192) : (55296 == (k & 64512) && g + 1 < a.length && 56320 == (a.charCodeAt(g + 1) & 64512) ? ((k = 65536 + ((k & 1023) << 10) + (a.charCodeAt(++g) & 1023)), (e[f++] = (k >> 18) | 240), (e[f++] = ((k >> 12) & 63) | 128)) : (e[f++] = (k >> 12) | 224), (e[f++] = ((k >> 6) & 63) | 128)), (e[f++] = (k & 63) | 128));
  277. }
  278. a = b;
  279. for (f = 0; f < e.length; f++) a = Fo(a + e[f], '+-a^+6');
  280. a = Fo(a, '+-3^+b+-f');
  281. a ^= Number(d[1]) || 0;
  282. 0 > a && (a = (a & 2147483647) + 2147483648);
  283. a %= 1e6;
  284. return a.toString() + '.' + (a ^ b);
  285. }
  286. Fo(a, b) {
  287. for (var c = 0; c < b.length - 2; c += 3) {
  288. var d = b.charAt(c + 2);
  289. d = 'a' <= d ? d.charCodeAt(0) - 87 : Number(d);
  290. d = '+' == b.charAt(c + 1) ? a >>> d : a << d;
  291. a = '+' == b.charAt(c) ? (a + d) & 4294967295 : a ^ d;
  292. }
  293. return a;
  294. }
  295.  
  296. async PromiseRetryWrap(task, options, ...values) {
  297. const { RetryTimes, ErrProcesser } = options || {};
  298. let retryTimes = RetryTimes || 5;
  299. const usedErrProcesser =
  300. ErrProcesser ||
  301. ((err) => {
  302. throw err;
  303. });
  304. if (!task) return;
  305. while (true) {
  306. try {
  307. return await task(...values);
  308. } catch (err) {
  309. if (!--retryTimes) {
  310. console.log(err);
  311. return usedErrProcesser(err);
  312. }
  313. }
  314. }
  315. }
  316.  
  317. async BaseTranslate(name, raw, options, processer, Record = true) {
  318. const toDo = async () => {
  319. var tmp;
  320. try {
  321. const data = await this.Request(options);
  322. tmp = data.responseText;
  323. const { finalRes, original } = await processer(tmp);
  324. let result = finalRes;
  325. if (result) {
  326. try {
  327. if (Record) {
  328. await this.sessionStorage.setItem(name + '-' + raw, result).bind(this);
  329. }
  330. } catch (e) {}
  331. }
  332. return { result, original };
  333. } catch (err) {
  334. throw {
  335. responseText: tmp,
  336. err: err
  337. };
  338. }
  339. };
  340. return await this.PromiseRetryWrap(toDo, { RetryTimes: 3, ErrProcesser: () => '翻译出错' });
  341. }
  342.  
  343. Request(options) {
  344. return new Promise(async (resolve) => {
  345. options.onload = function (res) {
  346. if (res.status !== 200) {
  347. resolve('');
  348. return;
  349. }
  350. resolve(res);
  351. };
  352. GM_xmlhttpRequest(options);
  353. });
  354. }
  355. }