#!/usr/bin/env node /** * translate.mjs — CLI-обёртка над apinex.bond /v1/tools/translator * * Использование: * node scripts/translate.mjs --target EN --text "Привет" * node scripts/translate.mjs --target EN --source RU --file page.html --out page.en.html * cat strings.txt | node scripts/translate.mjs --target EN --batch * node scripts/translate.mjs --list-languages * * Ключ берётся из HERMES_CUSTOM_APINEX_API_KEY / APINEX_API_KEY, иначе из /root/.hermes/.env. * * Для HTML (--html или авто) шаблонные токены {{...}} и содержимое защищаются * HTML-комментариями, чтобы переводчик их не трогал (они восстанавливаются после). */ import { readFileSync, writeFileSync } from "node:fs"; import { fileURLToPath } from "node:url"; import { dirname, resolve } from "node:path"; const __dirname = dirname(fileURLToPath(import.meta.url)); const API_URL = "https://api.apinex.bond/v1/tools/translator"; const LANG_URL = "https://api.apinex.bond/v1/tools/translator/languages"; const ENV_PATH = "/root/.hermes/.env"; // ---- аргументы ---- function parseArgs(argv) { const a = { target: null, source: null, html: null, batch: false, file: null, out: null, text: null, list: false, }; for (let i = 0; i < argv.length; i++) { const arg = argv[i]; const next = () => argv[++i]; switch (arg) { case "--target": case "-t": a.target = next(); break; case "--source": case "-s": a.source = next(); break; case "--html": a.html = true; break; case "--no-html": a.html = false; break; case "--batch": a.batch = true; break; case "--file": case "-f": a.file = next(); break; case "--out": case "-o": a.out = next(); break; case "--text": a.text = next(); break; case "--list-languages": case "--list": a.list = true; break; default: if (!a.text && !arg.startsWith("-")) a.text = arg; } } return a; } // ---- ключ ---- function getKey() { const fromEnv = process.env.HERMES_CUSTOM_APINEX_API_KEY || process.env.APINEX_API_KEY; if (fromEnv) return fromEnv; try { const txt = readFileSync(ENV_PATH, "utf8"); const m = txt.match(/^\s*HERMES_CUSTOM_APINEX_API_KEY\s*=\s*"?([^"\n]+)"?/m) || txt.match(/^\s*APINEX_API_KEY\s*=\s*"?([^"\n]+)"?/m); if (m) return m[1].trim(); } catch {} throw new Error("API key not found (HERMES_CUSTOM_APINEX_API_KEY / APINEX_API_KEY / " + ENV_PATH + ")"); } // ---- защита токенов,