UNPKG

i18n-ai

Version:

AI-powered translation tool for i18n JSON files

71 lines (68 loc) 6.96 kB
#!/usr/bin/env node import {u,r,v,p as p$1,t,j,i,h,g,f}from'./chunk-AOEQIIBE.js';import {Command}from'commander';import c from'fs';import _ from'path';function $(t,e=","){let o=t.split(/\r?\n/),s=[];for(let r of o){if(!r.trim())continue;let m=[],l="",n=false;for(let a=0;a<r.length;a++){let u=r[a];u==='"'?n&&r[a+1]==='"'?(l+='"',a++):n=!n:u===e&&!n?(m.push(l),l=""):l+=u;}m.push(l),s.push(m);}return s}async function V(t$1,e){let{inputPath:o,delimiter:s=",",skipHeader:r=true,overwrite:m=false}=e;if(!c.existsSync(o))throw new Error(`CSV file not found: ${o}`);let l=c.readFileSync(o,"utf-8"),n=$(l,s);if(n.length===0)throw new Error("CSV file is empty");let a=r?n[0]:null,u=r?1:0;if(a){let[,...i]=a,f=[t$1.source.code,...t$1.targets.map(g=>g.code)].filter(g=>!i.includes(g));if(f.length>0)throw new Error(`Missing language columns in CSV: ${f.join(", ")}`)}let j=[{...t$1.source,index:1},...t$1.targets.map((i,d)=>({...i,index:d+2}))];for(let i of j){let d={},f={};c.existsSync(i.path)&&(f=JSON.parse(c.readFileSync(i.path,"utf-8")));for(let h=u;h<n.length;h++){let O=n[h],y=O[0],C=O[i.index];y&&C&&(d[y]=C);}let g=m?{...f,...t(d)}:{...t(d),...f},E=_.dirname(i.path);c.existsSync(E)||c.mkdirSync(E,{recursive:true}),c.writeFileSync(i.path,JSON.stringify(g,null,2),"utf-8"),console.log(`Updated translations for ${i.code}: ${i.path}`);}console.log(` CSV import completed successfully!`);}var p=new Command;p.name("i18n-ai").description(`AI-powered translation tool for i18n JSON files Features: \u2022 Translates i18n JSON files using AI language models \u2022 Supports multiple AI providers (OpenAI, Anthropic, Gemini, DeepSeek, XAI) \u2022 Preserves JSON structure and nested keys \u2022 Smart chunking for large files \u2022 Handles existing translations \u2022 Configurable translation settings`).version("0.1.0");p.command("translate").description("Translate i18n JSON files").option("-c, --config <path>","Path to config file (default: translator.config.json)").option("-o, --overwrite","Overwrite existing translations").addHelpText("after",` Configuration File (translator.config.json): { "source": { "path": "./locales/en.json", // Source language file "code": "en" // Source language code }, "targets": [{ // Target languages to translate to "path": "./locales/es.json", "code": "es" }], "provider": "openai", // AI provider to use "model": "gpt-4", // Model to use (optional) "chunkSize": 50, // Number of keys per chunk (default: 50) "description": "My app context", // Project context for better translations "tone": "formal", // Desired tone (formal/casual/technical) "translateAllAtOnce": false, // Translate entire file at once "overwrite": false, // Overwrite existing translations "customProvider": { // Custom translation API configuration "url": "https://api.example.com/translate", // API endpoint "method": "POST", // HTTP method (default: POST) "headers": {}, // Custom HTTP headers "body": {}, // Request body template (supports placeholders) "responsePath": "translation", // Path to extract result from response "apiKeyEnvVar": "CUSTOM_API_KEY" // Env var with API key } } Environment Variables: OPENAI_API_KEY - OpenAI API key ANTHROPIC_API_KEY - Anthropic API key GEMINI_API_KEY - Google Gemini API key DEEPSEEK_API_KEY - DeepSeek API key XAI_API_KEY - XAI API key [custom env var] - For custom provider if configured Examples: $ i18n-ai translate # Use default config $ i18n-ai translate -c custom-config.json # Use custom config $ i18n-ai translate --overwrite # Overwrite existing translations `).action(async t=>{try{await u({configPath:t.config,overwrite:t.overwrite});}catch(e){console.error("Translation failed:",e),process.exit(1);}});p.command("models").description("List available AI models").option("-p, --provider <provider>","Show models for specific provider (openai, anthropic, gemini, deepseek, xai)").addHelpText("after",` Examples: $ i18n-ai models # List all available models $ i18n-ai models --provider openai # List OpenAI models only `).action(t=>{let e=(o,s)=>{console.log(` ${o.toUpperCase()}:`);let r=Object.keys(s).join(" | ");console.log(r),console.log();};if(t.provider){let o=t.provider.toLowerCase();switch(o){case "openai":e("OpenAI",f);break;case "anthropic":e("Anthropic",g);break;case "gemini":e("Gemini",h);break;case "deepseek":e("DeepSeek",i);break;case "xai":e("XAI",j);break;default:console.error(`Unknown provider: ${o}`),process.exit(1);}}else e("OpenAI",f),e("Anthropic",g),e("Gemini",h),e("DeepSeek",i),e("XAI",j);});p.command("export").description("Export translations to CSV format").option("-c, --config <path>","Path to config file (default: translator.config.json)").option("-o, --output <path>","Output path for CSV file (default: translations-export.csv)").option("-d, --delimiter <char>","Delimiter to use in CSV (default: ,)").addHelpText("after",` Examples: $ i18n-ai export # Use default settings $ i18n-ai export --output ./exports/translations.csv $ i18n-ai export --delimiter ";" $ i18n-ai export -c custom-config.json # Use custom config `).action(async t=>{try{let e=r(t.config);await v(e,{outputPath:t.output,delimiter:t.delimiter});}catch(e){console.error("Export failed:",e),process.exit(1);}});p.command("import").description("Import translations from a CSV file").option("-c, --config <path>","Path to config file (default: translator.config.json)").option("-i, --input <path>","Input CSV file path").option("-d, --delimiter <char>","Delimiter to use in CSV (default: ,)").option("--no-header","Skip header row in CSV").option("-o, --overwrite","Overwrite existing translations").addHelpText("after",` Examples: $ i18n-ai import -i translations.csv # Use default settings $ i18n-ai import -i ./data/translations.csv # Custom input path $ i18n-ai import -i translations.csv -d ";" # Custom delimiter $ i18n-ai import -i translations.csv --no-header # Skip header row $ i18n-ai import -i translations.csv --overwrite # Overwrite existing $ i18n-ai import -c custom-config.json -i translations.csv `).action(async t=>{try{let e=r(t.config);await V(e,{inputPath:t.input,delimiter:t.delimiter,skipHeader:t.header!==!1,overwrite:t.overwrite});}catch(e){console.error("Import failed:",e),process.exit(1);}});p.command("providers").description("List all available translation providers").action(()=>{let t=p$1();Object.entries(t.models).forEach(([e,o])=>{console.log(` ${e.toUpperCase()}:`);let s=Object.keys(o).join(" | ");console.log(s);});});p.parse();