add more translators: baidu/tencent/deeplfree

This commit is contained in:
Gabe Yuan
2023-10-21 11:54:04 +08:00
parent 507d54dba0
commit 160fc218fc
9 changed files with 340 additions and 550 deletions

View File

@@ -95,6 +95,7 @@ const userscriptWebpack = (config, env) => {
// @connect edge.microsoft.com // @connect edge.microsoft.com
// @connect api-free.deepl.com // @connect api-free.deepl.com
// @connect api.deepl.com // @connect api.deepl.com
// @connect www2.deepl.com
// @connect api.openai.com // @connect api.openai.com
// @connect openai.azure.com // @connect openai.azure.com
// @connect workers.dev // @connect workers.dev
@@ -104,6 +105,7 @@ const userscriptWebpack = (config, env) => {
// @connect ghproxy.com // @connect ghproxy.com
// @connect dav.jianguoyun.com // @connect dav.jianguoyun.com
// @connect fanyi.baidu.com // @connect fanyi.baidu.com
// @connect transmart.qq.com
// @connect localhost:3000 // @connect localhost:3000
// @connect 127.0.0.1:3000 // @connect 127.0.0.1:3000
// @connect localhost:1188 // @connect localhost:1188

View File

@@ -1,7 +1,7 @@
import queryString from "query-string"; import queryString from "query-string";
import { fetchPolyfill } from "../libs/fetch";
import { getBdauth, setBdauth } from "../libs/storage"; import { getBdauth, setBdauth } from "../libs/storage";
import { URL_BAIDU_WEB, URL_BAIDU_TRAN } from "../config"; import { URL_BAIDU_WEB, URL_BAIDU_TRAN } from "../config";
import { fetchApi } from "../libs/fetch";
/* eslint-disable */ /* eslint-disable */
function n(t, e) { function n(t, e) {
@@ -147,26 +147,13 @@ function getSign(t, gtk, r = null) {
); );
} }
const getCookie = async () => { const getToken = async () => {
const res = await fetch(URL_BAIDU_WEB, { const res = await fetchApi({
input: URL_BAIDU_WEB,
init: {
headers: { headers: {
"Content-type": "text/html; charset=utf-8", "Content-type": "text/html; charset=utf-8",
}, },
});
if (!res.ok) {
throw new Error(res.statusText);
}
return res.headers.get("set-cookie");
};
const getToken = async () => {
const cookie = await getCookie();
const res = await fetch(URL_BAIDU_WEB, {
headers: {
"Content-type": "text/html; charset=utf-8",
cookie,
}, },
}); });
@@ -179,7 +166,11 @@ const getToken = async () => {
const gtk = text.match(/gtk = "(.*)";/)[1]; const gtk = text.match(/gtk = "(.*)";/)[1];
const exp = Date.now() + 8 * 60 * 60 * 1000; const exp = Date.now() + 8 * 60 * 60 * 1000;
return { cookie, token, gtk, exp }; if (!token || !gtk) {
throw new Error("[baidu] get token error");
}
return { token, gtk, exp };
}; };
/** /**
@@ -212,21 +203,8 @@ const _bdAuth = () => {
const bdAuth = _bdAuth(); const bdAuth = _bdAuth();
/** export const genBaidu = async ({ text, from, to }) => {
* 腾讯翻译 const { token, gtk } = await bdAuth();
* @param {*} text
* @param {*} to
* @param {*} from
* @returns
*/
export const apiBaiduTranslate = async (
translator,
text,
to,
from,
{ useCache = true }
) => {
const { cookie, token, gtk } = await bdAuth();
const sign = getSign(text, gtk); const sign = getSign(text, gtk);
const data = { const data = {
from, from,
@@ -239,19 +217,14 @@ export const apiBaiduTranslate = async (
ts: Date.now(), ts: Date.now(),
}; };
const res = await fetchPolyfill(`${URL_BAIDU_TRAN}?from=${from}&to=${to}`, { const input = `${URL_BAIDU_TRAN}?from=${from}&to=${to}`;
const init = {
headers: { headers: {
"content-type": "application/x-www-form-urlencoded; charset=UTF-8", "content-type": "application/x-www-form-urlencoded; charset=UTF-8",
cookie,
}, },
method: "POST", method: "POST",
body: queryString.stringify(data), body: queryString.stringify(data),
useCache, };
usePool: true,
translator, return [input, init];
});
const trText = res.trans_result?.data.map((item) => item.dst).join(" ");
const isSame = res.trans_result?.to === res.trans_result?.from;
return [trText, isSame, res];
}; };

View File

@@ -1,22 +1,8 @@
import { fetchPolyfill } from "../libs/fetch";
import { URL_DEEPLFREE_TRAN } from "../config"; import { URL_DEEPLFREE_TRAN } from "../config";
let id = 1e4 * Math.round(1e4 * Math.random()); let id = 1e4 * Math.round(1e4 * Math.random());
/** export const genDeeplFree = ({ text, from, to }) => {
* DeepL翻译
* @param {*} text
* @param {*} to
* @param {*} from
* @returns
*/
export const apiDeepLFreeTranslate = async (
translator,
text,
to,
from,
{ useCache = true }
) => {
const iCount = (text.match(/[i]/g) || []).length + 1; const iCount = (text.match(/[i]/g) || []).length + 1;
let timestamp = Date.now(); let timestamp = Date.now();
timestamp = timestamp + (iCount - (timestamp % iCount)); timestamp = timestamp + (iCount - (timestamp % iCount));
@@ -51,7 +37,7 @@ export const apiDeepLFreeTranslate = async (
(id + 3) % 13 === 0 || (id + 5) % 29 === 0 ? 'method" : "' : 'method": "' (id + 3) % 13 === 0 || (id + 5) % 29 === 0 ? 'method" : "' : 'method": "'
); );
const res = await fetchPolyfill(URL_DEEPLFREE_TRAN, { const init = {
headers: { headers: {
"Content-Type": "application/json", "Content-Type": "application/json",
Accept: "*/*", Accept: "*/*",
@@ -66,12 +52,7 @@ export const apiDeepLFreeTranslate = async (
}, },
method: "POST", method: "POST",
body, body,
useCache, };
usePool: true,
translator, return [URL_DEEPLFREE_TRAN, init];
});
const trText = res.result?.texts.map((item) => item.text).join(" ");
const isSame = to === res.result?.lang;
return [trText, isSame];
}; };

View File

@@ -11,19 +11,14 @@ import {
OPT_TRANS_OPENAI, OPT_TRANS_OPENAI,
OPT_TRANS_CUSTOMIZE, OPT_TRANS_CUSTOMIZE,
URL_CACHE_TRAN, URL_CACHE_TRAN,
OPT_LANGS_SPECIAL,
PROMPT_PLACE_FROM,
PROMPT_PLACE_TO,
KV_SALT_SYNC, KV_SALT_SYNC,
URL_BAIDU_LANGDETECT, URL_BAIDU_LANGDETECT,
URL_MICROSOFT_TRAN,
OPT_LANGS_BAIDU, OPT_LANGS_BAIDU,
URL_TENCENT_TRANSMART,
OPT_LANGS_TENCENT,
OPT_LANGS_SPECIAL,
} from "../config"; } from "../config";
import { tryDetectLang } from "../libs";
import { sha256 } from "../libs/utils"; import { sha256 } from "../libs/utils";
import { apiDeepLFreeTranslate } from "./deepl";
import { apiBaiduTranslate } from "./baidu";
import { apiTencentTranslate } from "./tencent";
/** /**
* 同步数据 * 同步数据
@@ -49,244 +44,6 @@ export const apiSyncData = async (url, key, data) =>
*/ */
export const apiFetch = (url) => fetchPolyfill(url); export const apiFetch = (url) => fetchPolyfill(url);
/**
* 谷歌翻译
* @param {*} text
* @param {*} to
* @param {*} from
* @returns
*/
const apiGoogleTranslate = async (
translator,
text,
to,
from,
{ url, key, useCache = true }
) => {
const params = {
client: "gtx",
dt: "t",
dj: 1,
ie: "UTF-8",
sl: from,
tl: to,
q: text,
};
const input = `${url}?${queryString.stringify(params)}`;
const res = await fetchPolyfill(input, {
headers: {
"Content-type": "application/json",
},
useCache,
usePool: true,
translator,
token: key,
});
const trText = res.sentences.map((item) => item.trans).join(" ");
const isSame = to === res.src;
return [trText, isSame];
};
/**
* 微软翻译
* @param {*} text
* @param {*} to
* @param {*} from
* @returns
*/
const apiMicrosoftTranslate = async (
translator,
text,
to,
from,
{ useCache = true }
) => {
const params = {
from,
to,
"api-version": "3.0",
};
const input = `${URL_MICROSOFT_TRAN}?${queryString.stringify(params)}`;
const res = await fetchPolyfill(input, {
headers: {
"Content-type": "application/json",
},
method: "POST",
body: JSON.stringify([{ Text: text }]),
useCache,
usePool: true,
translator,
});
const trText = res[0].translations[0].text;
const isSame = to === res[0].detectedLanguage?.language;
return [trText, isSame];
};
/**
* DeepL翻译
* @param {*} text
* @param {*} to
* @param {*} from
* @returns
*/
const apiDeepLTranslate = async (
translator,
text,
to,
from,
{ url, key, useCache = true }
) => {
const data = {
text: [text],
target_lang: to,
// split_sentences: "0",
};
if (from) {
data.source_lang = from;
}
const res = await fetchPolyfill(url, {
headers: {
"Content-type": "application/json",
},
method: "POST",
body: JSON.stringify(data),
useCache,
usePool: true,
translator,
token: key,
});
const trText = res.translations.map((item) => item.text).join(" ");
const isSame = to === res.translations[0].detected_source_language;
return [trText, isSame];
};
/**
* DeepLX翻译
* https://github.com/OwO-Network/DeepLX
* @param {*} text
* @param {*} to
* @param {*} from
* @returns
*/
const apiDeepLXTranslate = async (
translator,
text,
to,
from,
{ url, key, useCache = true }
) => {
const data = {
text,
target_lang: to,
};
if (from) {
data.source_lang = from;
}
const res = await fetchPolyfill(url, {
headers: {
"Content-type": "application/json",
},
method: "POST",
body: JSON.stringify(data),
useCache,
usePool: true,
translator,
token: key,
});
const trText = res.data;
const isSame = to === res.source_lang;
return [trText, isSame];
};
/**
* OpenAI 翻译
* @param {*} text
* @param {*} to
* @param {*} from
* @returns
*/
const apiOpenaiTranslate = async (
translator,
text,
to,
from,
{ url, key, model, prompt, useCache = true }
) => {
prompt = prompt
.replaceAll(PROMPT_PLACE_FROM, from)
.replaceAll(PROMPT_PLACE_TO, to);
const res = await fetchPolyfill(url, {
headers: {
"Content-type": "application/json",
},
method: "POST",
body: JSON.stringify({
model: model,
messages: [
{
role: "system",
content: prompt,
},
{
role: "user",
content: text,
},
],
temperature: 0,
max_tokens: 256,
}),
useCache,
usePool: true,
translator,
token: key,
});
const trText = res?.choices?.[0].message.content;
const sLang = await tryDetectLang(text);
const tLang = await tryDetectLang(trText);
const isSame = text === trText || (sLang && tLang && sLang === tLang);
return [trText, isSame];
};
/**
* 自定义接口 翻译
* @param {*} text
* @param {*} to
* @param {*} from
* @returns
*/
const apiCustomTranslate = async (
translator,
text,
to,
from,
{ url, key, useCache = true }
) => {
const res = await fetchPolyfill(url, {
headers: {
"Content-type": "application/json",
},
method: "POST",
body: JSON.stringify({
text,
from,
to,
}),
useCache,
usePool: true,
translator,
token: key,
});
const trText = res.text;
const isSame = to === res.from;
return [trText, isSame];
};
/** /**
* 百度语言识别 * 百度语言识别
* @param {*} text * @param {*} text
@@ -311,6 +68,31 @@ export const apiBaiduLangdetect = async (text) => {
return ""; return "";
}; };
/**
* 腾讯语言识别
* @param {*} text
* @returns
*/
export const apiTencentLangdetect = async (text) => {
const body = JSON.stringify({
header: {
fn: "text_analysis",
},
text,
});
const res = await fetchPolyfill(URL_TENCENT_TRANSMART, {
headers: {
"Content-type": "application/json",
},
method: "POST",
body,
useCache: true,
});
return OPT_LANGS_TENCENT.get(res.language) ?? res.language;
};
/** /**
* 统一翻译接口 * 统一翻译接口
* @param {*} param0 * @param {*} param0
@@ -328,15 +110,31 @@ export const apiTranslate = async ({
let trText = ""; let trText = "";
let isSame = false; let isSame = false;
const transOpts = { const from =
OPT_LANGS_SPECIAL[translator].get(fromLang) ??
OPT_LANGS_SPECIAL[translator].get("auto");
const to = OPT_LANGS_SPECIAL[translator].get(toLang);
if (!to) {
console.log(`[trans] target lang: ${toLang} not support`);
return [trText, isSame];
}
const cacheOpts = {
translator, translator,
text, text,
fromLang, fromLang,
toLang, toLang,
}; };
const transOpts = {
translator,
text,
from,
to,
};
const res = await fetchPolyfill( const res = await fetchPolyfill(
`${URL_CACHE_TRAN}?${queryString.stringify(transOpts)}`, `${URL_CACHE_TRAN}?${queryString.stringify(cacheOpts)}`,
{ {
useCache, useCache,
usePool, usePool,
@@ -347,30 +145,44 @@ export const apiTranslate = async ({
switch (translator) { switch (translator) {
case OPT_TRANS_GOOGLE: case OPT_TRANS_GOOGLE:
trText = res.sentences.map((item) => item.trans).join(" ");
isSame = to === res.src;
break; break;
case OPT_TRANS_MICROSOFT: case OPT_TRANS_MICROSOFT:
trText = res[0].translations[0].text; trText = res[0].translations.map((item) => item.text).join(" ");
isSame = toLang === res[0].detectedLanguage?.language; isSame = text === trText;
break; break;
case OPT_TRANS_DEEPL: case OPT_TRANS_DEEPL:
trText = res.translations.map((item) => item.text).join(" ");
isSame = to === res.translations[0].detected_source_language;
break; break;
case OPT_TRANS_DEEPLFREE: case OPT_TRANS_DEEPLFREE:
trText = res.result?.texts.map((item) => item.text).join(" ");
isSame = to === res.result?.lang;
break; break;
case OPT_TRANS_DEEPLX: case OPT_TRANS_DEEPLX:
trText = res.data;
isSame = to === res.source_lang;
break; break;
case OPT_TRANS_BAIDU: case OPT_TRANS_BAIDU:
trText = res.trans_result?.data.map((item) => item.dst).join(" ");
isSame = res.trans_result?.to === res.trans_result?.from;
break; break;
case OPT_TRANS_TENCENT: case OPT_TRANS_TENCENT:
trText = res.auto_translation; trText = res.auto_translation;
isSame = text === trText; isSame = text === trText;
break; break;
case OPT_TRANS_OPENAI: case OPT_TRANS_OPENAI:
trText = res?.choices?.[0].message.content;
isSame = text === trText;
break; break;
case OPT_TRANS_CUSTOMIZE: case OPT_TRANS_CUSTOMIZE:
trText = res.text;
isSame = to === res.from;
break; break;
default: default:
break; break;
} }
return [trText, isSame]; return [trText, isSame, res];
}; };

View File

@@ -1,73 +0,0 @@
import { URL_TENCENT_TRANSMART, OPT_LANGS_TENCENT } from "../config";
import { fetchPolyfill } from "../libs/fetch";
/**
* 腾讯语言识别
* @param {*} text
* @returns
*/
export const apiTencentLangdetect = async (text) => {
const body = JSON.stringify({
header: {
fn: "text_analysis",
},
text,
});
const res = await fetchPolyfill(URL_TENCENT_TRANSMART, {
headers: {
"Content-type": "application/json",
},
method: "POST",
body,
useCache: true,
});
return OPT_LANGS_TENCENT.get(res.language) ?? res.language;
};
/**
* 腾讯翻译
* @param {*} text
* @param {*} to
* @param {*} from
* @returns
*/
export const apiTencentTranslate = async (
translator,
text,
to,
from,
{ useCache = true }
) => {
const data = {
header: {
fn: "auto_translation_block",
},
source: {
text_block: text,
},
target: {
lang: to,
},
};
if (from) {
data.source.lang = from;
}
const res = await fetchPolyfill(URL_TENCENT_TRANSMART, {
headers: {
"Content-Type": "application/json",
},
method: "POST",
body: JSON.stringify(data),
useCache,
usePool: true,
translator,
});
const trText = res.auto_translation;
const isSame = text === trText;
return [trText, isSame];
};

View File

@@ -1,4 +1,3 @@
import queryString from "query-string";
import { isExt, isGm } from "./client"; import { isExt, isGm } from "./client";
import { sendBgMsg } from "./msg"; import { sendBgMsg } from "./msg";
import { taskPool } from "./pool"; import { taskPool } from "./pool";
@@ -7,23 +6,11 @@ import {
MSG_FETCH_LIMIT, MSG_FETCH_LIMIT,
MSG_FETCH_CLEAR, MSG_FETCH_CLEAR,
CACHE_NAME, CACHE_NAME,
OPT_TRANS_GOOGLE,
OPT_TRANS_MICROSOFT,
OPT_TRANS_DEEPL,
OPT_TRANS_DEEPLFREE,
OPT_TRANS_DEEPLX,
OPT_TRANS_BAIDU,
OPT_TRANS_TENCENT,
OPT_TRANS_OPENAI,
OPT_TRANS_CUSTOMIZE,
DEFAULT_FETCH_INTERVAL, DEFAULT_FETCH_INTERVAL,
DEFAULT_FETCH_LIMIT, DEFAULT_FETCH_LIMIT,
OPT_LANGS_SPECIAL,
URL_MICROSOFT_TRAN,
URL_TENCENT_TRANSMART,
} from "../config"; } from "../config";
import { msAuth } from "./auth";
import { isBg } from "./browser"; import { isBg } from "./browser";
import { newCacheReq, newTransReq } from "./req";
/** /**
* 油猴脚本的请求封装 * 油猴脚本的请求封装
@@ -38,153 +25,35 @@ export const fetchGM = async (input, { method = "GET", headers, body } = {}) =>
url: input, url: input,
headers, headers,
data: body, data: body,
onload: ({ response, responseHeaders, status, statusText }) => { // withCredentials: true,
const headers = new Headers(); onload: ({ response, responseHeaders, status, statusText, ...opts }) => {
const headers = {};
responseHeaders.split("\n").forEach((line) => { responseHeaders.split("\n").forEach((line) => {
const [name, value] = line.split(":").map((item) => item.trim()); const [name, value] = line.split(":").map((item) => item.trim());
if (name && value) { if (name && value) {
headers.append(name, value); headers[name] = value;
} }
}); });
resolve( resolve({
new Response(response, { body: response,
headers, headers,
status, status,
statusText, statusText,
}) });
);
}, },
onerror: reject, onerror: reject,
}); });
}); });
/**
* 构造缓存 request
* @param {*} request
* @returns
*/
const newCacheReq = async (input, init) => {
let request = new Request(input, init);
if (request.method !== "GET") {
const body = await request.text();
const cacheUrl = new URL(request.url);
cacheUrl.pathname += body;
request = new Request(cacheUrl.toString(), { method: "GET" });
}
return request;
};
const newTransReq = (
{ translator, text, fromLang, toLang },
{ url, key } = {}
) => {
// console.log({ translator, text, fromLang, toLang }, { url, key });
let params;
let data;
let input;
let init;
const from = OPT_LANGS_SPECIAL[translator].get(fromLang) ?? "";
const to = OPT_LANGS_SPECIAL[translator].get(toLang);
if (!to) {
throw new Error(`[trans] target lang: ${toLang} not support`);
}
switch (translator) {
case OPT_TRANS_GOOGLE:
break;
case OPT_TRANS_MICROSOFT:
params = {
from,
to,
"api-version": "3.0",
};
input = `${URL_MICROSOFT_TRAN}?${queryString.stringify(params)}`;
init = {
headers: {
"Content-type": "application/json",
Authorization: `Bearer ${key}`,
},
method: "POST",
body: JSON.stringify([{ Text: text }]),
};
break;
case OPT_TRANS_DEEPL:
break;
case OPT_TRANS_DEEPLFREE:
break;
case OPT_TRANS_DEEPLX:
break;
case OPT_TRANS_BAIDU:
break;
case OPT_TRANS_TENCENT:
data = {
header: {
fn: "auto_translation_block",
},
source: {
text_block: text,
},
target: {
lang: to,
},
};
if (from) {
data.source.lang = from;
}
input = URL_TENCENT_TRANSMART;
init = {
headers: {
"Content-Type": "application/json",
},
method: "POST",
body: JSON.stringify(data),
};
break;
case OPT_TRANS_OPENAI:
break;
case OPT_TRANS_CUSTOMIZE:
break;
default:
break;
}
if (!input) {
throw new Error(`[trans] translator: ${translator} not support`);
}
return [input, init];
};
/** /**
* 发起请求 * 发起请求
* @param {*} param0 * @param {*} param0
* @returns * @returns
*/ */
export const fetchApi = async ({ export const fetchApi = async ({ input, init, transOpts, apiSetting }) => {
input,
init,
transOpts,
apiSetting,
token,
}) => {
if (token) {
apiSetting.key = token;
}
if (transOpts?.translator) { if (transOpts?.translator) {
[input, init] = newTransReq(transOpts, apiSetting); [input, init] = await newTransReq(transOpts, apiSetting);
} }
// if (token) {
// if (translator === OPT_TRANS_DEEPL) {
// init.headers["Authorization"] = `DeepL-Auth-Key ${token}`; // DeepL
// } else if (translator === OPT_TRANS_OPENAI) {
// init.headers["Authorization"] = `Bearer ${token}`; // OpenAI
// init.headers["api-key"] = token; // Azure OpenAI
// } else {
// init.headers["Authorization"] = `Bearer ${token}`; // Microsoft & others
// }
// }
if (isGm) { if (isGm) {
let info; let info;
@@ -193,19 +62,26 @@ export const fetchApi = async ({
} else { } else {
info = GM.info; info = GM.info;
} }
// Tampermonkey --> .connects // Tampermonkey --> .connects
// Violentmonkey --> .connect // Violentmonkey --> .connect
const connects = info?.script?.connects || info?.script?.connect || []; const connects = info?.script?.connects || info?.script?.connect || [];
const url = new URL(input); const url = new URL(input);
const isSafe = connects.find((item) => url.hostname.endsWith(item)); const isSafe = connects.find((item) => url.hostname.endsWith(item));
if (isSafe) { if (isSafe) {
if (window.KISS_GM) { const { body, headers, status, statusText } = window.KISS_GM
return window.KISS_GM.fetch(input, init); ? await window.KISS_GM.fetch(input, init)
} else { : await fetchGM(input, init);
return fetchGM(input, init);
} return new Response(body, {
headers: new Headers(headers),
status,
statusText,
});
} }
} }
return fetch(input, init); return fetch(input, init);
}; };
@@ -214,13 +90,7 @@ export const fetchApi = async ({
*/ */
export const fetchPool = taskPool( export const fetchPool = taskPool(
fetchApi, fetchApi,
async ({ transOpts }) => { null,
if (transOpts?.translator === OPT_TRANS_MICROSOFT) {
const [token] = await msAuth();
return { token };
}
return {};
},
DEFAULT_FETCH_INTERVAL, DEFAULT_FETCH_INTERVAL,
DEFAULT_FETCH_LIMIT DEFAULT_FETCH_LIMIT
); );

View File

@@ -31,7 +31,7 @@ export const taskPool = (
curCount++; curCount++;
const { args, resolve, reject, retry } = item; const { args, resolve, reject, retry } = item;
try { try {
const preArgs = await preFn(item.args); const preArgs = preFn ? await preFn(item.args) : {};
const res = await fn({ ...args, ...preArgs }); const res = await fn({ ...args, ...preArgs });
resolve(res); resolve(res);
} catch (err) { } catch (err) {

224
src/libs/req.js Normal file
View File

@@ -0,0 +1,224 @@
import queryString from "query-string";
import {
OPT_TRANS_GOOGLE,
OPT_TRANS_MICROSOFT,
OPT_TRANS_DEEPL,
OPT_TRANS_DEEPLFREE,
OPT_TRANS_DEEPLX,
OPT_TRANS_BAIDU,
OPT_TRANS_TENCENT,
OPT_TRANS_OPENAI,
OPT_TRANS_CUSTOMIZE,
URL_MICROSOFT_TRAN,
URL_TENCENT_TRANSMART,
PROMPT_PLACE_FROM,
PROMPT_PLACE_TO,
} from "../config";
import { msAuth } from "./auth";
import { genDeeplFree } from "../apis/deepl";
import { genBaidu } from "../apis/baidu";
/**
* 构造缓存 request
* @param {*} request
* @returns
*/
export const newCacheReq = async (input, init) => {
let request = new Request(input, init);
if (request.method !== "GET") {
const body = await request.text();
const cacheUrl = new URL(request.url);
cacheUrl.pathname += body;
request = new Request(cacheUrl.toString(), { method: "GET" });
}
return request;
};
const genGoogle = ({ text, from, to, url, key }) => {
const params = {
client: "gtx",
dt: "t",
dj: 1,
ie: "UTF-8",
sl: from,
tl: to,
q: text,
};
const input = `${url}?${queryString.stringify(params)}`;
const init = {
headers: {
"Content-type": "application/json",
},
};
if (key) {
init.headers.Authorization = `Bearer ${key}`;
}
return [input, init];
};
const genMicrosoft = async ({ text, from, to }) => {
const [token] = await msAuth();
const params = {
from,
to,
"api-version": "3.0",
};
const input = `${URL_MICROSOFT_TRAN}?${queryString.stringify(params)}`;
const init = {
headers: {
"Content-type": "application/json",
Authorization: `Bearer ${token}`,
},
method: "POST",
body: JSON.stringify([{ Text: text }]),
};
return [input, init];
};
const genDeepl = ({ text, from, to, url, key }) => {
const data = {
text: [text],
target_lang: to,
source_lang: from,
// split_sentences: "0",
};
const init = {
headers: {
"Content-type": "application/json",
Authorization: `DeepL-Auth-Key ${key}`,
},
method: "POST",
body: JSON.stringify(data),
};
return [url, init];
};
const genDeeplX = ({ text, from, to, url, key }) => {
const data = {
text,
target_lang: to,
source_lang: from,
};
const init = {
headers: {
"Content-type": "application/json",
},
method: "POST",
body: JSON.stringify(data),
};
if (key) {
init.headers.Authorization = `Bearer ${key}`;
}
return [url, init];
};
const genTencent = ({ text, from, to }) => {
const data = {
header: {
fn: "auto_translation_block",
},
source: {
text_block: text,
lang: from,
},
target: {
lang: to,
},
};
const init = {
headers: {
"Content-Type": "application/json",
},
method: "POST",
body: JSON.stringify(data),
};
return [URL_TENCENT_TRANSMART, init];
};
const genOpenai = ({ text, from, to, url, key, prompt, model }) => {
prompt = prompt
.replaceAll(PROMPT_PLACE_FROM, from)
.replaceAll(PROMPT_PLACE_TO, to);
const data = {
model,
messages: [
{
role: "system",
content: prompt,
},
{
role: "user",
content: text,
},
],
temperature: 0,
max_tokens: 256,
};
const init = {
headers: {
"Content-type": "application/json",
Authorization: `Bearer ${key}`, // OpenAI
"api-key": key, // Azure OpenAI
},
method: "POST",
body: JSON.stringify(data),
};
return [url, init];
};
const genCustom = ({ text, from, to, url, key }) => {
const data = {
text,
from,
to,
};
const init = {
headers: {
"Content-type": "application/json",
},
method: "POST",
body: JSON.stringify(data),
};
if (key) {
init.headers.Authorization = `Bearer ${key}`;
}
return [url, init];
};
export const newTransReq = ({ translator, text, from, to }, apiSetting) => {
const args = { text, from, to, ...apiSetting };
switch (translator) {
case OPT_TRANS_GOOGLE:
return genGoogle(args);
case OPT_TRANS_MICROSOFT:
return genMicrosoft(args);
case OPT_TRANS_DEEPL:
return genDeepl(args);
case OPT_TRANS_DEEPLFREE:
return genDeeplFree(args);
case OPT_TRANS_DEEPLX:
return genDeeplX(args);
case OPT_TRANS_BAIDU:
return genBaidu(args);
case OPT_TRANS_TENCENT:
return genTencent(args);
case OPT_TRANS_OPENAI:
return genOpenai(args);
case OPT_TRANS_CUSTOMIZE:
return genCustom(args);
default:
throw new Error(`[trans] translator: ${translator} not support`);
}
};

View File

@@ -38,7 +38,8 @@ function TestButton({ translator, api }) {
text: "hello world", text: "hello world",
fromLang: "en", fromLang: "en",
toLang: "zh-CN", toLang: "zh-CN",
apiSetting: { ...api, useCache: false }, apiSetting: api,
useCache: false,
}); });
if (!text) { if (!text) {
throw new Error("empty reault"); throw new Error("empty reault");