From 9312783f44f9c50d687210ec088d2b2087ed5df1 Mon Sep 17 00:00:00 2001 From: Gabe Yuan Date: Wed, 22 May 2024 23:33:30 +0800 Subject: [PATCH] feat: lang detector can be selected --- src/apis/index.js | 50 +++++++++++++++++++++++++++++++++ src/common.js | 2 ++ src/config/index.js | 23 ++++++++++++++- src/hooks/Translate.js | 6 +++- src/libs/index.js | 30 +++++++++++++++++--- src/views/Options/Setting.js | 19 +++++++++++++ src/views/Selection/TranBox.js | 12 +++++++- src/views/Selection/TranCont.js | 8 ++++-- src/views/Selection/index.js | 2 ++ 9 files changed, 142 insertions(+), 10 deletions(-) diff --git a/src/apis/index.js b/src/apis/index.js index c0b842f..378ca4a 100644 --- a/src/apis/index.js +++ b/src/apis/index.js @@ -24,6 +24,8 @@ import { OPT_TRANS_CUSTOMIZE_5, URL_CACHE_TRAN, KV_SALT_SYNC, + URL_GOOGLE_TRAN, + URL_MICROSOFT_LANGDETECT, URL_BAIDU_LANGDETECT, URL_BAIDU_SUGGEST, URL_BAIDU_TTS, @@ -31,9 +33,11 @@ import { URL_TENCENT_TRANSMART, OPT_LANGS_TENCENT, OPT_LANGS_SPECIAL, + OPT_LANGS_MICROSOFT, } from "../config"; import { sha256 } from "../libs/utils"; import interpreter from "../libs/interpreter"; +import { msAuth } from "../libs/auth"; /** * 同步数据 @@ -59,6 +63,52 @@ export const apiSyncData = async (url, key, data) => */ export const apiFetch = (url) => fetchData(url); +/** + * Google语言识别 + * @param {*} text + * @returns + */ +export const apiGoogleLangdetect = async (text) => { + const params = { + client: "gtx", + dt: "t", + dj: 1, + ie: "UTF-8", + sl: "auto", + tl: "zh-CN", + q: text, + }; + const input = `${URL_GOOGLE_TRAN}?${queryString.stringify(params)}`; + const res = await fetchData(input, { + headers: { + "Content-type": "application/json", + }, + useCache: true, + }); + + return res.src; +}; + +/** + * Microsoft语言识别 + * @param {*} text + * @returns + */ +export const apiMicrosoftLangdetect = async (text) => { + const [token] = await msAuth(); + const res = await fetchData(URL_MICROSOFT_LANGDETECT, { + headers: { + "Content-type": "application/json", + Authorization: `Bearer ${token}`, + }, + method: "POST", + body: JSON.stringify([{ Text: text }]), + useCache: true, + }); + + return OPT_LANGS_MICROSOFT.get(res[0].language) ?? res[0].language; +}; + /** * 百度语言识别 * @param {*} text diff --git a/src/common.js b/src/common.js index d296d31..f422d30 100644 --- a/src/common.js +++ b/src/common.js @@ -141,6 +141,7 @@ function showTransbox({ transApis, darkMode, uiLang, + langDetector, }) { if (!tranboxSetting?.transOpen) { return; @@ -172,6 +173,7 @@ function showTransbox({ tranboxSetting={tranboxSetting} transApis={transApis} uiLang={uiLang} + langDetector={langDetector} /> diff --git a/src/config/index.js b/src/config/index.js index 1a030ef..bf49ed7 100644 --- a/src/config/index.js +++ b/src/config/index.js @@ -78,9 +78,16 @@ export const URL_RAW_PREFIX = "https://raw.githubusercontent.com/fishjar/kiss-translator/master"; export const URL_CACHE_TRAN = `https://${APP_LCNAME}/translate`; + +// api.cognitive.microsofttranslator.com export const URL_MICROSOFT_TRAN = "https://api-edge.cognitive.microsofttranslator.com/translate"; export const URL_MICROSOFT_AUTH = "https://edge.microsoft.com/translate/auth"; +export const URL_MICROSOFT_LANGDETECT = + "https://api-edge.cognitive.microsofttranslator.com/detect?api-version=3.0"; + +export const URL_GOOGLE_TRAN = + "https://translate.googleapis.com/translate_a/single"; export const URL_BAIDU_LANGDETECT = "https://fanyi.baidu.com/langdetect"; export const URL_BAIDU_SUGGEST = "https://fanyi.baidu.com/sug"; export const URL_BAIDU_TTS = "https://fanyi.baidu.com/gettts"; @@ -140,6 +147,13 @@ export const OPT_TRANS_ALL = [ OPT_TRANS_CUSTOMIZE_5, ]; +export const OPT_LANGDETECTOR_ALL = [ + OPT_TRANS_GOOGLE, + OPT_TRANS_MICROSOFT, + OPT_TRANS_BAIDU, + OPT_TRANS_TENCENT, +]; + export const OPT_LANGS_TO = [ ["en", "English - English"], ["zh-CN", "Simplified Chinese - 简体中文"], @@ -318,6 +332,12 @@ export const OPT_LANGS_SPECIAL = { ]), }; export const OPT_LANGS_LIST = OPT_LANGS_TO.map(([lang]) => lang); +export const OPT_LANGS_MICROSOFT = new Map( + Array.from(OPT_LANGS_SPECIAL[OPT_TRANS_MICROSOFT].entries()).map(([k, v]) => [ + v, + k, + ]) +); export const OPT_LANGS_BAIDU = new Map( Array.from(OPT_LANGS_SPECIAL[OPT_TRANS_BAIDU].entries()).map(([k, v]) => [ v, @@ -515,7 +535,7 @@ const defaultOllamaApi = { }; export const DEFAULT_TRANS_APIS = { [OPT_TRANS_GOOGLE]: { - url: "https://translate.googleapis.com/translate_a/single", + url: URL_GOOGLE_TRAN, key: "", fetchLimit: DEFAULT_FETCH_LIMIT, // 最大任务数量 fetchInterval: DEFAULT_FETCH_INTERVAL, // 任务间隔时间 @@ -636,6 +656,7 @@ export const DEFAULT_SETTING = { csplist: DEFAULT_CSPLIST.join(",\n"), // 禁用CSP名单 // disableLangs: [], // 不翻译的语言(移至rule,作废) transInterval: 500, // 翻译间隔时间 + langDetector: OPT_TRANS_MICROSOFT, // 远程语言识别服务 }; export const DEFAULT_RULES = [GLOBLA_RULE]; diff --git a/src/hooks/Translate.js b/src/hooks/Translate.js index a2f89ef..6ca03a7 100644 --- a/src/hooks/Translate.js +++ b/src/hooks/Translate.js @@ -30,7 +30,11 @@ export function useTranslate(q, rule, setting) { return; } - const deLang = await tryDetectLang(q, detectRemote === "true"); + const deLang = await tryDetectLang( + q, + detectRemote === "true", + setting.langDetector + ); if (deLang && (toLang.includes(deLang) || skipLangs.includes(deLang))) { setSamelang(true); } else { diff --git a/src/libs/index.js b/src/libs/index.js index 13ed33e..36759b1 100644 --- a/src/libs/index.js +++ b/src/libs/index.js @@ -1,8 +1,26 @@ -import { CACHE_NAME } from "../config"; +import { + CACHE_NAME, + OPT_TRANS_GOOGLE, + OPT_TRANS_MICROSOFT, + OPT_TRANS_BAIDU, + OPT_TRANS_TENCENT, +} from "../config"; import { browser } from "./browser"; -import { apiBaiduLangdetect } from "../apis"; +import { + apiGoogleLangdetect, + apiMicrosoftLangdetect, + apiBaiduLangdetect, + apiTencentLangdetect, +} from "../apis"; import { kissLog } from "./log"; +const langdetectMap = { + [OPT_TRANS_GOOGLE]: apiGoogleLangdetect, + [OPT_TRANS_MICROSOFT]: apiMicrosoftLangdetect, + [OPT_TRANS_BAIDU]: apiBaiduLangdetect, + [OPT_TRANS_TENCENT]: apiTencentLangdetect, +}; + /** * 清除缓存数据 */ @@ -19,12 +37,16 @@ export const tryClearCaches = async () => { * @param {*} q * @returns */ -export const tryDetectLang = async (q, useRemote = false) => { +export const tryDetectLang = async ( + q, + useRemote = false, + langDetector = OPT_TRANS_MICROSOFT +) => { let lang = ""; if (useRemote) { try { - lang = await apiBaiduLangdetect(q); + lang = await langdetectMap[langDetector](q); } catch (err) { kissLog(err, "detect lang remote"); } diff --git a/src/views/Options/Setting.js b/src/views/Options/Setting.js index 4a0f3b9..b916e4c 100644 --- a/src/views/Options/Setting.js +++ b/src/views/Options/Setting.js @@ -17,6 +17,8 @@ import { UI_LANGS, TRANS_NEWLINE_LENGTH, CACHE_NAME, + OPT_TRANS_MICROSOFT, + OPT_LANGDETECTOR_ALL, OPT_SHORTCUT_TRANSLATE, OPT_SHORTCUT_STYLE, OPT_SHORTCUT_POPUP, @@ -113,6 +115,7 @@ export default function Settings() { blacklist = DEFAULT_BLACKLIST.join(",\n"), csplist = DEFAULT_CSPLIST.join(",\n"), transInterval = 500, + langDetector = OPT_TRANS_MICROSOFT, } = setting; const { isHide = false } = fab || {}; @@ -231,6 +234,22 @@ export default function Settings() { + + {i18n("detect_lang_remote")} + + + {isExt ? ( <> diff --git a/src/views/Selection/TranBox.js b/src/views/Selection/TranBox.js index 6b96179..2f84e76 100644 --- a/src/views/Selection/TranBox.js +++ b/src/views/Selection/TranBox.js @@ -101,7 +101,14 @@ function Header({ ); } -function TranForm({ text, setText, tranboxSetting, transApis, simpleStyle }) { +function TranForm({ + text, + setText, + tranboxSetting, + transApis, + simpleStyle, + langDetector, +}) { const i18n = useI18n(); const [editMode, setEditMode] = useState(false); @@ -242,6 +249,7 @@ function TranForm({ text, setText, tranboxSetting, transApis, simpleStyle }) { toLang2={tranboxSetting.toLang2} transApis={transApis} simpleStyle={simpleStyle} + langDetector={langDetector} /> )} @@ -268,6 +276,7 @@ export default function TranBox({ followSelection, setFollowSelection, extStyles, + langDetector, }) { const [mouseHover, setMouseHover] = useState(false); return ( @@ -300,6 +309,7 @@ export default function TranBox({ tranboxSetting={tranboxSetting} transApis={transApis} simpleStyle={simpleStyle} + langDetector={langDetector} /> diff --git a/src/views/Selection/TranCont.js b/src/views/Selection/TranCont.js index 60abd14..b89ab32 100644 --- a/src/views/Selection/TranCont.js +++ b/src/views/Selection/TranCont.js @@ -5,10 +5,11 @@ import Stack from "@mui/material/Stack"; import { useI18n } from "../../hooks/I18n"; import { DEFAULT_TRANS_APIS } from "../../config"; import { useEffect, useState } from "react"; -import { apiTranslate, apiBaiduLangdetect } from "../../apis"; +import { apiTranslate } from "../../apis"; import CopyBtn from "./CopyBtn"; import Typography from "@mui/material/Typography"; import Alert from "@mui/material/Alert"; +import { tryDetectLang } from "../../libs"; export default function TranCont({ text, @@ -18,6 +19,7 @@ export default function TranCont({ toLang2 = "en", transApis, simpleStyle, + langDetector, }) { const i18n = useI18n(); const [trText, setTrText] = useState(""); @@ -33,7 +35,7 @@ export default function TranCont({ let to = toLang; if (toLang !== toLang2 && toLang2 !== "none") { - const detectLang = await apiBaiduLangdetect(text); + const detectLang = await tryDetectLang(text, true, langDetector); if (detectLang === toLang) { to = toLang2; } @@ -55,7 +57,7 @@ export default function TranCont({ setLoading(false); } })(); - }, [text, translator, fromLang, toLang, toLang2, transApis]); + }, [text, translator, fromLang, toLang, toLang2, transApis, langDetector]); if (simpleStyle) { return ( diff --git a/src/views/Selection/index.js b/src/views/Selection/index.js index 2f950a0..4982f76 100644 --- a/src/views/Selection/index.js +++ b/src/views/Selection/index.js @@ -20,6 +20,7 @@ export default function Slection({ tranboxSetting, transApis, uiLang, + langDetector, }) { const { hideTranBtn = false, @@ -234,6 +235,7 @@ export default function Slection({ followSelection={followSelection} setFollowSelection={setFollowSelection} extStyles={extStyles} + langDetector={langDetector} /> )}