Ezt a szkriptet nem ajánlott közvetlenül telepíteni. Ez egy könyvtár más szkriptek számára, amik tartalmazzák a // @require https://update.greasyfork.org/scripts/521561/1508824/Google%20Translate%20API%20Library.js
hivatkozást.
// ==UserScript==
// @name Google Translate API Library
// @namespace http://tampermonkey.net/
// @version 2024.12.24.2
// @description Google Translate API Library for UserScripts
// @author Yuusei
// @grant GM_xmlhttpRequest
// @icon https://cdn-icons-png.flaticon.com/512/9502/9502737.png
// ==/UserScript==
const GoogleTranslateAPI = (function () {
'use strict';
const translationCache = new Map();
const CACHE_EXPIRY = 24 * 60 * 60 * 1000;
const MAX_BATCH_SIZE = 128;
const MAX_RETRIES = 3;
const RETRY_DELAY = 1000;
const languages = {
auto: 'Automatic',
af: 'Afrikaans',
sq: 'Albanian',
am: 'Amharic',
ar: 'Arabic',
hy: 'Armenian',
az: 'Azerbaijani',
eu: 'Basque',
be: 'Belarusian',
bn: 'Bengali',
bs: 'Bosnian',
bg: 'Bulgarian',
ca: 'Catalan',
ceb: 'Cebuano',
ny: 'Chichewa',
'zh-cn': 'Chinese Simplified',
'zh-tw': 'Chinese Traditional',
co: 'Corsican',
hr: 'Croatian',
cs: 'Czech',
da: 'Danish',
nl: 'Dutch',
en: 'English',
eo: 'Esperanto',
et: 'Estonian',
tl: 'Filipino',
fi: 'Finnish',
fr: 'French',
fy: 'Frisian',
gl: 'Galician',
ka: 'Georgian',
de: 'German',
el: 'Greek',
gu: 'Gujarati',
ht: 'Haitian Creole',
ha: 'Hausa',
haw: 'Hawaiian',
iw: 'Hebrew',
hi: 'Hindi',
hmn: 'Hmong',
hu: 'Hungarian',
is: 'Icelandic',
ig: 'Igbo',
id: 'Indonesian',
ga: 'Irish',
it: 'Italian',
ja: 'Japanese',
jw: 'Javanese',
kn: 'Kannada',
kk: 'Kazakh',
km: 'Khmer',
ko: 'Korean',
ku: 'Kurdish (Kurmanji)',
ky: 'Kyrgyz',
lo: 'Lao',
la: 'Latin',
lv: 'Latvian',
lt: 'Lithuanian',
lb: 'Luxembourgish',
mk: 'Macedonian',
mg: 'Malagasy',
ms: 'Malay',
ml: 'Malayalam',
mt: 'Maltese',
mi: 'Maori',
mr: 'Marathi',
mn: 'Mongolian',
my: 'Myanmar (Burmese)',
ne: 'Nepali',
no: 'Norwegian',
ps: 'Pashto',
fa: 'Persian',
pl: 'Polish',
pt: 'Portuguese',
pa: 'Punjabi',
ro: 'Romanian',
ru: 'Russian',
sm: 'Samoan',
gd: 'Scots Gaelic',
sr: 'Serbian',
st: 'Sesotho',
sn: 'Shona',
sd: 'Sindhi',
si: 'Sinhala',
sk: 'Slovak',
sl: 'Slovenian',
so: 'Somali',
es: 'Spanish',
su: 'Sundanese',
sw: 'Swahili',
sv: 'Swedish',
tg: 'Tajik',
ta: 'Tamil',
te: 'Telugu',
th: 'Thai',
tr: 'Turkish',
uk: 'Ukrainian',
ur: 'Urdu',
uz: 'Uzbek',
vi: 'Vietnamese',
cy: 'Welsh',
xh: 'Xhosa',
yi: 'Yiddish',
yo: 'Yoruba',
zu: 'Zulu',
};
function validateLanguage(language) {
if (!language) {
throw new Error('Language cannot be empty');
}
const isoCode = getISOCode(language);
if (!isoCode) {
throw new Error(`Language not supported: ${language}`);
}
return isoCode;
}
function getISOCode(language) {
if (!language) return false;
language = language.toLowerCase();
if (language in languages) return language;
let keys = Object.keys(languages).filter(key => {
if (typeof languages[key] !== 'string') return false;
return languages[key].toLowerCase() === language;
});
return keys[0] || false;
}
function isSupported(language) {
return Boolean(getISOCode(language));
}
function getCacheKey(text, options) {
return `${text}|${options.from}|${options.to}`;
}
function getFromCache(text, options) {
const key = getCacheKey(text, options);
const cached = translationCache.get(key);
if (cached && Date.now() - cached.timestamp < CACHE_EXPIRY) {
return cached.result;
}
return null;
}
function saveToCache(text, options, result) {
const key = getCacheKey(text, options);
translationCache.set(key, {
result,
timestamp: Date.now(),
});
}
async function translate(text, options = {}) {
if (!text) throw new Error('Text cannot be empty');
options.from = options.from || 'auto';
options.to = options.to || 'en';
options.from = validateLanguage(options.from);
options.to = validateLanguage(options.to);
const cached = getFromCache(text, options);
if (cached) return cached;
let baseUrl = 'https://translate.googleapis.com/translate_a/single';
let data = {
client: 'gtx',
sl: options.from,
tl: options.to,
dt: 't',
q: text,
};
let url = `${baseUrl}?` + new URLSearchParams(data).toString();
return new Promise((resolve, reject) => {
GM_xmlhttpRequest({
method: 'GET',
url: url,
headers: {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
Accept: '*/*',
},
timeout: 10000,
onload: function (response) {
try {
if (response.status !== 200) {
throw new Error(`HTTP Error: ${response.status}`);
}
const body = JSON.parse(response.responseText);
if (!body || !Array.isArray(body) || !body[0]) {
throw new Error('Invalid response structure');
}
let result = {
text: '',
from: {
language: {
didYouMean: false,
iso: body[2] || options.from,
},
text: {
autoCorrected: false,
value: '',
didYouMean: false,
},
},
raw: body,
};
result.text = body[0]
.filter(chunk => chunk && chunk[0])
.map(chunk => decodeURIComponent(chunk[0].trim()))
.join(' ')
.trim();
saveToCache(text, options, result);
resolve(result);
} catch (error) {
reject(new Error('Error processing response: ' + error.message));
}
},
onerror: function (error) {
reject(new Error('Connection error: ' + error));
},
ontimeout: function () {
reject(new Error('Timeout: Request took too long'));
},
});
});
}
async function translateWithRetry(text, options = {}, maxRetries = MAX_RETRIES, delay = RETRY_DELAY) {
let lastError;
for (let i = 0; i < maxRetries; i++) {
try {
return await translate(text, options);
} catch (error) {
lastError = error;
console.log(`Try ${i + 1}/${maxRetries} failed:`, error);
if (i < maxRetries - 1) {
await new Promise(resolve => setTimeout(resolve, delay * Math.pow(2, i)));
}
}
}
throw new Error(`Translation failed after ${maxRetries} attempts: ${lastError.message}`);
}
async function translateBatch(texts, options = {}) {
if (!Array.isArray(texts)) {
throw new Error('Texts must be an array');
}
const results = [];
const chunks = [];
// Chia nhỏ mảng texts thành các chunks có kích thước MAX_BATCH_SIZE
for (let i = 0; i < texts.length; i += MAX_BATCH_SIZE) {
chunks.push(texts.slice(i, i + MAX_BATCH_SIZE));
}
// Dịch từng chunk
for (const chunk of chunks) {
const chunkResults = await Promise.all(
chunk.map(text => translateWithRetry(text, options).catch(error => ({ error })))
);
results.push(...chunkResults);
}
return results;
}
function clearExpiredCache() {
const now = Date.now();
for (const [key, value] of translationCache.entries()) {
if (now - value.timestamp > CACHE_EXPIRY) {
translationCache.delete(key);
}
}
}
setInterval(clearExpiredCache, 60 * 60 * 1000);
return {
translate,
translateWithRetry,
translateBatch,
languages,
getISOCode,
isSupported,
clearExpiredCache,
};
})();
if (typeof module !== 'undefined' && module.exports) {
module.exports = GoogleTranslateAPI;
}