UNPKG

@scoutello/i18n-magic

Version:

Intelligent CLI toolkit that automates internationalization workflows with AI-powered translations for JavaScript/TypeScript projects

113 lines (97 loc) 3.5 kB
import { Command } from "commander" import dotenv from "dotenv" import OpenAI from "openai" import { checkMissing } from "./commands/check-missing" import { removeUnusedKeys } from "./commands/clean" import { replaceTranslation } from "./commands/replace" import { translateMissing } from "./commands/scan" import { syncLocales } from "./commands/sync-locales" import type { CommandType, Configuration } from "./lib/types" import { loadConfig } from "./lib/utils" const program = new Command() program .name("i18n-magic") .description( "CLI to help you manage your locales JSON with translations, replacements, etc. with OpenAI.", ) .version("0.2.0") .option("-c, --config <path>", "path to config file") .option("-e, --env <path>", "path to .env file") const commands: CommandType[] = [ { name: "scan", description: "Scan for missing translations, get prompted for each, translate it to the other locales and save it to the JSON file.", action: translateMissing, }, { name: "replace", description: "Replace a translation based on the key, and translate it to the other locales and save it to the JSON file.", action: replaceTranslation, }, { name: "check-missing", description: "Check if there are any missing translations. Useful for a CI/CD pipeline or husky hook.", action: checkMissing, }, { name: "sync", description: "Sync the translations from the default locale to the other locales. Useful for a CI/CD pipeline or husky hook.", action: syncLocales, }, { name: "clean", description: "Remove unused translations from all locales. Useful for a CI/CD pipeline or husky hook.", action: removeUnusedKeys, }, ] for (const command of commands) { const cmd = program.command(command.name).description(command.description) // Add key option to replace command if (command.name === "replace") { cmd .option("-k, --key <key>", "translation key to replace") .allowExcessArguments(true) .argument("[key]", "translation key to replace") } cmd.action(async (arg, options) => { const res = dotenv.config({ path: program.opts().env || ".env", }) const config: Configuration = await loadConfig({ configPath: program.opts().config, }) const isGemini = (config.model as string)?.includes("gemini") // Get API key from environment or config const openaiKey = res.parsed.OPENAI_API_KEY || config.OPENAI_API_KEY const geminiKey = res.parsed.GEMINI_API_KEY || config.GEMINI_API_KEY // Select appropriate key based on model type const key = isGemini ? geminiKey : openaiKey if (!key) { const keyType = isGemini ? "GEMINI_API_KEY" : "OPENAI_API_KEY" console.error( `Please provide a${isGemini ? " Gemini" : "n OpenAI"} API key in your .env file or config, called ${keyType}.`, ) process.exit(1) } const openai = new OpenAI({ apiKey: key, ...(isGemini && { baseURL: "https://generativelanguage.googleapis.com/v1beta/openai/", }), }) // For replace command, check for key in argument or option if (command.name === "replace") { // If key is provided as positional argument, use that first const keyToUse = typeof arg === "string" ? arg : options.key command.action({ ...config, openai }, keyToUse) } else { command.action({ ...config, openai }) } }) } program.parse(process.argv)