UNPKG

i18n-ai-translate

Version:

Use LLMs to translate your i18n JSON to any language.

309 lines 15.9 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = buildTranslateCommand; const constants_1 = require("./constants"); const commander_1 = require("commander"); const utils_1 = require("./utils"); const cli_helpers_1 = require("./cli_helpers"); const translate_directory_1 = require("./translate_directory"); const translate_file_1 = require("./translate_file"); const fs_1 = __importStar(require("fs")); const path_1 = __importDefault(require("path")); /** * Builds the translate command for translating i18n files or directories. * @returns the translate command with its options and action. */ function buildTranslateCommand() { return new commander_1.Command("translate") .requiredOption("-i, --input <input>", "Source i18n file or path of source language, in the jsons/ directory if a relative path is given") .option("-o, --output-languages [language codes...]", "A list of languages to translate to") .requiredOption("-e, --engine <engine>", constants_1.CLI_HELP.Engine) .option("-m, --model <model>", constants_1.CLI_HELP.Model) .option("-r, --rate-limit-ms <rateLimitMs>", constants_1.CLI_HELP.RateLimit) .option("-f, --force-language-name <language name>", "Force output language name") .option("-A, --all-languages", "Translate to all supported languages") .option("-p, --templated-string-prefix <prefix>", "Prefix for templated strings", constants_1.DEFAULT_TEMPLATED_STRING_PREFIX) .option("-s, --templated-string-suffix <suffix>", "Suffix for templated strings", constants_1.DEFAULT_TEMPLATED_STRING_SUFFIX) .option("-k, --api-key <API key>", "API key") .option("-h, --host <hostIP:port>", constants_1.CLI_HELP.OllamaHost) .option("--ensure-changed-translation", constants_1.CLI_HELP.EnsureChangedTranslation, false) .option("-n, --batch-size <batchSize>", constants_1.CLI_HELP.BatchSize) .option("--skip-translation-verification", constants_1.CLI_HELP.SkipTranslationVerification, false) .option("--skip-styling-verification", constants_1.CLI_HELP.SkipStylingVerification, false) .option("--override-prompt <path to JSON file>", constants_1.CLI_HELP.OverridePromptFile) .option("--verbose", constants_1.CLI_HELP.Verbose, false) .option("--prompt-mode <prompt-mode>", constants_1.CLI_HELP.PromptMode) .option("--batch-max-tokens <batch-max-tokens>", constants_1.CLI_HELP.MaxTokens) .option("--dry-run", constants_1.CLI_HELP.DryRun, false) .action(async (options) => { const { model, chatParams, rateLimitMs, apiKey, host, promptMode, batchSize, batchMaxTokens, } = (0, cli_helpers_1.processModelArgs)(options); let overridePrompt; if (options.overridePrompt) { overridePrompt = (0, cli_helpers_1.processOverridePromptFile)(options.overridePrompt); } let dryRun; if (options.dryRun) { dryRun = { basePath: (0, fs_1.mkdtempSync)(`/tmp/i18n-ai-translate-${new Date().toISOString().replace(/[:.]/g, "-")}-`), }; } if (options.outputLanguages) { if (options.forceLanguageName) { (0, utils_1.printError)("Cannot use both --output-languages and --force-language"); return; } if (options.allLanguages) { (0, utils_1.printError)("Cannot use both --all-languages and --output-languages"); return; } if (options.outputLanguages.length === 0) { (0, utils_1.printError)("No languages specified"); return; } if (options.verbose) { (0, utils_1.printInfo)(`Translating to ${options.outputLanguages.join(", ")}...`); } const jsonFolder = path_1.default.resolve(process.cwd(), "jsons"); let inputPath; if (path_1.default.isAbsolute(options.input)) { inputPath = path_1.default.resolve(options.input); } else { inputPath = path_1.default.resolve(jsonFolder, options.input); if (!fs_1.default.existsSync(inputPath)) { inputPath = path_1.default.resolve(process.cwd(), options.input); } } if (fs_1.default.statSync(inputPath).isFile()) { let i = 0; for (const languageCode of options.outputLanguages) { i++; if (options.verbose) { (0, utils_1.printInfo)(`Translating ${i}/${options.outputLanguages.length} languages...`); } const output = (0, utils_1.getOutputPathFromInputPath)(inputPath, languageCode); if (options.input === output) { continue; } let outputPath; if (path_1.default.isAbsolute(output)) { outputPath = path_1.default.resolve(output); } else { outputPath = path_1.default.resolve(jsonFolder, output); if (!fs_1.default.existsSync(jsonFolder)) { outputPath = path_1.default.resolve(process.cwd(), output); } } try { // eslint-disable-next-line no-await-in-loop await (0, translate_file_1.translateFile)({ apiKey, batchMaxTokens, batchSize, chatParams, dryRun, engine: options.engine, ensureChangedTranslation: options.ensureChangedTranslation, host, inputFilePath: inputPath, model, outputFilePath: outputPath, overridePrompt, promptMode, rateLimitMs, skipStylingVerification: options.skipStylingVerification, skipTranslationVerification: options.skipTranslationVerification, templatedStringPrefix: options.templatedStringPrefix, templatedStringSuffix: options.templatedStringSuffix, verbose: options.verbose, }); } catch (err) { (0, utils_1.printError)(`Failed to translate file to ${languageCode}: ${err}`); } } } else { let i = 0; for (const languageCode of options.outputLanguages) { i++; if (options.verbose) { (0, utils_1.printInfo)(`Translating ${i}/${options.outputLanguages.length} languages...`); } const output = (0, utils_1.getOutputPathFromInputPath)(inputPath, languageCode); if (options.input === output) { continue; } try { // eslint-disable-next-line no-await-in-loop await (0, translate_directory_1.translateDirectory)({ apiKey, baseDirectory: path_1.default.resolve(inputPath, ".."), batchMaxTokens: options.batchMaxTokens, batchSize: options.batchSize, chatParams, dryRun, engine: options.engine, ensureChangedTranslation: options.ensureChangedTranslation, host, inputLanguage: path_1.default.basename(inputPath), model, outputLanguage: languageCode, overridePrompt, promptMode, rateLimitMs, skipStylingVerification: options.skipStylingVerification, skipTranslationVerification: options.skipTranslationVerification, templatedStringPrefix: options.templatedStringPrefix, templatedStringSuffix: options.templatedStringSuffix, verbose: options.verbose, }); } catch (err) { (0, utils_1.printError)(`Failed to translate directory to ${languageCode}: ${err}`); } } } } else { if (options.forceLanguageName) { (0, utils_1.printError)("Cannot use both --all-languages and --force-language"); return; } (0, utils_1.printWarn)("Some languages may fail to translate due to the model's limitations"); let i = 0; for (const languageCode of (0, utils_1.getAllLanguageCodes)()) { i++; if (options.verbose) { (0, utils_1.printInfo)(`Translating ${i}/${(0, utils_1.getAllLanguageCodes)().length} languages...`); } const jsonFolder = path_1.default.resolve(process.cwd(), "jsons"); let inputPath; if (path_1.default.isAbsolute(options.input)) { inputPath = path_1.default.resolve(options.input); } else { inputPath = path_1.default.resolve(jsonFolder, options.input); if (!fs_1.default.existsSync(inputPath)) { inputPath = path_1.default.resolve(process.cwd(), options.input); } } if (fs_1.default.statSync(inputPath).isFile()) { const output = (0, utils_1.getOutputPathFromInputPath)(inputPath, languageCode); if (options.input === output) { continue; } let outputPath; if (path_1.default.isAbsolute(output)) { outputPath = path_1.default.resolve(output); } else { outputPath = path_1.default.resolve(jsonFolder, output); if (!fs_1.default.existsSync(jsonFolder)) { outputPath = path_1.default.resolve(process.cwd(), output); } } try { // eslint-disable-next-line no-await-in-loop await (0, translate_file_1.translateFile)({ apiKey, batchMaxTokens: options.batchMaxTokens, batchSize: options.batchSize, chatParams, dryRun, engine: options.engine, ensureChangedTranslation: options.ensureChangedTranslation, host, inputFilePath: inputPath, model, outputFilePath: outputPath, overridePrompt, promptMode, rateLimitMs, skipStylingVerification: options.skipStylingVerification, skipTranslationVerification: options.skipTranslationVerification, templatedStringPrefix: options.templatedStringPrefix, templatedStringSuffix: options.templatedStringSuffix, verbose: options.verbose, }); } catch (err) { (0, utils_1.printError)(`Failed to translate to ${languageCode}: ${err}`); } } else { const output = (0, utils_1.getOutputPathFromInputPath)(inputPath, languageCode); if (options.input === output) { continue; } try { // eslint-disable-next-line no-await-in-loop await (0, translate_directory_1.translateDirectory)({ apiKey, baseDirectory: path_1.default.resolve(inputPath, ".."), batchMaxTokens: options.batchMaxTokens, batchSize: options.batchSize, chatParams, dryRun, engine: options.engine, ensureChangedTranslation: options.ensureChangedTranslation, host, inputLanguage: path_1.default.basename(inputPath), model, outputLanguage: languageCode, overridePrompt, promptMode, rateLimitMs, skipStylingVerification: options.skipStylingVerification, skipTranslationVerification: options.skipTranslationVerification, templatedStringPrefix: options.templatedStringPrefix, templatedStringSuffix: options.templatedStringSuffix, verbose: options.verbose, }); } catch (err) { (0, utils_1.printError)(`Failed to translate directory to ${languageCode}: ${err}`); } } } } }); } //# sourceMappingURL=cli_translate.js.map