diff --git a/bundled-addons/translate/addon.json b/bundled-addons/translate/addon.json new file mode 100644 index 0000000..cd8ae17 --- /dev/null +++ b/bundled-addons/translate/addon.json @@ -0,0 +1,19 @@ +{ + "id": "translate", + "name": "Translate", + "version": "0.1.0", + "description": "Right-click a selection to translate it. Sidebar panel with LibreTranslate or Google as the backend.", + "author": "Silent Mode", + "icon": "🌐", + "main": "index.js", + "capabilities": ["sidebar-panel", "context-menu-item"], + "context-menu-items": [ + { + "id": "translate-selection", + "label": "Translate selection", + "when": "selectionText", + "icon": "🌐" + } + ], + "updateURL": "https://navigate.st/bns/theseus.x/extensions/translate/updates.json" +} diff --git a/bundled-addons/translate/index.js b/bundled-addons/translate/index.js new file mode 100644 index 0000000..f6cf9b8 --- /dev/null +++ b/bundled-addons/translate/index.js @@ -0,0 +1,32 @@ +// Translate — right-click a selection, get a translation in the sidebar. +// +// One sidebar panel; the panel HTML does the actual translation (LibreTranslate +// or Google unofficial free endpoint, user's pick). When the user picks +// "Translate selection" from a page's right-click menu we stash the selection +// under storage.__pending and reveal our sidebar; the panel reads __pending on +// load / on visibility change and translates immediately. + +module.exports = { + activate(api) { + api.registerSidebarPanel({ + id: "main", + title: "Translate", + icon: "🌐", + page: "panel.html", + }); + + api.onMessage("context-menu", async (payload) => { + const text = String(payload && payload.selectionText || "").trim(); + if (!text) { api.log("context-menu fired with no selection"); return; } + // Cap what we stash to keep storage tiny; the address bar and menu already + // truncate visually, but the raw selection can be huge. + const clip = text.length > 12_000 ? text.slice(0, 12_000) : text; + api.storage.set("__pending", { text: clip, host: payload.host || "", at: Date.now() }); + api.revealSidebar("main"); + api.log(`context-menu → translate ${clip.length} chars from ${payload.host || "?"}`); + return { ok: true }; + }); + + api.log("registered translate panel + context-menu item"); + }, +}; diff --git a/bundled-addons/translate/panel.html b/bundled-addons/translate/panel.html new file mode 100644 index 0000000..9e696e5 --- /dev/null +++ b/bundled-addons/translate/panel.html @@ -0,0 +1,350 @@ + + + + +Translate + + + +
+
🌐 Translate
+
ready
+
+ +
+ + + +
+ +
+
+ + +
+
+ +
The translation will appear here.
+
+
+ +
+ + +
+ +
+ + + +
+ LibreTranslate is a free MIT-licensed engine. Public instances rate-limit; if you + hit "too many requests", pick another URL or self-host. Google (unofficial) uses + translate.googleapis.com/translate_a/single — free, no key, but + unofficial and Google can break it at any time. +
+
+ + + +