add more translators: baidu/tencent/deeplfree
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
import queryString from "query-string";
|
||||
import { fetchPolyfill } from "../libs/fetch";
|
||||
import { getBdauth, setBdauth } from "../libs/storage";
|
||||
import { URL_BAIDU_WEB, URL_BAIDU_TRAN } from "../config";
|
||||
import { fetchApi } from "../libs/fetch";
|
||||
|
||||
/* eslint-disable */
|
||||
function n(t, e) {
|
||||
@@ -147,26 +147,13 @@ function getSign(t, gtk, r = null) {
|
||||
);
|
||||
}
|
||||
|
||||
const getCookie = async () => {
|
||||
const res = await fetch(URL_BAIDU_WEB, {
|
||||
headers: {
|
||||
"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,
|
||||
const res = await fetchApi({
|
||||
input: URL_BAIDU_WEB,
|
||||
init: {
|
||||
headers: {
|
||||
"Content-type": "text/html; charset=utf-8",
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
@@ -179,7 +166,11 @@ const getToken = async () => {
|
||||
const gtk = text.match(/gtk = "(.*)";/)[1];
|
||||
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();
|
||||
|
||||
/**
|
||||
* 腾讯翻译
|
||||
* @param {*} text
|
||||
* @param {*} to
|
||||
* @param {*} from
|
||||
* @returns
|
||||
*/
|
||||
export const apiBaiduTranslate = async (
|
||||
translator,
|
||||
text,
|
||||
to,
|
||||
from,
|
||||
{ useCache = true }
|
||||
) => {
|
||||
const { cookie, token, gtk } = await bdAuth();
|
||||
export const genBaidu = async ({ text, from, to }) => {
|
||||
const { token, gtk } = await bdAuth();
|
||||
const sign = getSign(text, gtk);
|
||||
const data = {
|
||||
from,
|
||||
@@ -239,19 +217,14 @@ export const apiBaiduTranslate = async (
|
||||
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: {
|
||||
"content-type": "application/x-www-form-urlencoded; charset=UTF-8",
|
||||
cookie,
|
||||
},
|
||||
method: "POST",
|
||||
body: queryString.stringify(data),
|
||||
useCache,
|
||||
usePool: true,
|
||||
translator,
|
||||
});
|
||||
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];
|
||||
return [input, init];
|
||||
};
|
||||
|
||||
@@ -1,22 +1,8 @@
|
||||
import { fetchPolyfill } from "../libs/fetch";
|
||||
import { URL_DEEPLFREE_TRAN } from "../config";
|
||||
|
||||
let id = 1e4 * Math.round(1e4 * Math.random());
|
||||
|
||||
/**
|
||||
* DeepL翻译
|
||||
* @param {*} text
|
||||
* @param {*} to
|
||||
* @param {*} from
|
||||
* @returns
|
||||
*/
|
||||
export const apiDeepLFreeTranslate = async (
|
||||
translator,
|
||||
text,
|
||||
to,
|
||||
from,
|
||||
{ useCache = true }
|
||||
) => {
|
||||
export const genDeeplFree = ({ text, from, to }) => {
|
||||
const iCount = (text.match(/[i]/g) || []).length + 1;
|
||||
let timestamp = Date.now();
|
||||
timestamp = timestamp + (iCount - (timestamp % iCount));
|
||||
@@ -51,7 +37,7 @@ export const apiDeepLFreeTranslate = async (
|
||||
(id + 3) % 13 === 0 || (id + 5) % 29 === 0 ? 'method" : "' : 'method": "'
|
||||
);
|
||||
|
||||
const res = await fetchPolyfill(URL_DEEPLFREE_TRAN, {
|
||||
const init = {
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
Accept: "*/*",
|
||||
@@ -66,12 +52,7 @@ export const apiDeepLFreeTranslate = async (
|
||||
},
|
||||
method: "POST",
|
||||
body,
|
||||
useCache,
|
||||
usePool: true,
|
||||
translator,
|
||||
});
|
||||
const trText = res.result?.texts.map((item) => item.text).join(" ");
|
||||
const isSame = to === res.result?.lang;
|
||||
};
|
||||
|
||||
return [trText, isSame];
|
||||
return [URL_DEEPLFREE_TRAN, init];
|
||||
};
|
||||
|
||||
@@ -11,19 +11,14 @@ import {
|
||||
OPT_TRANS_OPENAI,
|
||||
OPT_TRANS_CUSTOMIZE,
|
||||
URL_CACHE_TRAN,
|
||||
OPT_LANGS_SPECIAL,
|
||||
PROMPT_PLACE_FROM,
|
||||
PROMPT_PLACE_TO,
|
||||
KV_SALT_SYNC,
|
||||
URL_BAIDU_LANGDETECT,
|
||||
URL_MICROSOFT_TRAN,
|
||||
OPT_LANGS_BAIDU,
|
||||
URL_TENCENT_TRANSMART,
|
||||
OPT_LANGS_TENCENT,
|
||||
OPT_LANGS_SPECIAL,
|
||||
} from "../config";
|
||||
import { tryDetectLang } from "../libs";
|
||||
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);
|
||||
|
||||
/**
|
||||
* 谷歌翻译
|
||||
* @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
|
||||
@@ -311,6 +68,31 @@ export const apiBaiduLangdetect = async (text) => {
|
||||
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
|
||||
@@ -328,15 +110,31 @@ export const apiTranslate = async ({
|
||||
let trText = "";
|
||||
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,
|
||||
text,
|
||||
fromLang,
|
||||
toLang,
|
||||
};
|
||||
|
||||
const transOpts = {
|
||||
translator,
|
||||
text,
|
||||
from,
|
||||
to,
|
||||
};
|
||||
|
||||
const res = await fetchPolyfill(
|
||||
`${URL_CACHE_TRAN}?${queryString.stringify(transOpts)}`,
|
||||
`${URL_CACHE_TRAN}?${queryString.stringify(cacheOpts)}`,
|
||||
{
|
||||
useCache,
|
||||
usePool,
|
||||
@@ -347,30 +145,44 @@ export const apiTranslate = async ({
|
||||
|
||||
switch (translator) {
|
||||
case OPT_TRANS_GOOGLE:
|
||||
trText = res.sentences.map((item) => item.trans).join(" ");
|
||||
isSame = to === res.src;
|
||||
break;
|
||||
case OPT_TRANS_MICROSOFT:
|
||||
trText = res[0].translations[0].text;
|
||||
isSame = toLang === res[0].detectedLanguage?.language;
|
||||
trText = res[0].translations.map((item) => item.text).join(" ");
|
||||
isSame = text === trText;
|
||||
break;
|
||||
case OPT_TRANS_DEEPL:
|
||||
trText = res.translations.map((item) => item.text).join(" ");
|
||||
isSame = to === res.translations[0].detected_source_language;
|
||||
break;
|
||||
case OPT_TRANS_DEEPLFREE:
|
||||
trText = res.result?.texts.map((item) => item.text).join(" ");
|
||||
isSame = to === res.result?.lang;
|
||||
break;
|
||||
case OPT_TRANS_DEEPLX:
|
||||
trText = res.data;
|
||||
isSame = to === res.source_lang;
|
||||
break;
|
||||
case OPT_TRANS_BAIDU:
|
||||
trText = res.trans_result?.data.map((item) => item.dst).join(" ");
|
||||
isSame = res.trans_result?.to === res.trans_result?.from;
|
||||
break;
|
||||
case OPT_TRANS_TENCENT:
|
||||
trText = res.auto_translation;
|
||||
isSame = text === trText;
|
||||
break;
|
||||
case OPT_TRANS_OPENAI:
|
||||
trText = res?.choices?.[0].message.content;
|
||||
isSame = text === trText;
|
||||
break;
|
||||
case OPT_TRANS_CUSTOMIZE:
|
||||
trText = res.text;
|
||||
isSame = to === res.from;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return [trText, isSame];
|
||||
return [trText, isSame, res];
|
||||
};
|
||||
|
||||
@@ -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];
|
||||
};
|
||||
Reference in New Issue
Block a user