Untitled

JavaScript Guest 8 Views Size: 3.24 KB Posted on: Jun 15, 26 @ 11:01 PM
  1. /*
  2.  * translate.js
  3.  * A HexDroid script
  4.  *
  5.  * Auto-translates incoming messages and adds a /tr command for manual one-off translation.
  6.  *
  7.  * Backend: a LibreTranslate instance (https://libretranslate.com or self-hosted).
  8.  * LibreTranslate is FOSS and has a /detect + /translate JSON API
  9.  * Point TR_ENDPOINT at your own instance for privacy + no rate limits. If your instance needs a key, set TR_KEY.
  10.  *
  11.  * The host must permit network to TR_ENDPOINT (ScriptHost.isNetworkAllowed).
  12.  */
  13.  
  14. var TR_ENDPOINT = "https://libretranslate.com";
  15. var TR_KEY      = "";          // API key for your instance
  16. var SHOW_ORIGINAL_LANG = true; // prefix the translated line with the detected lang
  17.  
  18. function appLang() {
  19.   // e.g. "en". Falls back to English if the host doesn't expose the setting.
  20.   return (setting("appLanguage") || "en").toLowerCase().slice(0, 2);
  21. }
  22.  
  23. // POST JSON and parse the reply. cb(err, obj).
  24. function postJson(path, payload, cb) {
  25.   http.post(TR_ENDPOINT + path, JSON.stringify(payload), function (res) {
  26.     if (!res.ok) { cb(res.error || ("HTTP " + res.status), null); return; }
  27.     try { cb(null, JSON.parse(res.body)); }
  28.     catch (e) { cb("bad JSON from server", null); }
  29.   });
  30. }
  31.  
  32. function detect(text, cb) {
  33.   postJson("/detect", { q: text, api_key: TR_KEY }, function (err, arr) {
  34.     if (err) { cb(err, null); return; }
  35.     // /detect returns [{ confidence, language }], best first.
  36.     if (arr && arr.length && arr[0].language) cb(null, arr[0].language);
  37.     else cb("no language detected", null);
  38.   });
  39. }
  40.  
  41. function translate(text, source, target, cb) {
  42.   postJson("/translate", {
  43.     q: text, source: source, target: target, format: "text", api_key: TR_KEY
  44.   }, function (err, obj) {
  45.     if (err) { cb(err, null); return; }
  46.     if (obj && obj.translatedText) cb(null, obj.translatedText);
  47.     else cb("no translation returned", null);
  48.   });
  49. }
  50.  
  51. // auto-translate incoming foreign messages
  52.  
  53. on("TEXT", function (e) {
  54.   if (e.isMine) return; // don't translate our own echo
  55.   var text = e.text;
  56.   if (!text || text.length < 2) return;
  57.  
  58.   var want = appLang();
  59.  
  60.   detect(text, function (err, src) {
  61.     if (err) { log("detect failed:", err); return; }
  62.     src = src.toLowerCase().slice(0, 2);
  63.     if (src === want) return;
  64.  
  65.     translate(text, src, want, function (err2, out) {
  66.       if (err2) { log("translate failed:", err2); return; }
  67.       if (!out || out === text) return;
  68.       var prefix = SHOW_ORIGINAL_LANG ? ("\u0002[" + src + "\u2192" + want + "]\u0002 ") : "";
  69.       // Inject a line under the original, attributed to the same nick.
  70.       echo(e.buffer, e.from, prefix + out);
  71.     });
  72.   });
  73. });
  74.  
  75. // /tr <text> translate something manually
  76.  
  77. command("tr", function (args, e) {
  78.   var text = (args || "").trim();
  79.   if (!text) { echo(e.buffer, "*** Usage: /tr <text to translate>"); return; }
  80.   var want = appLang();
  81.   detect(text, function (err, src) {
  82.     src = (err ? want : src).toLowerCase().slice(0, 2);
  83.     translate(text, src === want ? "auto" : src, want, function (err2, out) {
  84.       if (err2) { echo(e.buffer, "*** /tr failed: " + err2); return; }
  85.       echo(e.buffer, "*** (" + src + "\u2192" + want + ") " + out);
  86.     });
  87.   });
  88. });
  89.  
  90. log("translate.js loaded (endpoint " + TR_ENDPOINT + ")");

Raw Paste

Comments 0
Login to post a comment.
  • No comments yet. Be the first.
Login to post a comment. Login or Register
We use cookies. To comply with GDPR in the EU and the UK we have to show you these.

We use cookies and similar technologies to keep this website functional (including spam protection via Google reCAPTCHA or Cloudflare Turnstile), and — with your consent — to measure usage and show ads. See Privacy.