Skill: xujfcn/crazyrouter-translate (version 1.1.0)

--- name: crazyrouter-translate description: AI-powered translation via Crazyrouter. Translate text between any languages using GPT-5, Claude, DeepSeek, or Qwen. Supports file translation and multi-model comparison. Use when user asks to translate text, documents, or compare translations. Requires environment variable CRAZYROUTER_API_KEY (get at https://crazyrouter.com). --- # AI Translation via Crazyrouter Translate text between any languages using the best AI models through [Crazyrouter](https://crazyrouter.com). ## Script Directory **Agent Execution**: 1. `SKILL_DIR` = this SKILL.md file's directory 2. Script path = `${SKILL_DIR}/scripts/main.mjs` ## Step 0: Check API Key ⛔ BLOCKING ```bash [ -n "${CRAZYROUTER_API_KEY}" ] && echo "key_present" || echo "not_set" ``` | Result | Action | |--------|--------| | `key_present` | Continue | | `not_set` | Ask user to set `CRAZYROUTER_API_KEY`. Get key at https://crazyrouter.com | ## Usage ```bash # Basic translation node ${SKILL_DIR}/scripts/main.mjs --text "Hello world" --to zh # Translate file node ${SKILL_DIR}/scripts/main.mjs --input article.md --to ja --output article_ja.md # Use specific model node ${SKILL_DIR}/scripts/main.mjs --text "Bonjour le monde" --to en --model deepseek-r1 # Specify source language node ${SKILL_DIR}/scripts/main.mjs --text "你好世界" --from zh --to ko # Keep formatting (Markdown) node ${SKILL_DIR}/scripts/main.mjs --input README.md --to ja --output README_ja.md --format markdown ``` ### Options | Option | Description | Default | |--------|-------------|---------| | `--text <text>` | Text to translate | — | | `--input <file>` | Read from file | — | | `--output <file>` | Save to file | stdout | | `--from <lang>` | Source language | auto-detect | | `--to <lang>` | Target language (required) | — | | `--model <id>` | AI model | `gpt-4o-mini` | | `--format <fmt>` | `plain` or `markdown` | `plain` | ### Language Codes en, zh, ja, ko, es, fr, de, pt, ru, ar, vi, th, id, tr, it, pl, nl, sv, hi, ...

path: scripts/main.mjs
content: import { readFile, writeFile } from "node:fs/promises";
import process from "node:process";

const DEFAULT_MODEL = "gpt-4o-mini";
const API_BASE = process.env.CRAZYROUTER_BASE_URL || "https://crazyrouter.com/v1";

function parseArgs(argv) {
  const args = { text: null, inputFile: null, output: null, from: null, to: null, model: DEFAULT_MODEL, format: "plain" };
  for (let i = 2; i < argv.length; i++) {
    switch (argv[i]) {
      case "--text": case "-t": args.text = argv[++i]; break;
      case "--input": case "-i": args.inputFile = argv[++i]; break;
      case "--output": case "-o": args.output = argv[++i]; break;
      case "--from": args.from = argv[++i]; break;
      case "--to": args.to = argv[++i]; break;
      case "--model": case "-m": args.model = argv[++i]; break;
      case "--format": args.format = argv[++i]; break;
      case "--help": case "-h":
        console.log(`Usage: main.mjs --text "..." --to <lang> [--from <lang>] [--model gpt-4o-mini] [--output file]
Env: CRAZYROUTER_API_KEY (required)`);
        process.exit(0);
    }
  }
  return args;
}

function getApiKey() {
  const key = process.env.CRAZYROUTER_API_KEY;
  if (!key) { console.error("Error: CRAZYROUTER_API_KEY not set. Get your key at https://crazyrouter.com"); process.exit(1); }
  return key;
}

async function translate(args) {
  let text = args.text;
  if (!text && args.inputFile) {
    text = await readFile(args.inputFile, "utf-8");
    console.error(`Read ${text.length} characters from ${args.inputFile}`);
  }
  if (!text) { console.error("Error: --text or --input required"); process.exit(1); }
  if (!args.to) { console.error("Error: --to <language> required"); process.exit(1); }
  const [REDACTED_SECRET]);
  const fromHint = args.from ? `from ${args.from} ` : "";
  const formatHint = args.format === "markdown" ? " Preserve all Markdown formatting." : "";
  const systemPrompt = `You are a professional translator. Translate the following text ${fromHint}to ${args.to}. Output ONLY the translated text, nothing else.${formatHint}`;
  console.error(`Model: ${args.model} | ${args.from || "auto"} -> ${args.to}`);
  const response = await fetch(`${API_BASE}/chat/completions`, {
    method: "POST",
    headers: { "Authorization": `Bearer ${apiKey}`, "Content-Type": "application/json" },
    body: JSON.stringify({
      model: args.model,
      messages: [{ role: "system", content: systemPrompt }, { role: "user", content: text }],
      temperature: 0.3,
    }),
  });
  if (!response.ok) { console.error(`API Error (${response.status}): ${await response.text()}`); process.exit(1); }
  const result = await response.json();
  const translated = result.choices?.[0]?.message?.content ?? "";
  if (args.output) {
    await writeFile(args.output, translated);
    console.error(`Saved to ${args.output}`);
  } else {
    console.log(translated);
  }
  if (result.usage) console.error(`${result.usage.total_tokens} tokens`);
}

const args = parseArgs(process.argv);
translate(args).catch((err) => { console.error(`Error: ${err.message}`); process.exit(1); });


Security scan verdicts — ClawScan: suspicious | static analysis: suspicious | VirusTotal: clean | SkillSpector: suspicious (MEDIUM)