fix: throw more errors in translate api

This commit is contained in:
Gabe
2025-10-14 10:31:49 +08:00
parent c38a3d439d
commit b63ef8c1aa
4 changed files with 84 additions and 72 deletions

View File

@@ -378,14 +378,14 @@ export const apiBuiltinAIDetect = async (text) => {
* @param {*} param0 * @param {*} param0
* @returns * @returns
*/ */
const apiBuiltinAITranslate = ({ text, from, to, apiSetting }) => { const apiBuiltinAITranslate = async ({ text, from, to, apiSetting }) => {
if (!isBuiltinAIAvailable) { if (!isBuiltinAIAvailable) {
return ["", true]; return ["", true];
} }
const { fetchInterval, fetchLimit, httpTimeout } = apiSetting; const { fetchInterval, fetchLimit, httpTimeout } = apiSetting;
const fetchPool = getFetchPool(fetchInterval, fetchLimit); const fetchPool = getFetchPool(fetchInterval, fetchLimit);
return withTimeout( const result = await withTimeout(
fetchPool.push(fnPolyfill, { fetchPool.push(fnPolyfill, {
fn: chromeTranslate, fn: chromeTranslate,
msg: MSG_BUILTINAI_TRANSLATE, msg: MSG_BUILTINAI_TRANSLATE,
@@ -395,6 +395,17 @@ const apiBuiltinAITranslate = ({ text, from, to, apiSetting }) => {
}), }),
httpTimeout httpTimeout
); );
if (!result) {
throw new Error("apiBuiltinAITranslate got null reault");
}
const [trText, srLang, error] = result;
if (error) {
throw new Error("apiBuiltinAITranslate got error", error);
}
return [trText, srLang];
}; };
/** /**
@@ -438,17 +449,16 @@ export const apiTranslate = async ({
// 查询缓存数据 // 查询缓存数据
if (useCache) { if (useCache) {
const cache = (await getHttpCachePolyfill(cacheInput)) || {}; const cache = await getHttpCachePolyfill(cacheInput);
if (cache.trText) { if (cache?.trText) {
return [cache.trText, cache.isSame]; return [cache.trText, cache.isSame];
} }
} }
// 请求接口数据 // 请求接口数据
let trText = ""; let tranlation = [];
let srLang = "";
if (apiType === OPT_TRANS_BUILTINAI) { if (apiType === OPT_TRANS_BUILTINAI) {
[trText, srLang] = await apiBuiltinAITranslate({ tranlation = await apiBuiltinAITranslate({
text, text,
from, from,
to, to,
@@ -462,7 +472,7 @@ export const apiTranslate = async ({
batchSize, batchSize,
batchLength, batchLength,
}); });
const tranlation = await queue.addTask(text, { tranlation = await queue.addTask(text, {
from, from,
to, to,
fromLang, fromLang,
@@ -473,13 +483,8 @@ export const apiTranslate = async ({
apiSetting, apiSetting,
usePool, usePool,
}); });
if (Array.isArray(tranlation)) {
[trText, srLang = ""] = tranlation;
} else if (typeof tranlation === "string") {
trText = tranlation;
}
} else { } else {
const translations = await handleTranslate([text], { [tranlation] = await handleTranslate([text], {
from, from,
to, to,
fromLang, fromLang,
@@ -490,19 +495,24 @@ export const apiTranslate = async ({
apiSetting, apiSetting,
usePool, usePool,
}); });
if (Array.isArray(translations)) { }
if (Array.isArray(translations[0])) {
[trText, srLang = ""] = translations[0]; let trText = "";
} else { let srLang = "";
[trText, srLang = ""] = translations; if (Array.isArray(tranlation)) {
} [trText, srLang = ""] = tranlation;
} } else if (typeof tranlation === "string") {
trText = tranlation;
}
if (!trText) {
throw new Error("tanslate api got empty trtext");
} }
const isSame = fromLang === "auto" && srLang === to; const isSame = fromLang === "auto" && srLang === to;
// 插入缓存 // 插入缓存
if (useCache && trText) { if (useCache) {
putHttpCachePolyfill(cacheInput, null, { trText, isSame, srLang }); putHttpCachePolyfill(cacheInput, null, { trText, isSame, srLang });
} }

View File

@@ -745,6 +745,7 @@ export const parseTransRes = async (
let modelMsg = ""; let modelMsg = "";
// todo: 根据结果抛出实际异常信息
switch (apiType) { switch (apiType) {
case OPT_TRANS_GOOGLE: case OPT_TRANS_GOOGLE:
return [[res?.sentences?.map((item) => item.trans).join(" "), res?.src]]; return [[res?.sentences?.map((item) => item.trans).join(" "), res?.src]];
@@ -842,7 +843,7 @@ export const parseTransRes = async (
default: default:
} }
return []; throw new Error("parse translate result: apiType not matched", apiType);
}; };
/** /**
@@ -883,6 +884,9 @@ export const handleTranslate = async (
let token = ""; let token = "";
if (apiType === OPT_TRANS_MICROSOFT) { if (apiType === OPT_TRANS_MICROSOFT) {
token = await msAuth(); token = await msAuth();
if (!token) {
throw new Error("got msauth error");
}
} }
const [input, init, userMsg] = await genTransReq({ const [input, init, userMsg] = await genTransReq({
@@ -899,19 +903,18 @@ export const handleTranslate = async (
...apiSetting, ...apiSetting,
}); });
const res = await fetchData(input, init, { const response = await fetchData(input, init, {
useCache: false, useCache: false,
usePool, usePool,
fetchInterval, fetchInterval,
fetchLimit, fetchLimit,
httpTimeout, httpTimeout,
}); });
if (!res) { if (!response) {
kissLog("tranlate got empty response"); throw new Error("tranlate got empty response");
return [];
} }
return parseTransRes(res, { const result = await parseTransRes(response, {
texts, texts,
from, from,
to, to,
@@ -922,6 +925,11 @@ export const handleTranslate = async (
userMsg, userMsg,
...apiSetting, ...apiSetting,
}); });
if (!Array.isArray(result)) {
throw new Error("tranlate got an unexpected result");
}
return result;
}; };
/** /**

View File

@@ -47,11 +47,12 @@ const newCacheReq = async (input, init) => {
*/ */
export const getHttpCache = async ({ input, init }) => { export const getHttpCache = async ({ input, init }) => {
try { try {
const req = await newCacheReq(input, init); const request = await newCacheReq(input, init);
const cache = await caches.open(CACHE_NAME); const cache = await caches.open(CACHE_NAME);
const res = await cache.match(req); const response = await cache.match(request);
if (res) { if (response) {
return await parseResponse(res); const res = await parseResponse(response);
return res;
} }
} catch (err) { } catch (err) {
kissLog("get cache", err); kissLog("get cache", err);

View File

@@ -970,6 +970,7 @@ export class Translator {
// langDetector // langDetector
} = this.#setting; } = this.#setting;
const parentNode = hostNode.parentElement; const parentNode = hostNode.parentElement;
const hideOrigin = transOnly === "true";
// 翻译开始钩子函数 // 翻译开始钩子函数
if (transStartHook?.trim()) { if (transStartHook?.trim()) {
@@ -985,49 +986,37 @@ export class Translator {
} }
} }
const [processedString, placeholderMap] =
this.#serializeForTranslation(nodes);
// console.log("processedString", processedString);
if (this.#isInvalidText(processedString)) return;
const wrapper = document.createElement(this.#translationTagName);
wrapper.className = Translator.KISS_CLASS.warpper;
if (processedString.length > newlineLength) {
const br = document.createElement("br");
br.hidden = transOnly === "true";
wrapper.appendChild(br);
}
const inner = document.createElement(transTag);
inner.className = `${Translator.KISS_CLASS.inner} ${this.#textClass[textStyle]}`;
inner.appendChild(createLoadingSVG());
wrapper.appendChild(inner);
nodes[nodes.length - 1].after(wrapper);
this.#translationNodes.set(wrapper, {
nodes,
isHide: transOnly === "true",
});
const currentRunId = this.#runId;
try { try {
// const deLang = await tryDetectLang( const [processedString, placeholderMap] =
// processedString, this.#serializeForTranslation(nodes);
// detectRemote, // console.log("processedString", processedString);
// langDetector if (this.#isInvalidText(processedString)) return;
// );
// if (deLang && (toLang.includes(deLang) || skipLangs.includes(deLang))) {
// wrapper.remove();
// return;
// }
const wrapper = document.createElement(this.#translationTagName);
wrapper.className = Translator.KISS_CLASS.warpper;
if (processedString.length > newlineLength) {
const br = document.createElement("br");
br.hidden = hideOrigin;
wrapper.appendChild(br);
}
const inner = document.createElement(transTag);
inner.className = `${Translator.KISS_CLASS.inner} ${this.#textClass[textStyle]}`;
inner.appendChild(createLoadingSVG());
wrapper.appendChild(inner);
nodes[nodes.length - 1].after(wrapper);
const currentRunId = this.#runId;
const [translatedText, isSameLang] = await this.#translateFetch( const [translatedText, isSameLang] = await this.#translateFetch(
processedString, processedString,
deLang deLang
); );
// console.log("translatedText", translatedText); if (this.#runId !== currentRunId) {
if (isSameLang || this.#runId !== currentRunId) { throw new Error("Request terminated");
}
if (!translatedText || isSameLang) {
wrapper.remove(); wrapper.remove();
return; return;
} }
@@ -1036,7 +1025,11 @@ export class Translator {
translatedText, translatedText,
placeholderMap placeholderMap
); );
if (transOnly === "true") { this.#translationNodes.set(wrapper, {
nodes,
isHide: hideOrigin,
});
if (hideOrigin) {
this.#removeNodes(nodes); this.#removeNodes(nodes);
} }
@@ -1069,8 +1062,8 @@ export class Translator {
} catch (err) { } catch (err) {
// inner.textContent = `[失败]...`; // inner.textContent = `[失败]...`;
// todo: 失败重试按钮 // todo: 失败重试按钮
wrapper.remove(); kissLog("translate group error: ", err.message);
kissLog("translateNodeGroup", err); this.#cleanupDirectTranslations(hostNode);
} }
} }