-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtranslator.js
More file actions
65 lines (56 loc) · 2.68 KB
/
Copy pathtranslator.js
File metadata and controls
65 lines (56 loc) · 2.68 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
let cached = {}; // key: `${src||auto}|${tgt}`
function dispatchProgress(p) {
try { window.dispatchEvent(new CustomEvent("translator-progress", { detail: { loaded: p } })); } catch {}
}
function dispatchReady() { try { window.dispatchEvent(new CustomEvent("translator-ready")); } catch {} }
async function maybeDetectSource(text, source) {
if (source && source !== "auto") return { code: source, confidence: 1, detected: true };
try {
if (!("LanguageDetector" in self)) return null;
const det = await LanguageDetector.create();
const r = await det.detect(text);
const code =
r?.language ?? r?.detectedLanguage ?? r?.detected ?? r?.code ?? r?.lang ?? "en";
const conf =
(typeof r?.confidence === "number" && r.confidence) ??
(typeof r?.probability === "number" && r.probability) ??
(typeof r?.score === "number" && r.score) ??
1;
return { code, confidence: conf, detected: true };
} catch { return null; }
}
function mockTranslate(text, target) {
const tiny = { es:{Hello:"Hola"}, te:{banana:"అరటిపండు"} };
let out = text, map = tiny[target] || {};
for (const [k,v] of Object.entries(map)) out = out.replace(new RegExp(`\\b${k}\\b`,"gi"), v);
return `[${target}] ${out}`;
}
export async function translateWithOnDeviceAI(text, sourceLang, targetLang) {
const { devFallback } = await chrome.storage.sync.get(["devFallback"]);
if (!("Translator" in self)) {
if (devFallback) return { ok:true, output: mockTranslate(text, targetLang), source: sourceLang || "auto", detectInfo:{detected:false} };
return { ok:false, error:"On-device Translator API not available in this Chrome." };
}
try {
const det = await maybeDetectSource(text, sourceLang);
const src = det?.code || (sourceLang === "auto" ? undefined : sourceLang);
const monitor = (m) => {
m?.addEventListener?.("downloadprogress", (e) => dispatchProgress(e?.progress ?? e?.loaded ?? 0));
m?.addEventListener?.("ready", () => dispatchReady());
};
const key = `${src || "auto"}|${targetLang}`;
let translator = cached[key];
if (!translator) {
const opts = { targetLanguage: targetLang, monitor };
if (src) opts.sourceLanguage = src;
translator = await Translator.create(opts);
cached[key] = translator;
dispatchReady();
}
const output = await translator.translate(text);
return { ok:true, output, source: src || "auto", detectInfo: det || { detected:false } };
} catch (e) {
if (devFallback) return { ok:true, output: mockTranslate(text, targetLang), source: sourceLang || "auto", detectInfo:{detected:false}, note:"dev-fallback" };
return { ok:false, error: e?.message || String(e) };
}
}