fix: lang detect
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
import { getMsauth, setMsauth } from "./storage";
|
||||
import { fetchData } from "./fetch";
|
||||
import { kissLog } from "./log";
|
||||
import { apiMsAuth } from "../apis";
|
||||
|
||||
const parseMSToken = (token) => {
|
||||
try {
|
||||
@@ -16,28 +16,55 @@ const parseMSToken = (token) => {
|
||||
* @returns
|
||||
*/
|
||||
const _msAuth = () => {
|
||||
let { token, exp } = {};
|
||||
let tokenPromise = null;
|
||||
const EXPIRATION_MS = 1000;
|
||||
|
||||
const fetchNewToken = async () => {
|
||||
try {
|
||||
const now = Date.now();
|
||||
|
||||
// 1. 查询storage缓存
|
||||
const storageToken = await getMsauth();
|
||||
if (storageToken) {
|
||||
const storageExp = parseMSToken(storageToken);
|
||||
const storageExpiresAt = storageExp * 1000;
|
||||
if (storageExpiresAt > now + EXPIRATION_MS) {
|
||||
return { token: storageToken, expiresAt: storageExpiresAt };
|
||||
}
|
||||
}
|
||||
|
||||
// 2. 缓存没有或失效,查询接口
|
||||
const apiToken = await apiMsAuth();
|
||||
if (!apiToken) {
|
||||
throw new Error("Failed to fetch ms token");
|
||||
}
|
||||
|
||||
const apiExp = parseMSToken(apiToken);
|
||||
const apiExpiresAt = apiExp * 1000;
|
||||
await setMsauth(apiToken);
|
||||
return { token: apiToken, expiresAt: apiExpiresAt };
|
||||
} catch (error) {
|
||||
kissLog("get msauth failed", error);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
return async () => {
|
||||
// 查询内存缓存
|
||||
const now = Date.now();
|
||||
if (token && exp * 1000 > now + 1000) {
|
||||
return [token, exp];
|
||||
// 检查是否有缓存的 Promise
|
||||
if (tokenPromise) {
|
||||
try {
|
||||
const cachedResult = await tokenPromise;
|
||||
if (cachedResult.expiresAt > Date.now() + EXPIRATION_MS) {
|
||||
return cachedResult.token;
|
||||
}
|
||||
} catch (error) {
|
||||
//
|
||||
}
|
||||
}
|
||||
|
||||
// 查询storage缓存
|
||||
const res = await getMsauth();
|
||||
token = res?.token;
|
||||
exp = res?.exp;
|
||||
if (token && exp * 1000 > now + 1000) {
|
||||
return [token, exp];
|
||||
}
|
||||
|
||||
// 缓存没有或失效,查询接口
|
||||
token = await fetchData("https://edge.microsoft.com/translate/auth");
|
||||
exp = parseMSToken(token);
|
||||
await setMsauth({ token, exp });
|
||||
return [token, exp];
|
||||
tokenPromise = fetchNewToken();
|
||||
const result = await tokenPromise;
|
||||
return result.token;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -10,6 +10,17 @@ import { isBg } from "./browser";
|
||||
import { sendBgMsg } from "./msg";
|
||||
import { blobToBase64 } from "./utils";
|
||||
|
||||
/**
|
||||
* 清除缓存数据
|
||||
*/
|
||||
export const tryClearCaches = async () => {
|
||||
try {
|
||||
caches.delete(CACHE_NAME);
|
||||
} catch (err) {
|
||||
kissLog("clean caches", err);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 构造缓存 request
|
||||
* @param {*} input
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
import {
|
||||
CACHE_NAME,
|
||||
OPT_TRANS_GOOGLE,
|
||||
OPT_TRANS_MICROSOFT,
|
||||
OPT_TRANS_BAIDU,
|
||||
OPT_TRANS_TENCENT,
|
||||
OPT_LANGS_TO_CODE,
|
||||
OPT_LANGS_MAP,
|
||||
} from "../config";
|
||||
import { browser } from "./browser";
|
||||
import {
|
||||
@@ -14,52 +15,51 @@ import {
|
||||
} from "../apis";
|
||||
import { kissLog } from "./log";
|
||||
|
||||
const langdetectMap = {
|
||||
const langdetectFns = {
|
||||
[OPT_TRANS_GOOGLE]: apiGoogleLangdetect,
|
||||
[OPT_TRANS_MICROSOFT]: apiMicrosoftLangdetect,
|
||||
[OPT_TRANS_BAIDU]: apiBaiduLangdetect,
|
||||
[OPT_TRANS_TENCENT]: apiTencentLangdetect,
|
||||
};
|
||||
|
||||
/**
|
||||
* 清除缓存数据
|
||||
*/
|
||||
export const tryClearCaches = async () => {
|
||||
try {
|
||||
caches.delete(CACHE_NAME);
|
||||
} catch (err) {
|
||||
kissLog("clean caches", err);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 语言识别
|
||||
* @param {*} q
|
||||
* @param {*} text
|
||||
* @returns
|
||||
*/
|
||||
export const tryDetectLang = async (
|
||||
q,
|
||||
useRemote = false,
|
||||
text,
|
||||
useRemote = "false",
|
||||
langDetector = OPT_TRANS_MICROSOFT
|
||||
) => {
|
||||
let lang = "";
|
||||
let deLang = "";
|
||||
|
||||
if (useRemote) {
|
||||
// 远程识别
|
||||
if (useRemote === "true" && langDetector) {
|
||||
try {
|
||||
lang = await langdetectMap[langDetector](q);
|
||||
const lang = await langdetectFns[langDetector](text);
|
||||
if (lang) {
|
||||
deLang = OPT_LANGS_TO_CODE[langDetector].get(lang) || "";
|
||||
}
|
||||
} catch (err) {
|
||||
kissLog("detect lang remote", err);
|
||||
}
|
||||
}
|
||||
|
||||
if (!lang) {
|
||||
// 本地识别
|
||||
if (!deLang) {
|
||||
try {
|
||||
const res = await browser?.i18n?.detectLanguage(q);
|
||||
lang = res?.languages?.[0]?.language;
|
||||
const res = await browser?.i18n?.detectLanguage(text);
|
||||
const lang = res?.languages?.[0]?.language;
|
||||
if (OPT_LANGS_MAP.has(lang)) {
|
||||
deLang = lang;
|
||||
} else if (lang.startsWith("zh")) {
|
||||
deLang = "zh-CN";
|
||||
}
|
||||
} catch (err) {
|
||||
kissLog("detect lang local", err);
|
||||
}
|
||||
}
|
||||
|
||||
return lang;
|
||||
return deLang;
|
||||
};
|
||||
@@ -24,7 +24,7 @@ import { clearAllBatchQueue } from "./batchQueue";
|
||||
import { genTextClass } from "./style";
|
||||
import { loadingSvg } from "./svg";
|
||||
import { shortcutRegister } from "./shortcut";
|
||||
import { tryDetectLang } from ".";
|
||||
import { tryDetectLang } from "./detect";
|
||||
|
||||
/**
|
||||
* @class Translator
|
||||
@@ -436,6 +436,7 @@ export class Translator {
|
||||
}
|
||||
}
|
||||
|
||||
// todo: 利用AI总结
|
||||
#getDocDescription() {
|
||||
try {
|
||||
const meta = document.querySelector('meta[name="description"]');
|
||||
@@ -738,19 +739,29 @@ export class Translator {
|
||||
}
|
||||
|
||||
// 提前进行语言检测
|
||||
const { detectRemote, toLang, skipLangs = [] } = this.#rule;
|
||||
const { langDetector } = this.#setting;
|
||||
const deLang = await tryDetectLang(
|
||||
node.textContent,
|
||||
let deLang = "";
|
||||
const {
|
||||
detectRemote,
|
||||
langDetector
|
||||
);
|
||||
// console.log("deLang", deLang, toLang);
|
||||
if (
|
||||
deLang &&
|
||||
(toLang.slice(0, 2) === deLang.slice(0, 2) || skipLangs.includes(deLang))
|
||||
) {
|
||||
return;
|
||||
fromLang = "auto",
|
||||
toLang,
|
||||
skipLangs = [],
|
||||
} = this.#rule;
|
||||
if (fromLang === "auto") {
|
||||
const { langDetector } = this.#setting;
|
||||
deLang = await tryDetectLang(
|
||||
node.textContent,
|
||||
detectRemote,
|
||||
langDetector
|
||||
);
|
||||
if (
|
||||
deLang &&
|
||||
(toLang.slice(0, 2) === deLang.slice(0, 2) ||
|
||||
skipLangs.includes(deLang))
|
||||
) {
|
||||
// 保留处理状态,不做删除
|
||||
// this.#processedNodes.delete(node);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
let nodeGroup = [];
|
||||
@@ -762,13 +773,13 @@ export class Translator {
|
||||
if (!shouldBreak && shouldGroup) {
|
||||
nodeGroup.push(child);
|
||||
} else if (shouldBreak && nodeGroup.length) {
|
||||
this.#translateNodeGroup(nodeGroup, node);
|
||||
this.#translateNodeGroup(nodeGroup, node, deLang);
|
||||
nodeGroup = [];
|
||||
}
|
||||
});
|
||||
|
||||
if (nodeGroup.length) {
|
||||
this.#translateNodeGroup(nodeGroup, node);
|
||||
this.#translateNodeGroup(nodeGroup, node, deLang);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -834,7 +845,7 @@ export class Translator {
|
||||
}
|
||||
|
||||
// 翻译内联节点
|
||||
async #translateNodeGroup(nodes, hostNode) {
|
||||
async #translateNodeGroup(nodes, hostNode, deLang) {
|
||||
const {
|
||||
transTag,
|
||||
textStyle,
|
||||
@@ -901,8 +912,10 @@ export class Translator {
|
||||
// return;
|
||||
// }
|
||||
|
||||
const [translatedText, isSameLang] =
|
||||
await this.#translateFetch(processedString);
|
||||
const [translatedText, isSameLang] = await this.#translateFetch(
|
||||
processedString,
|
||||
deLang
|
||||
);
|
||||
// console.log("translatedText", translatedText);
|
||||
if (isSameLang || this.#runId !== currentRunId) {
|
||||
wrapper.remove();
|
||||
@@ -1060,7 +1073,7 @@ export class Translator {
|
||||
}
|
||||
|
||||
// 发起翻译请求
|
||||
#translateFetch(text) {
|
||||
#translateFetch(text, deLang = "") {
|
||||
const { apiSlug, fromLang, toLang } = this.#rule;
|
||||
const apiSetting =
|
||||
this.#setting.transApis.find((api) => api.apiSlug === apiSlug) ||
|
||||
@@ -1068,7 +1081,7 @@ export class Translator {
|
||||
|
||||
return apiTranslate({
|
||||
text,
|
||||
fromLang,
|
||||
fromLang: deLang || fromLang,
|
||||
toLang,
|
||||
apiSetting,
|
||||
docInfo: this.#docInfo,
|
||||
@@ -1295,17 +1308,23 @@ export class Translator {
|
||||
this.#init();
|
||||
}
|
||||
|
||||
// 翻译页面标题
|
||||
if (this.#rule.transTitle === "true") {
|
||||
const title = document.title;
|
||||
this.#docInfo.title = title;
|
||||
this.#translateFetch(title)
|
||||
.then(([trText]) => {
|
||||
document.title = trText || title;
|
||||
})
|
||||
.catch((err) => {
|
||||
kissLog("tanslate title", err);
|
||||
});
|
||||
this.#translateTitle();
|
||||
}
|
||||
}
|
||||
|
||||
// 翻译页面标题
|
||||
async #translateTitle() {
|
||||
const title = document.title;
|
||||
this.#docInfo.title = title;
|
||||
if (!title) return;
|
||||
|
||||
try {
|
||||
const deLang = await tryDetectLang(title);
|
||||
const [translatedTitle] = await this.#translateFetch(title, deLang);
|
||||
document.title = translatedTitle || title;
|
||||
} catch (err) {
|
||||
kissLog("tanslate title", err);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user