From 9a1478ef99efa8fe52ca59da680376533be817c3 Mon Sep 17 00:00:00 2001 From: BANKA2017 Date: Thu, 7 Mar 2024 22:02:10 +0800 Subject: [PATCH] add: new translate endpoint for google translator --- .../translator-utils-crypto/index.node.js | 4 +- src/source/google.ts | 116 +++++++++++------- tests/google.test.ts | 18 +++ 3 files changed, 95 insertions(+), 43 deletions(-) diff --git a/packages/translator-utils-crypto/index.node.js b/packages/translator-utils-crypto/index.node.js index 4cc45e2..56a7103 100644 --- a/packages/translator-utils-crypto/index.node.js +++ b/packages/translator-utils-crypto/index.node.js @@ -1,3 +1,3 @@ -import { webcrypto } from 'crypto' -const cryptoHandle = webcrypto +import crypto from 'crypto' +const cryptoHandle = crypto export default cryptoHandle diff --git a/src/source/google.ts b/src/source/google.ts index 2bb3d17..2552479 100644 --- a/src/source/google.ts +++ b/src/source/google.ts @@ -14,47 +14,81 @@ const GoogleTranslate: TranslatorModuleFunction<'google'> = async (text = '', so if (Array.isArray(text)) { text = text.join('\n') } - const query = new URLSearchParams({ - client: 'webapp', - sl: source, - tl: target || 'en', - hl: target || 'en', - dt: 't', - clearbtn: '1', - otf: '1', - pc: '1', - ssel: '0', - tsel: '0', - kc: '2', - tk: '', - q: text - }) - return new Promise(async (resolve, reject) => { - axiosFetch - .get('https://translate.google.com/translate_a/single?' + 'dt=at&dt=bd&dt=ex&dt=md&dt=rw&dt=ss&dt=rm&' + query.toString(), { - headers: { - referer: 'https://translate.google.com/', - authority: 'translate.google.com' - } - }) - .then((response) => { - if (response.data && Array.isArray(response.data[0])) { - resolve( - raw - ? response.data - : response.data[0] - .filter((translate) => translate) - .map((translate) => translate[0]) - .join('') - ) - //resolve(response.data[0].filter(translate => translate).map(translate => translate[0]).join('')) - } - reject(raw ? response.data : 'Invalid content #GoogleTranslate ') - }) - .catch((e) => { - reject(raw ? e : e.toString()) - }) - }) + // thanks https://codeberg.org/aryak/libmozhi/src/branch/master/engines.go#L52 + if (!ext.legacy === false) { + return new Promise(async (resolve, reject) => { + axiosFetch + .post( + 'https://translate.google.com/_/TranslateWebserverUi/data/batchexecute', + new URLSearchParams({ + 'f.req': JSON.stringify([[['MkEWBc', JSON.stringify([[text, source, target, 1], []]), null, 'generic']]]) + }).toString() + ) + .then((response) => { + if (raw && !ext.raw_json) { + resolve(response.data) + } + + // try to parse content + const splitedResponse = response.data.split('\n') + let tmpData = '' + for (let index in splitedResponse) { + const i = Number(index) + if (!isNaN(splitedResponse[i]) && i < splitedResponse.length - 1 && splitedResponse[i + 1].startsWith('[')) { + tmpData = splitedResponse[i + 1] + break + } + } + resolve(raw && ext.raw_json ? JSON.parse(tmpData) : JSON.parse(JSON.parse(tmpData)[0][2])[1][0][0][5][0][0]) + }) + .catch((e) => { + console.log(e) + reject(raw ? e : e.toString()) + }) + }) + } else { + const query = new URLSearchParams({ + client: 'webapp', + sl: source, + tl: target || 'en', + hl: target || 'en', + dt: 't', + clearbtn: '1', + otf: '1', + pc: '1', + ssel: '0', + tsel: '0', + kc: '2', + tk: '', + q: text + }) + return new Promise(async (resolve, reject) => { + axiosFetch + .get('https://translate.google.com/translate_a/single?' + 'dt=at&dt=bd&dt=ex&dt=md&dt=rw&dt=ss&dt=rm&' + query.toString(), { + headers: { + referer: 'https://translate.google.com/', + authority: 'translate.google.com' + } + }) + .then((response) => { + if (response.data && Array.isArray(response.data[0])) { + resolve( + raw + ? response.data + : response.data[0] + .filter((translate) => translate) + .map((translate) => translate[0]) + .join('') + ) + //resolve(response.data[0].filter(translate => translate).map(translate => translate[0]).join('')) + } + reject(raw ? response.data : 'Invalid content #GoogleTranslate ') + }) + .catch((e) => { + reject(raw ? e : e.toString()) + }) + }) + } } const GoogleBrowserTranslate: TranslatorModuleFunction<'google_browser'> = async (text = '', source = 'auto', target, raw, ext = {}) => { diff --git a/tests/google.test.ts b/tests/google.test.ts index a47e806..b321d6c 100644 --- a/tests/google.test.ts +++ b/tests/google.test.ts @@ -23,6 +23,24 @@ describe('Google translate(web)', () => { }) }) +describe('Google translate(new web)', () => { + test.concurrent('English', async ({ expect }) => { + expect(await GoogleTranslate('hello', 'auto', 'zh-cn', false, { legacy: false })).toMatch(/(你|妳|您)好/gm) + }) + test.concurrent('Japanese', async ({ expect }) => { + expect(await GoogleTranslate('こんにちわ', 'auto', 'zh-cn', false, { legacy: false })).toMatch(/(你|妳|您)好/gm) + }) + test.concurrent('Simplified Chinese', async ({ expect }) => { + expect(await GoogleTranslate('你好', 'auto', 'zh-cn', false, { legacy: false })).toMatch(/(你|妳|您)好/gm) + }) + test.concurrent('Korean', async ({ expect }) => { + expect(await GoogleTranslate('안녕하세요', 'auto', 'zh-cn', false, { legacy: false })).toMatch(/(你|妳|您)好/gm) + }) + test.concurrent('Empty text', async ({ expect }) => { + await expect(GoogleTranslate('', 'auto', 'zh-cn', false, { legacy: false })).rejects.toMatch('Empty text #GoogleTranslate ') + }) +}) + describe('Google translate(browser)', () => { test.concurrent('English', async ({ expect }) => { expect(await GoogleBrowserTranslate('hello', 'auto', 'zh-cn', false)).toMatch(/(你|妳|您)好/gm)