Google Translate API Library

Google Translate API Library for UserScripts

目前为 2024-12-23 提交的版本。查看 最新版本

此脚本不应直接安装,它是一个供其他脚本使用的外部库。如果您需要使用该库,请在脚本元属性加入:// @require https://update.gf.qytechs.cn/scripts/521561/1508140/Google%20Translate%20API%20Library.js

  1. // ==UserScript==
  2. // @name Google Translate API Library
  3. // @namespace http://tampermonkey.net/
  4. // @version 2024.12.23.1
  5. // @description Google Translate API Library for UserScripts
  6. // @author Yuusei
  7. // @grant GM_xmlhttpRequest
  8. // @icon https://cdn-icons-png.flaticon.com/512/9502/9502737.png
  9. // ==/UserScript==
  10.  
  11. const GoogleTranslateAPI = (function () {
  12. 'use strict';
  13.  
  14. const translationCache = new Map();
  15.  
  16. const CACHE_EXPIRY = 24 * 60 * 60 * 1000;
  17.  
  18. const languages = {
  19. auto: 'Automatic',
  20. af: 'Afrikaans',
  21. sq: 'Albanian',
  22. am: 'Amharic',
  23. ar: 'Arabic',
  24. hy: 'Armenian',
  25. az: 'Azerbaijani',
  26. eu: 'Basque',
  27. be: 'Belarusian',
  28. bn: 'Bengali',
  29. bs: 'Bosnian',
  30. bg: 'Bulgarian',
  31. ca: 'Catalan',
  32. ceb: 'Cebuano',
  33. ny: 'Chichewa',
  34. 'zh-cn': 'Chinese Simplified',
  35. 'zh-tw': 'Chinese Traditional',
  36. co: 'Corsican',
  37. hr: 'Croatian',
  38. cs: 'Czech',
  39. da: 'Danish',
  40. nl: 'Dutch',
  41. en: 'English',
  42. eo: 'Esperanto',
  43. et: 'Estonian',
  44. tl: 'Filipino',
  45. fi: 'Finnish',
  46. fr: 'French',
  47. fy: 'Frisian',
  48. gl: 'Galician',
  49. ka: 'Georgian',
  50. de: 'German',
  51. el: 'Greek',
  52. gu: 'Gujarati',
  53. ht: 'Haitian Creole',
  54. ha: 'Hausa',
  55. haw: 'Hawaiian',
  56. iw: 'Hebrew',
  57. hi: 'Hindi',
  58. hmn: 'Hmong',
  59. hu: 'Hungarian',
  60. is: 'Icelandic',
  61. ig: 'Igbo',
  62. id: 'Indonesian',
  63. ga: 'Irish',
  64. it: 'Italian',
  65. ja: 'Japanese',
  66. jw: 'Javanese',
  67. kn: 'Kannada',
  68. kk: 'Kazakh',
  69. km: 'Khmer',
  70. ko: 'Korean',
  71. ku: 'Kurdish (Kurmanji)',
  72. ky: 'Kyrgyz',
  73. lo: 'Lao',
  74. la: 'Latin',
  75. lv: 'Latvian',
  76. lt: 'Lithuanian',
  77. lb: 'Luxembourgish',
  78. mk: 'Macedonian',
  79. mg: 'Malagasy',
  80. ms: 'Malay',
  81. ml: 'Malayalam',
  82. mt: 'Maltese',
  83. mi: 'Maori',
  84. mr: 'Marathi',
  85. mn: 'Mongolian',
  86. my: 'Myanmar (Burmese)',
  87. ne: 'Nepali',
  88. no: 'Norwegian',
  89. ps: 'Pashto',
  90. fa: 'Persian',
  91. pl: 'Polish',
  92. pt: 'Portuguese',
  93. pa: 'Punjabi',
  94. ro: 'Romanian',
  95. ru: 'Russian',
  96. sm: 'Samoan',
  97. gd: 'Scots Gaelic',
  98. sr: 'Serbian',
  99. st: 'Sesotho',
  100. sn: 'Shona',
  101. sd: 'Sindhi',
  102. si: 'Sinhala',
  103. sk: 'Slovak',
  104. sl: 'Slovenian',
  105. so: 'Somali',
  106. es: 'Spanish',
  107. su: 'Sundanese',
  108. sw: 'Swahili',
  109. sv: 'Swedish',
  110. tg: 'Tajik',
  111. ta: 'Tamil',
  112. te: 'Telugu',
  113. th: 'Thai',
  114. tr: 'Turkish',
  115. uk: 'Ukrainian',
  116. ur: 'Urdu',
  117. uz: 'Uzbek',
  118. vi: 'Vietnamese',
  119. cy: 'Welsh',
  120. xh: 'Xhosa',
  121. yi: 'Yiddish',
  122. yo: 'Yoruba',
  123. zu: 'Zulu',
  124. };
  125.  
  126. function validateLanguage(language) {
  127. if (!language) {
  128. throw new Error('Language cannot be empty');
  129. }
  130. const isoCode = getISOCode(language);
  131. if (!isoCode) {
  132. throw new Error(`Language not supported: ${language}`);
  133. }
  134. return isoCode;
  135. }
  136.  
  137. function getISOCode(language) {
  138. if (!language) return false;
  139. language = language.toLowerCase();
  140. if (language in languages) return language;
  141.  
  142. let keys = Object.keys(languages).filter(key => {
  143. if (typeof languages[key] !== 'string') return false;
  144. return languages[key].toLowerCase() === language;
  145. });
  146.  
  147. return keys[0] || false;
  148. }
  149.  
  150. function isSupported(language) {
  151. return Boolean(getISOCode(language));
  152. }
  153.  
  154. function getCacheKey(text, options) {
  155. return `${text}|${options.from}|${options.to}`;
  156. }
  157.  
  158. function getFromCache(text, options) {
  159. const key = getCacheKey(text, options);
  160. const cached = translationCache.get(key);
  161. if (cached && Date.now() - cached.timestamp < CACHE_EXPIRY) {
  162. return cached.result;
  163. }
  164. return null;
  165. }
  166.  
  167. function saveToCache(text, options, result) {
  168. const key = getCacheKey(text, options);
  169. translationCache.set(key, {
  170. result,
  171. timestamp: Date.now(),
  172. });
  173. }
  174.  
  175. async function translate(text, options = {}) {
  176. if (!text) throw new Error('Text cannot be empty');
  177.  
  178. options.from = options.from || 'auto';
  179. options.to = options.to || 'en';
  180.  
  181. options.from = validateLanguage(options.from);
  182. options.to = validateLanguage(options.to);
  183.  
  184. const cached = getFromCache(text, options);
  185. if (cached) return cached;
  186.  
  187. let baseUrl = 'https://translate.googleapis.com/translate_a/single';
  188. let data = {
  189. client: 'gtx',
  190. sl: options.from,
  191. tl: options.to,
  192. dt: 't',
  193. q: text,
  194. };
  195.  
  196. let url = `${baseUrl}?` + new URLSearchParams(data).toString();
  197.  
  198. return new Promise((resolve, reject) => {
  199. GM_xmlhttpRequest({
  200. method: 'GET',
  201. url: url,
  202. headers: {
  203. 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
  204. Accept: '*/*',
  205. },
  206. timeout: 10000,
  207. onload: function (response) {
  208. try {
  209. if (response.status !== 200) {
  210. throw new Error(`HTTP Error: ${response.status}`);
  211. }
  212.  
  213. const body = JSON.parse(response.responseText);
  214.  
  215. if (!body || !Array.isArray(body) || !body[0]) {
  216. throw new Error('Invalid response structure');
  217. }
  218.  
  219. let result = {
  220. text: '',
  221. from: {
  222. language: {
  223. didYouMean: false,
  224. iso: body[2] || options.from,
  225. },
  226. text: {
  227. autoCorrected: false,
  228. value: '',
  229. didYouMean: false,
  230. },
  231. },
  232. raw: body,
  233. };
  234.  
  235. result.text = body[0]
  236. .filter(chunk => chunk && chunk[0])
  237. .map(chunk => decodeURIComponent(chunk[0].trim()))
  238. .join(' ')
  239. .trim();
  240.  
  241. saveToCache(text, options, result);
  242.  
  243. resolve(result);
  244. } catch (error) {
  245. reject(new Error('Error processing response: ' + error.message));
  246. }
  247. },
  248. onerror: function (error) {
  249. reject(new Error('Connection error: ' + error));
  250. },
  251. ontimeout: function () {
  252. reject(new Error('Timeout: Request took too long'));
  253. },
  254. });
  255. });
  256. }
  257.  
  258. async function translateWithRetry(text, options = {}, maxRetries = 3, delay = 1000) {
  259. let lastError;
  260. for (let i = 0; i < maxRetries; i++) {
  261. try {
  262. return await translate(text, options);
  263. } catch (error) {
  264. lastError = error;
  265. console.log(`Try ${i + 1}/${maxRetries} failed:`, error);
  266. if (i < maxRetries - 1) {
  267. await new Promise(resolve => setTimeout(resolve, delay * Math.pow(2, i)));
  268. await new Promise(resolve => setTimeout(resolve, delay * Math.pow(2, i)));
  269. }
  270. }
  271. }
  272. throw new Error(`Translation failed after ${maxRetries} attempts: ${lastError.message}`);
  273. }
  274.  
  275. function clearExpiredCache() {
  276. const now = Date.now();
  277. for (const [key, value] of translationCache.entries()) {
  278. if (now - value.timestamp > CACHE_EXPIRY) {
  279. translationCache.delete(key);
  280. }
  281. }
  282. }
  283.  
  284. setInterval(clearExpiredCache, 60 * 60 * 1000);
  285.  
  286. return {
  287. translate,
  288. translateWithRetry,
  289. languages,
  290. getISOCode,
  291. isSupported,
  292. clearExpiredCache,
  293. };
  294. })();
  295.  
  296. if (typeof module !== 'undefined' && module.exports) {
  297. module.exports = GoogleTranslateAPI;
  298. }

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址