i18n-ai-cli 1.0.1 → 1.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -8,6 +8,7 @@ AI-powered CLI tool for managing translation files in internationalized applicat
8
8
  - **Language Management**: Add or remove locales with ease, with optional cloning from existing locales.
9
9
  - **Key Management**: Add, update, or remove translation keys across all locales.
10
10
  - **Cleanup**: Identify and remove unused translation keys by scanning source code.
11
+ - **Validation**: Detect missing, extra, or type-mismatched keys across locale files with auto-correction support.
11
12
  - **Structural Validation**: Prevents conflicts between nested and flat key structures.
12
13
  - **Dry Run**: Preview changes before they are applied.
13
14
  - **CI Friendly**: Non-interactive mode with deterministic exit codes and fail-on-change semantics.
@@ -31,12 +32,32 @@ npm install -g i18n-ai-cli
31
32
  npm install --save-dev i18n-ai-cli
32
33
  ```
33
34
 
34
- Then use with `npx`:
35
+ When installed locally, the `i18n-ai-cli` command is not automatically available in your shell PATH. Use one of these methods:
35
36
 
37
+ **Option 1: Use npx (recommended)**
36
38
  ```bash
37
39
  npx i18n-ai-cli --help
38
40
  ```
39
41
 
42
+ **Option 2: Add a script to your package.json**
43
+ ```json
44
+ {
45
+ "scripts": {
46
+ "i18n": "i18n-ai-cli"
47
+ }
48
+ }
49
+ ```
50
+ Then run:
51
+ ```bash
52
+ npm run i18n -- --help
53
+ ```
54
+
55
+ **Option 3: Install globally**
56
+ ```bash
57
+ npm install -g i18n-ai-cli
58
+ i18n-ai-cli --help
59
+ ```
60
+
40
61
  ## Quick Start
41
62
 
42
63
  ```bash
@@ -51,6 +72,9 @@ i18n-ai-cli add:key welcome.message --value "Welcome to our app"
51
72
 
52
73
  # Clean up unused keys
53
74
  i18n-ai-cli clean:unused
75
+
76
+ # Validate translation files
77
+ i18n-ai-cli validate
54
78
  ```
55
79
 
56
80
  ## Configuration
@@ -183,6 +207,28 @@ Example: `i18n-ai-cli remove:key auth.login.title`
183
207
 
184
208
  Removes the key from all locales.
185
209
 
210
+ ### Validation Commands
211
+
212
+ #### Validate translation files
213
+
214
+ ```bash
215
+ i18n-ai-cli validate [--provider <provider>]
216
+ ```
217
+
218
+ Validates all translation files against the default locale, detecting:
219
+ - **Missing keys**: Keys present in the default locale but missing in other locales
220
+ - **Extra keys**: Keys present in other locales but not in the default locale
221
+ - **Type mismatches**: Keys where the value type differs from the default locale
222
+
223
+ Options:
224
+ - `--provider <provider>`: Use a translation provider to auto-translate missing keys. Supported: `openai`, `google`
225
+
226
+ The command will display a report of all issues found and optionally auto-correct them:
227
+ - Without a provider: Missing keys are filled with empty strings
228
+ - With a provider: Missing keys are automatically translated
229
+
230
+ **Note:** Extra keys are always removed during auto-correction, and type mismatches are fixed based on the default locale's value type.
231
+
186
232
  ### Maintenance Commands
187
233
 
188
234
  #### Clean unused keys
@@ -250,6 +296,16 @@ i18n-ai-cli add:lang de --from en
250
296
  i18n-ai-cli remove:key auth.legacy --dry-run
251
297
  ```
252
298
 
299
+ ### Validate with auto-translation
300
+ ```bash
301
+ # Validate and auto-translate missing keys using OpenAI
302
+ export OPENAI_API_KEY=sk-your-api-key-here
303
+ i18n-ai-cli validate --provider openai
304
+
305
+ # Or use Google Translate (no API key required)
306
+ i18n-ai-cli validate --provider google
307
+ ```
308
+
253
309
  ### Skip confirmation prompts
254
310
  ```bash
255
311
  i18n-ai-cli clean:unused --yes
@@ -265,6 +321,15 @@ To apply changes in CI:
265
321
  i18n-ai-cli clean:unused --ci --yes
266
322
  ```
267
323
 
324
+ ### Validate in CI
325
+ ```bash
326
+ # Check for validation issues (fails if any found)
327
+ i18n-ai-cli validate --ci --dry-run
328
+
329
+ # Auto-correct validation issues in CI
330
+ i18n-ai-cli validate --ci --yes
331
+ ```
332
+
268
333
  ### Initialize in non-interactive mode
269
334
  ```bash
270
335
  i18n-ai-cli init --yes
package/dist/cli.js CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  // src/bin/cli.ts
4
4
  import { Command } from "commander";
5
- import chalk8 from "chalk";
5
+ import chalk9 from "chalk";
6
6
 
7
7
  // src/config/config-loader.ts
8
8
  import fs from "fs-extra";
@@ -423,9 +423,10 @@ async function maybeInitLocales(config, options) {
423
423
  return;
424
424
  }
425
425
  await fs3.ensureDir(localesPath);
426
+ const defaultLocale = config.defaultLocale.replace(/\.json$/i, "");
426
427
  const defaultLocaleFile = path3.join(
427
428
  localesPath,
428
- `${config.defaultLocale}.json`
429
+ `${defaultLocale}.json`
429
430
  );
430
431
  if (await fs3.pathExists(defaultLocaleFile)) {
431
432
  return;
@@ -956,6 +957,262 @@ async function cleanUnusedCommand(context) {
956
957
  }
957
958
  }
958
959
 
960
+ // src/commands/validate.ts
961
+ import chalk8 from "chalk";
962
+ function detectTypeMismatches(referenceFlat, localeFlat) {
963
+ const mismatches = [];
964
+ for (const key of Object.keys(referenceFlat)) {
965
+ if (!(key in localeFlat)) continue;
966
+ const refType = typeof referenceFlat[key];
967
+ const locType = typeof localeFlat[key];
968
+ if (refType !== locType) {
969
+ mismatches.push({ key, expected: refType, actual: locType });
970
+ }
971
+ }
972
+ return mismatches;
973
+ }
974
+ function printReport(reports) {
975
+ let totalIssues = 0;
976
+ for (const { locale, issues } of reports) {
977
+ const issueCount = issues.missingKeys.length + issues.extraKeys.length + issues.typeMismatches.length;
978
+ if (issueCount === 0) {
979
+ console.log(chalk8.green(` \u2714 ${locale}.json \u2014 no issues`));
980
+ continue;
981
+ }
982
+ totalIssues += issueCount;
983
+ console.log(chalk8.yellow(` \u2718 ${locale}.json \u2014 ${issueCount} issue(s)`));
984
+ if (issues.missingKeys.length > 0) {
985
+ console.log(chalk8.red(` Missing keys (${issues.missingKeys.length}):`));
986
+ for (const key of issues.missingKeys.slice(0, 10)) {
987
+ console.log(` - ${key}`);
988
+ }
989
+ if (issues.missingKeys.length > 10) {
990
+ console.log(
991
+ chalk8.gray(` ... and ${issues.missingKeys.length - 10} more`)
992
+ );
993
+ }
994
+ }
995
+ if (issues.extraKeys.length > 0) {
996
+ console.log(chalk8.red(` Extra keys (${issues.extraKeys.length}):`));
997
+ for (const key of issues.extraKeys.slice(0, 10)) {
998
+ console.log(` - ${key}`);
999
+ }
1000
+ if (issues.extraKeys.length > 10) {
1001
+ console.log(
1002
+ chalk8.gray(` ... and ${issues.extraKeys.length - 10} more`)
1003
+ );
1004
+ }
1005
+ }
1006
+ if (issues.typeMismatches.length > 0) {
1007
+ console.log(
1008
+ chalk8.red(` Type mismatches (${issues.typeMismatches.length}):`)
1009
+ );
1010
+ for (const m of issues.typeMismatches.slice(0, 10)) {
1011
+ console.log(
1012
+ ` - ${m.key}: expected ${m.expected}, got ${m.actual}`
1013
+ );
1014
+ }
1015
+ if (issues.typeMismatches.length > 10) {
1016
+ console.log(
1017
+ chalk8.gray(
1018
+ ` ... and ${issues.typeMismatches.length - 10} more`
1019
+ )
1020
+ );
1021
+ }
1022
+ }
1023
+ }
1024
+ console.log("");
1025
+ if (totalIssues === 0) {
1026
+ console.log(chalk8.green("\u2714 All translation files are valid.\n"));
1027
+ } else {
1028
+ console.log(
1029
+ chalk8.yellow(`Found ${totalIssues} issue(s) across locale files.
1030
+ `)
1031
+ );
1032
+ }
1033
+ }
1034
+ async function translateKey(translator, sourceText, targetLocale, sourceLocale) {
1035
+ if (typeof sourceText !== "string" || sourceText === "") {
1036
+ return "";
1037
+ }
1038
+ const result = await translator.translate({
1039
+ text: sourceText,
1040
+ targetLocale,
1041
+ sourceLocale
1042
+ });
1043
+ return result.text;
1044
+ }
1045
+ async function validateCommand(context, validateOptions = {}) {
1046
+ const { config, fileManager, options } = context;
1047
+ const { dryRun, yes, ci } = options;
1048
+ const { translator } = validateOptions;
1049
+ console.log(chalk8.cyan("\nValidating translation files...\n"));
1050
+ const defaultLocale = config.defaultLocale;
1051
+ const referenceData = await fileManager.readLocale(defaultLocale);
1052
+ const referenceFlat = flattenObject(referenceData);
1053
+ const referenceKeys = new Set(Object.keys(referenceFlat));
1054
+ const otherLocales = config.supportedLocales.filter(
1055
+ (l) => l !== defaultLocale
1056
+ );
1057
+ const reports = [];
1058
+ for (const locale of otherLocales) {
1059
+ const localeData = await fileManager.readLocale(locale);
1060
+ const localeFlat = flattenObject(localeData);
1061
+ const localeKeys = new Set(Object.keys(localeFlat));
1062
+ const missingKeys = [...referenceKeys].filter((k) => !localeKeys.has(k));
1063
+ const extraKeys = [...localeKeys].filter((k) => !referenceKeys.has(k));
1064
+ const typeMismatches = detectTypeMismatches(referenceFlat, localeFlat);
1065
+ reports.push({
1066
+ locale,
1067
+ issues: { missingKeys, extraKeys, typeMismatches }
1068
+ });
1069
+ }
1070
+ printReport(reports);
1071
+ const fixableReports = reports.filter(
1072
+ (r) => r.issues.missingKeys.length > 0 || r.issues.extraKeys.length > 0 || r.issues.typeMismatches.length > 0
1073
+ );
1074
+ if (fixableReports.length === 0) {
1075
+ return;
1076
+ }
1077
+ if (ci && !yes) {
1078
+ throw new Error(
1079
+ `CI mode: validation found issues in ${fixableReports.length} locale(s). Re-run with --yes to auto-correct.`
1080
+ );
1081
+ }
1082
+ const confirmMsg = translator ? "Auto-correct these issues? (translates missing keys, removes extra keys, re-translates type mismatches)" : "Auto-correct these issues? (adds missing keys as empty strings, removes extra keys, fixes type mismatches)";
1083
+ const confirmed = await confirmAction(confirmMsg, {
1084
+ skip: yes ?? false,
1085
+ ci: ci ?? false
1086
+ });
1087
+ if (!confirmed) {
1088
+ console.log(chalk8.red("\nAuto-correction cancelled.\n"));
1089
+ return;
1090
+ }
1091
+ for (const { locale, issues } of fixableReports) {
1092
+ const localeData = await fileManager.readLocale(locale);
1093
+ const localeFlat = flattenObject(localeData);
1094
+ const keysToTranslate = [
1095
+ ...issues.missingKeys,
1096
+ ...issues.typeMismatches.map((m) => m.key)
1097
+ ];
1098
+ if (translator && keysToTranslate.length > 0) {
1099
+ console.log(
1100
+ chalk8.gray(
1101
+ ` Translating ${keysToTranslate.length} key(s) to ${locale}...`
1102
+ )
1103
+ );
1104
+ for (const key of keysToTranslate) {
1105
+ const sourceText = String(referenceFlat[key] ?? "");
1106
+ localeFlat[key] = await translateKey(
1107
+ translator,
1108
+ sourceText,
1109
+ locale,
1110
+ defaultLocale
1111
+ );
1112
+ }
1113
+ } else {
1114
+ for (const key of keysToTranslate) {
1115
+ localeFlat[key] = "";
1116
+ }
1117
+ }
1118
+ for (const key of issues.extraKeys) {
1119
+ delete localeFlat[key];
1120
+ }
1121
+ const rebuilt = config.keyStyle === "nested" ? unflattenObject(localeFlat) : localeFlat;
1122
+ await fileManager.writeLocale(locale, rebuilt, {
1123
+ dryRun: dryRun ?? false
1124
+ });
1125
+ console.log(chalk8.green(`\u2714 Fixed ${locale}.json`));
1126
+ }
1127
+ if (dryRun) {
1128
+ console.log(
1129
+ chalk8.yellow("\n[DRY RUN] No files were modified.\n")
1130
+ );
1131
+ } else {
1132
+ console.log(
1133
+ chalk8.green(
1134
+ `
1135
+ \u2728 Auto-corrected ${fixableReports.length} locale file(s).
1136
+ `
1137
+ )
1138
+ );
1139
+ }
1140
+ }
1141
+
1142
+ // src/providers/google.ts
1143
+ import { translate } from "@vitalets/google-translate-api";
1144
+ var GoogleTranslator = class {
1145
+ name = "google";
1146
+ options;
1147
+ constructor(options = {}) {
1148
+ this.options = options;
1149
+ }
1150
+ async translate(request) {
1151
+ const { text, targetLocale, sourceLocale } = request;
1152
+ const { from, host, fetchOptions } = this.options;
1153
+ const translateOptions = { to: targetLocale };
1154
+ if (host !== void 0) {
1155
+ translateOptions.host = host;
1156
+ }
1157
+ if (fetchOptions !== void 0) {
1158
+ translateOptions.fetchOptions = fetchOptions;
1159
+ }
1160
+ if (sourceLocale !== void 0) {
1161
+ translateOptions.from = sourceLocale;
1162
+ } else if (from !== void 0) {
1163
+ translateOptions.from = from;
1164
+ }
1165
+ const result = await translate(text, translateOptions);
1166
+ return {
1167
+ text: result.text,
1168
+ detectedSourceLocale: result.raw?.src,
1169
+ provider: this.name
1170
+ };
1171
+ }
1172
+ };
1173
+
1174
+ // src/providers/openai.ts
1175
+ import OpenAI from "openai";
1176
+ var OpenAITranslator = class {
1177
+ name = "openai";
1178
+ client;
1179
+ model;
1180
+ constructor(options = {}) {
1181
+ const apiKey = options.apiKey ?? process.env.OPENAI_API_KEY;
1182
+ if (!apiKey) {
1183
+ throw new Error(
1184
+ "OpenAI API key is required. Provide it via the 'apiKey' constructor option or set the OPENAI_API_KEY environment variable."
1185
+ );
1186
+ }
1187
+ this.model = options.model ?? "gpt-3.5-turbo";
1188
+ this.client = new OpenAI({
1189
+ apiKey,
1190
+ ...options.baseUrl ? { baseURL: options.baseUrl } : {}
1191
+ });
1192
+ }
1193
+ async translate(request) {
1194
+ const { text, targetLocale, sourceLocale, context } = request;
1195
+ const sourcePart = sourceLocale ? ` from ${sourceLocale}` : "";
1196
+ const systemMessage = `You are a professional translator. Translate the given text${sourcePart} to ${targetLocale}. Return ONLY the translated text, nothing else. Do not add quotes, explanations, or any extra formatting.`;
1197
+ const userMessage = context ? `Context: ${context}
1198
+
1199
+ ${text}` : text;
1200
+ const response = await this.client.chat.completions.create({
1201
+ model: this.model,
1202
+ temperature: 0.3,
1203
+ messages: [
1204
+ { role: "system", content: systemMessage },
1205
+ { role: "user", content: userMessage }
1206
+ ]
1207
+ });
1208
+ const content = response.choices[0]?.message?.content?.trim() ?? "";
1209
+ return {
1210
+ text: content,
1211
+ provider: this.name
1212
+ };
1213
+ }
1214
+ };
1215
+
959
1216
  // src/bin/cli.ts
960
1217
  var program = new Command();
961
1218
  program.name("i18n-ai-cli").description("Professional CLI tool for managing translation files").version("1.0.0");
@@ -1003,11 +1260,37 @@ withGlobalOptions(
1003
1260
  await cleanUnusedCommand(context);
1004
1261
  })
1005
1262
  );
1263
+ withGlobalOptions(
1264
+ program.command("validate").description("Validate & auto-correct existing translation files").option(
1265
+ "-p, --provider <provider>",
1266
+ "Translation provider for missing keys (google, openai)"
1267
+ ).action(async (options) => {
1268
+ const context = await buildContext(options);
1269
+ let translator;
1270
+ if (options.provider) {
1271
+ const provider = options.provider;
1272
+ if (provider === "google") {
1273
+ translator = new GoogleTranslator();
1274
+ } else if (provider === "openai") {
1275
+ translator = new OpenAITranslator();
1276
+ } else {
1277
+ throw new Error(
1278
+ `Unknown translation provider "${provider}". Use "google" or "openai".`
1279
+ );
1280
+ }
1281
+ } else if (process.env.OPENAI_API_KEY) {
1282
+ translator = new OpenAITranslator();
1283
+ } else {
1284
+ translator = new GoogleTranslator();
1285
+ }
1286
+ await validateCommand(context, { translator });
1287
+ })
1288
+ );
1006
1289
  program.exitOverride();
1007
1290
  try {
1008
1291
  await program.parseAsync(process.argv);
1009
1292
  } catch (err) {
1010
- console.error(chalk8.red("\u274C Error:"), err.message);
1293
+ console.error(chalk9.red("\u274C Error:"), err.message);
1011
1294
  process.exitCode = 1;
1012
1295
  }
1013
1296
  //# sourceMappingURL=cli.js.map
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/bin/cli.ts","../src/config/config-loader.ts","../src/core/file-manager.ts","../src/context/build-context.ts","../src/commands/init.ts","../src/core/confirmation.ts","../src/commands/add-lang.ts","../src/commands/remove-lang.ts","../src/commands/add-key.ts","../src/core/object-utils.ts","../src/core/key-validator.ts","../src/commands/update-key.ts","../src/commands/remove-key.ts","../src/commands/clean-unused.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport { Command } from \"commander\";\nimport chalk from \"chalk\";\nimport { buildContext } from \"../context/build-context.js\";\nimport { initCommand } from \"../commands/init.js\";\nimport { addLang } from \"../commands/add-lang.js\";\nimport { removeLangCommand } from \"../commands/remove-lang.js\";\nimport { addKeyCommand } from \"../commands/add-key.js\";\nimport { updateKeyCommand } from \"../commands/update-key.js\";\nimport { removeKeyCommand } from \"../commands/remove-key.js\";\nimport { cleanUnusedCommand } from \"../commands/clean-unused.js\";\n\nconst program = new Command();\n\nprogram\n .name(\"i18n-ai-cli\")\n .description(\"Professional CLI tool for managing translation files\")\n .version(\"1.0.0\");\n\n// Global options helper\nfunction withGlobalOptions(command: Command): Command {\n return command\n .option(\"-y, --yes\", \"Skip confirmation prompts\")\n .option(\"--dry-run\", \"Preview changes without writing files\")\n .option(\"--ci\", \"Run in CI mode (no prompts, exit on issues)\")\n .option(\"-f, --force\", \"Force operation even if validation fails\");\n}\n\n// Language Commands\nwithGlobalOptions(\n program\n .command(\"init\")\n .description(\"Create an i18n-cli configuration file\")\n .action(async (options) => {\n await initCommand(options);\n })\n);\n\nwithGlobalOptions(\n program\n .command(\"add:lang <lang>\")\n .option(\"--from <locale>\", \"Clone from existing locale\")\n .option(\"--strict\", \"Enable strict mode\")\n .description(\"Add new language locale\")\n .action(async (lang, options) => {\n const context = await buildContext(options);\n await addLang(lang, options, context);\n })\n);\n\nwithGlobalOptions(\n program\n .command(\"remove:lang\")\n .argument(\"<lang>\", \"Language code to remove\")\n .description(\"Remove a language translation file\")\n .action(async (lang, options) => {\n const context = await buildContext(options);\n await removeLangCommand(context, lang);\n })\n);\n\n//\n// Key Commands\n//\nwithGlobalOptions(\n program\n .command(\"add:key\")\n .argument(\"<key>\", \"Translation key (e.g., auth.login.title)\")\n .requiredOption(\"-v, --value <value>\", \"Value for default locale\")\n .description(\"Add new translation key to all locales\")\n .action(async (key, options) => {\n const context = await buildContext(options);\n await addKeyCommand(context, key, options);\n })\n);\n\nwithGlobalOptions(\n program\n .command(\"update:key\")\n .argument(\"<key>\", \"Translation key\")\n .requiredOption(\"-v, --value <value>\", \"New value\")\n .option(\"-l, --locale <locale>\", \"Specific locale to update\")\n .description(\"Update translation key\")\n .action(async (key, options) => {\n const context = await buildContext(options);\n await updateKeyCommand(context, key, options);\n })\n);\n\nwithGlobalOptions(\n program\n .command(\"remove:key\")\n .argument(\"<key>\", \"Translation key to remove\")\n .description(\"Remove translation key from all locales\")\n .action(async (key, options) => {\n const context = await buildContext(options);\n await removeKeyCommand(context, key);\n })\n);\n\n// Clean Command\nwithGlobalOptions(\n program\n .command(\"clean:unused\")\n .description(\"Remove unused translation keys from all locales\")\n .action(async (options) => {\n const context = await buildContext(options);\n await cleanUnusedCommand(context);\n })\n);\n\n// Global Error Handling\nprogram.exitOverride();\n\ntry {\n await program.parseAsync(process.argv);\n} catch (err: any) {\n console.error(chalk.red(\"❌ Error:\"), err.message);\n process.exitCode = 1;\n}\n","import fs from \"fs-extra\";\nimport path from \"path\";\nimport { z } from \"zod\";\nimport type { I18nConfig } from \"./types.js\";\n\nexport const CONFIG_FILE_NAME = \"i18n-cli.config.json\";\n\nconst ConfigSchema = z.object({\n localesPath: z.string().min(1),\n defaultLocale: z.string().min(2),\n supportedLocales: z.array(z.string().min(2)),\n keyStyle: z.enum([\"flat\", \"nested\"]).default(\"nested\"),\n usagePatterns: z.array(z.string()).default([]),\n autoSort: z.boolean().default(true)\n});\n\ntype ParsedConfig = z.infer<typeof ConfigSchema>;\n\nfunction resolveConfigPath(): string {\n const cwd = process.cwd();\n return path.join(cwd, CONFIG_FILE_NAME);\n}\n\nexport async function loadConfig(): Promise<I18nConfig> {\n const configPath = resolveConfigPath();\n\n if (!(await fs.pathExists(configPath))) {\n throw new Error(\n `Configuration file \"${CONFIG_FILE_NAME}\" not found in project root.\\n` +\n `Run \"i18n-cli init\" to create one.`\n );\n }\n\n let rawConfig: unknown;\n\n try {\n rawConfig = await fs.readJson(configPath);\n } catch (err) {\n throw new Error(\n `Failed to parse ${CONFIG_FILE_NAME}. Ensure it contains valid JSON.`\n );\n }\n\n const parsed = ConfigSchema.safeParse(rawConfig);\n\n if (!parsed.success) {\n const errors = parsed.error.issues\n .map(e => `• ${e.path.join(\".\")}: ${e.message}`)\n .join(\"\\n\");\n\n throw new Error(\n `Invalid configuration in ${CONFIG_FILE_NAME}:\\n${errors}`\n );\n }\n\n const config = parsed.data;\n\n validateConfigLogic(config);\n const compiledUsagePatterns = compileUsagePatterns(\n config.usagePatterns\n );\n\n return {\n ...config,\n compiledUsagePatterns\n };\n}\n\nfunction validateConfigLogic(config: ParsedConfig): void {\n if (!config.supportedLocales.includes(config.defaultLocale)) {\n throw new Error(\n `defaultLocale \"${config.defaultLocale}\" must be included in supportedLocales.`\n );\n }\n\n const duplicates = findDuplicates(config.supportedLocales);\n if (duplicates.length > 0) {\n throw new Error(\n `Duplicate locales found in supportedLocales: ${duplicates.join(\", \")}`\n );\n }\n}\n\nexport function compileUsagePatterns(patterns: string[]): RegExp[] {\n if (patterns.length === 0) {\n return [];\n }\n\n return patterns.map((pattern, index) => {\n let regex: RegExp;\n\n try {\n regex = new RegExp(pattern, \"g\");\n } catch (err) {\n throw new Error(\n `Invalid regex in usagePatterns[${index}]: ${String(err)}`\n );\n }\n\n const groupCount = countCapturingGroups(pattern);\n if (groupCount === 0) {\n throw new Error(\n `usagePatterns[${index}] must include a capturing group (use a named group like \"(?<key>...)\" or a standard \"(...)\").`\n );\n }\n\n return regex;\n });\n}\n\nfunction countCapturingGroups(pattern: string): number {\n let count = 0;\n let inCharClass = false;\n\n for (let i = 0; i < pattern.length; i++) {\n const char = pattern[i];\n\n if (char === \"\\\\\") {\n i += 1;\n continue;\n }\n\n if (char === \"[\") {\n inCharClass = true;\n continue;\n }\n\n if (char === \"]\" && inCharClass) {\n inCharClass = false;\n continue;\n }\n\n if (inCharClass) {\n continue;\n }\n\n if (char !== \"(\") {\n continue;\n }\n\n const next = pattern[i + 1];\n if (next !== \"?\") {\n count += 1;\n continue;\n }\n\n const next2 = pattern[i + 2];\n if (next2 !== \"<\") {\n continue;\n }\n\n const next3 = pattern[i + 3];\n if (next3 === \"=\" || next3 === \"!\") {\n continue;\n }\n\n count += 1;\n }\n\n return count;\n}\n\nfunction findDuplicates(arr: string[]): string[] {\n const seen = new Set<string>();\n const duplicates: string[] = [];\n\n for (const item of arr) {\n if (seen.has(item)) {\n duplicates.push(item);\n }\n seen.add(item);\n }\n\n return duplicates;\n}\n","import fs from \"fs-extra\";\nimport path from \"path\";\nimport type { I18nConfig } from \"../config/types.js\";\n\nexport class FileManager {\n private localesPath: string;\n private config: I18nConfig;\n\n constructor(config: I18nConfig) {\n this.config = config;\n this.localesPath = path.resolve(process.cwd(), config.localesPath);\n }\n\n getLocaleFilePath(locale: string): string {\n return path.join(this.localesPath, `${locale}.json`);\n }\n\n async ensureLocalesDirectory(): Promise<void> {\n await fs.ensureDir(this.localesPath);\n }\n\n async localeExists(locale: string): Promise<boolean> {\n const filePath = this.getLocaleFilePath(locale);\n return fs.pathExists(filePath);\n }\n\n async listLocales(): Promise<string[]> {\n return this.config.supportedLocales;\n }\n\n async readLocale(locale: string): Promise<Record<string, any>> {\n const filePath = this.getLocaleFilePath(locale);\n\n if (!(await fs.pathExists(filePath))) {\n throw new Error(`Locale file \"${locale}.json\" does not exist.`);\n }\n\n try {\n return await fs.readJson(filePath);\n } catch {\n throw new Error(`Invalid JSON in \"${locale}.json\".`);\n }\n }\n\n async writeLocale(\n locale: string,\n data: Record<string, any>,\n options?: { dryRun?: boolean }\n ): Promise<void> {\n const filePath = this.getLocaleFilePath(locale);\n\n const finalData = this.config.autoSort\n ? this.sortKeysRecursively(data)\n : data;\n\n if (options?.dryRun) {\n return;\n }\n\n await fs.writeJson(filePath, finalData, { spaces: 2 });\n }\n\n async deleteLocale(\n locale: string,\n options?: { dryRun?: boolean }\n ): Promise<void> {\n const filePath = this.getLocaleFilePath(locale);\n\n if (!(await fs.pathExists(filePath))) {\n throw new Error(`Locale \"${locale}\" does not exist.`);\n }\n\n if (options?.dryRun) {\n return;\n }\n\n await fs.remove(filePath);\n }\n\n async createLocale(\n locale: string,\n initialData: Record<string, any>,\n options?: { dryRun?: boolean }\n ): Promise<void> {\n await this.ensureLocalesDirectory();\n\n const filePath = this.getLocaleFilePath(locale);\n\n if (await fs.pathExists(filePath)) {\n throw new Error(`Locale \"${locale}\" already exists.`);\n }\n\n if (options?.dryRun) {\n return;\n }\n\n await fs.writeJson(filePath, initialData, { spaces: 2 });\n }\n\n private sortKeysRecursively(obj: any): any {\n if (Array.isArray(obj)) {\n return obj.map(item => this.sortKeysRecursively(item));\n }\n\n if (obj !== null && typeof obj === \"object\") {\n return Object.keys(obj)\n .sort()\n .reduce((acc: any, key) => {\n acc[key] = this.sortKeysRecursively(obj[key]);\n return acc;\n }, Object.create(null));\n }\n\n return obj;\n }\n \n}\n","import { loadConfig } from \"../config/config-loader.js\";\nimport { FileManager } from \"../core/file-manager.js\";\nimport type { CommandContext, GlobalOptions } from \"./types.js\";\n\nexport async function buildContext(\n options: GlobalOptions\n): Promise<CommandContext> {\n const config = await loadConfig();\n const fileManager = new FileManager(config);\n\n return {\n config,\n fileManager,\n options\n };\n}","import chalk from \"chalk\";\nimport fs from \"fs-extra\";\nimport inquirer from \"inquirer\";\nimport path from \"path\";\nimport { CONFIG_FILE_NAME, compileUsagePatterns } from \"../config/config-loader.js\";\nimport type { KeyStyle } from \"../config/types.js\";\nimport type { GlobalOptions } from \"../context/types.js\";\nimport { confirmAction } from \"../core/confirmation.js\";\n\ninterface InitConfigFile {\n localesPath: string;\n defaultLocale: string;\n supportedLocales: string[];\n keyStyle: KeyStyle;\n usagePatterns: string[];\n autoSort: boolean;\n}\n\nconst DEFAULT_USAGE_PATTERNS = [\n \"t\\\\(['\\\"](.*?)['\\\"]\\\\)\",\n \"translate\\\\(['\\\"](.*?)['\\\"]\\\\)\",\n \"i18n\\\\.t\\\\(['\\\"](.*?)['\\\"]\\\\)\"\n];\n\nexport async function initCommand(\n options: GlobalOptions\n): Promise<void> {\n const { yes, dryRun, ci, force } = options;\n const configPath = path.join(process.cwd(), CONFIG_FILE_NAME);\n const configExists = await fs.pathExists(configPath);\n\n if (configExists && !force) {\n throw new Error(\n `Configuration file \"${CONFIG_FILE_NAME}\" already exists. ` +\n `Use --force to overwrite.`\n );\n }\n\n const canPrompt = process.stdout.isTTY && !yes && !ci;\n\n let config: InitConfigFile;\n\n if (canPrompt) {\n const answers = await inquirer.prompt([\n {\n type: \"input\",\n name: \"localesPath\",\n message: \"Locales directory\",\n default: \"./locales\",\n validate: (input: string) =>\n input.trim().length > 0 || \"Please provide a locales path.\"\n },\n {\n type: \"input\",\n name: \"defaultLocale\",\n message: \"Default locale\",\n default: \"en\",\n validate: (input: string) =>\n input.trim().length >= 2 || \"Default locale must be at least 2 characters.\"\n },\n {\n type: \"input\",\n name: \"supportedLocales\",\n message: \"Supported locales (comma-separated)\",\n default: (answers: { defaultLocale: string }) =>\n answers.defaultLocale\n },\n {\n type: \"list\",\n name: \"keyStyle\",\n message: \"Key style\",\n choices: [\"nested\", \"flat\"],\n default: \"nested\"\n },\n {\n type: \"confirm\",\n name: \"autoSort\",\n message: \"Auto-sort keys?\",\n default: true\n },\n {\n type: \"confirm\",\n name: \"useDefaultUsagePatterns\",\n message: \"Use default usagePatterns?\",\n default: true\n }\n ]);\n\n let usagePatterns: string[] = DEFAULT_USAGE_PATTERNS;\n\n if (!answers.useDefaultUsagePatterns) {\n usagePatterns = [];\n let addMore = true;\n\n while (addMore) {\n const { pattern } = await inquirer.prompt([\n {\n type: \"input\",\n name: \"pattern\",\n message: \"Add usage pattern (regex)\",\n validate: (input: string) =>\n input.trim().length > 0 || \"Pattern cannot be empty.\"\n }\n ]);\n\n usagePatterns.push(pattern.trim());\n\n const { again } = await inquirer.prompt([\n {\n type: \"confirm\",\n name: \"again\",\n message: \"Add another pattern?\",\n default: false\n }\n ]);\n\n addMore = again;\n }\n }\n\n const supportedLocales = parseLocales(\n answers.supportedLocales\n );\n\n config = {\n localesPath: answers.localesPath.trim(),\n defaultLocale: answers.defaultLocale.trim(),\n supportedLocales,\n keyStyle: answers.keyStyle,\n usagePatterns,\n autoSort: answers.autoSort\n };\n } else {\n config = {\n localesPath: \"./locales\",\n defaultLocale: \"en\",\n supportedLocales: [\"en\"],\n keyStyle: \"nested\",\n usagePatterns: DEFAULT_USAGE_PATTERNS,\n autoSort: true\n };\n }\n\n config.supportedLocales = normalizeLocales(\n config.supportedLocales,\n config.defaultLocale\n );\n\n compileUsagePatterns(config.usagePatterns);\n\n if (ci && !yes) {\n const action = configExists ? \"overwritten\" : \"created\";\n throw new Error(\n `CI mode: configuration file would be ${action}. Re-run with --yes to apply.`\n );\n }\n\n if (configExists && !yes) {\n const confirmed = await confirmAction(\n `This will overwrite \"${CONFIG_FILE_NAME}\". Continue?`,\n { skip: false, ci: ci ?? false }\n );\n\n if (!confirmed) {\n console.log(chalk.red(\"\\nOperation cancelled.\"));\n return;\n }\n }\n\n if (dryRun) {\n console.log(chalk.yellow(\"\\n[DRY RUN] Configuration not written.\"));\n return;\n }\n\n await fs.writeJson(configPath, config, { spaces: 2 });\n\n await maybeInitLocales(config, { dryRun: false });\n\n console.log(\n chalk.green(`\\n✔ Created ${CONFIG_FILE_NAME} successfully.`)\n );\n}\n\nfunction parseLocales(input: string): string[] {\n return input\n .split(\",\")\n .map(locale => locale.trim())\n .filter(Boolean);\n}\n\nfunction normalizeLocales(\n locales: string[],\n defaultLocale: string\n): string[] {\n const unique = new Set<string>();\n\n for (const locale of locales) {\n if (locale.length > 0) {\n unique.add(locale);\n }\n }\n\n if (!unique.has(defaultLocale)) {\n unique.add(defaultLocale);\n }\n\n return Array.from(unique);\n}\n\nasync function maybeInitLocales(\n config: InitConfigFile,\n options: { dryRun: boolean }\n): Promise<void> {\n const localesPath = path.resolve(\n process.cwd(),\n config.localesPath\n );\n\n if (options.dryRun) {\n return;\n }\n\n await fs.ensureDir(localesPath);\n\n const defaultLocaleFile = path.join(\n localesPath,\n `${config.defaultLocale}.json`\n );\n\n if (await fs.pathExists(defaultLocaleFile)) {\n return;\n }\n\n await fs.writeJson(defaultLocaleFile, {}, { spaces: 2 });\n}\n","import inquirer from \"inquirer\";\n\ninterface ConfirmOptions {\n skip?: boolean; // used when --yes flag is passed\n defaultValue?: boolean;\n ci?: boolean;\n}\n\nexport async function confirmAction(\n message: string,\n options: ConfirmOptions = {}\n): Promise<boolean> {\n const { skip = false, defaultValue = false, ci = false } = options;\n\n // If --yes is passed, skip prompt\n if (skip) {\n return true;\n }\n\n // If running in CI mode, require explicit confirmation via --yes\n if (ci) {\n throw new Error(\n \"Confirmation required in CI mode. Re-run with --yes to proceed.\"\n );\n }\n\n // If running in non-interactive environment\n if (!process.stdout.isTTY) {\n return defaultValue;\n }\n\n const { confirmed } = await inquirer.prompt([\n {\n type: \"confirm\",\n name: \"confirmed\",\n message,\n default: defaultValue\n }\n ]);\n\n return confirmed;\n}\n","import chalk from \"chalk\";\nimport ISO6391 from \"iso-639-1\";\nimport type { CommandContext } from \"../context/types.js\";\nimport { confirmAction } from \"../core/confirmation.js\";\n\ninterface AddLangOptions {\n from?: string;\n strict?: boolean;\n}\n\nfunction isValidLocale(code: string): boolean {\n // Accept en or en-US format\n const parts = code.split(\"-\");\n\n if (parts.length === 1) {\n return ISO6391.validate(parts[0]!);\n }\n\n if (parts.length === 2) {\n return ISO6391.validate(parts[0]!);\n }\n\n return false;\n}\n\nexport async function addLang(\n lang: string,\n options: AddLangOptions,\n context: CommandContext\n): Promise<void> {\n const { config, fileManager } = context;\n const { yes, dryRun, ci } = context.options;\n\n const locale = lang.trim();\n\n if (!isValidLocale(locale)) {\n throw new Error(`Invalid language code: ${locale}`);\n }\n\n if (config.supportedLocales.includes(locale)) {\n throw new Error(`Language ${locale} already exists`);\n }\n\n const exists = await fileManager.localeExists(locale);\n if (exists) {\n throw new Error(`File already exists: ${locale}.json`);\n }\n\n let baseContent: Record<string, unknown> = {};\n\n // If clone from existing locale\n if (options.from) {\n const baseLocale = options.from;\n\n if (!config.supportedLocales.includes(baseLocale)) {\n throw new Error(`Base locale ${baseLocale} does not exist`);\n }\n\n baseContent = await fileManager.readLocale(baseLocale);\n }\n\n console.log(chalk.cyan(`\\nPreparing to add locale:`));\n console.log(chalk.yellow(` ${locale}\\n`));\n\n if (ci && !yes) {\n throw new Error(\n `CI mode: locale \"${locale}\" would be created. Re-run with --yes to apply.`\n );\n }\n\n const confirmed = await confirmAction(\n `This will create new locale \"${locale}\". Continue?`,\n { skip: yes ?? false, ci: ci ?? false }\n );\n\n if (!confirmed) {\n console.log(chalk.red(\"\\nOperation cancelled.\"));\n return;\n }\n\n await fileManager.createLocale(locale, baseContent, { dryRun: dryRun ?? false });\n\n if (dryRun) {\n console.log(\n chalk.yellow(\"\\n[DRY RUN] No files were modified.\")\n );\n } else {\n console.log(\n chalk.green(`\\n✔ Locale \"${locale}\" created successfully.`)\n );\n console.log(\n chalk.gray(\n `Note: Add \"${locale}\" to supportedLocales in config manually.`\n )\n );\n }\n}\n","import chalk from \"chalk\";\nimport type { CommandContext } from \"../context/types.js\";\nimport { confirmAction } from \"../core/confirmation.js\";\n\nexport async function removeLangCommand(\n context: CommandContext,\n lang: string\n): Promise<void> {\n const { config, fileManager, options } = context;\n const { yes, dryRun, ci } = options;\n\n const locale = lang.trim();\n\n // Validate locale exists\n if (!config.supportedLocales.includes(locale)) {\n throw new Error(\n `Locale \"${locale}\" is not in supportedLocales.`\n );\n }\n\n // Prevent removing default locale\n if (locale === config.defaultLocale) {\n throw new Error(\n `Cannot remove default locale \"${locale}\". ` +\n `Change defaultLocale first.`\n );\n }\n\n // Check if file exists\n const exists = await fileManager.localeExists(locale);\n if (!exists) {\n throw new Error(\n `Locale file \"${locale}.json\" does not exist.`\n );\n }\n\n console.log(chalk.cyan(`\\nPreparing to remove locale:`));\n console.log(chalk.yellow(` ${locale}\\n`));\n\n if (ci && !yes) {\n throw new Error(\n `CI mode: locale \"${locale}\" would be removed. Re-run with --yes to apply.`\n );\n }\n\n const confirmed = await confirmAction(\n `This will permanently delete \"${locale}.json\". Continue?`,\n { skip: yes ?? false, ci: ci ?? false }\n );\n\n if (!confirmed) {\n console.log(chalk.red(\"\\nOperation cancelled.\"));\n return;\n }\n\n // Delete the locale file\n await fileManager.deleteLocale(locale, { dryRun: dryRun ?? false });\n\n if (dryRun) {\n console.log(\n chalk.yellow(\"\\n[DRY RUN] No files were modified.\")\n );\n } else {\n console.log(\n chalk.green(`\\n✔ Locale \"${locale}\" removed successfully.`)\n );\n console.log(\n chalk.gray(\n `Note: Remove \"${locale}\" from supportedLocales in config manually.`\n )\n );\n }\n}\n","import chalk from \"chalk\";\nimport type { CommandContext } from \"../context/types.js\";\nimport { flattenObject, unflattenObject } from \"../core/object-utils.js\";\nimport { validateNoStructuralConflict } from \"../core/key-validator.js\";\nimport { confirmAction } from \"../core/confirmation.js\";\n\nexport async function addKeyCommand(\n context: CommandContext,\n key: string,\n options: { value: string }\n): Promise<void> {\n const { config, fileManager } = context;\n const { yes, dryRun, ci } = context.options;\n\n const value = options.value;\n\n if (!key || !value) {\n throw new Error(\"Both key and --value are required.\");\n }\n\n const locales = config.supportedLocales;\n\n console.log(chalk.cyan(`\\nPreparing to add key:`));\n console.log(chalk.yellow(` ${key}\\n`));\n\n const updatedLocales: string[] = [];\n\n for (const locale of locales) {\n const nested = await fileManager.readLocale(locale);\n const flat = flattenObject(nested);\n\n // Strict mode validation\n validateNoStructuralConflict(flat, key);\n\n if (flat[key] !== undefined) {\n throw new Error(\n `Key \"${key}\" already exists in locale \"${locale}\". Use update:key instead.`\n );\n }\n\n updatedLocales.push(locale);\n }\n\n console.log(chalk.white(\"This operation will update:\"));\n updatedLocales.forEach(l =>\n console.log(chalk.gray(` • ${l}.json`))\n );\n\n if (ci && !yes) {\n throw new Error(\n `CI mode: key \"${key}\" would be added to ${updatedLocales.length} locale(s). Re-run with --yes to apply.`\n );\n }\n\n const confirmed = await confirmAction(\n \"\\nDo you want to continue?\",\n { skip: yes ?? false, ci: ci ?? false }\n );\n\n if (!confirmed) {\n console.log(chalk.red(\"\\nOperation cancelled.\"));\n return;\n }\n\n for (const locale of locales) {\n const nested = await fileManager.readLocale(locale);\n const flat = flattenObject(nested);\n\n flat[key] = locale === config.defaultLocale ? value : \"\";\n\n const finalData =\n config.keyStyle === \"nested\"\n ? unflattenObject(flat)\n : flat;\n\n await fileManager.writeLocale(locale, finalData, { dryRun: dryRun ?? false });\n }\n\n if (dryRun) {\n console.log(\n chalk.yellow(\"\\n[DRY RUN] No files were modified.\")\n );\n } else {\n updatedLocales.forEach(l =>\n console.log(chalk.green(`✔ Updated ${l}.json`))\n );\n\n console.log(\n chalk.green(\"\\n✨ Key added successfully across all locales.\")\n );\n }\n}\n","export type FlatObject = Record<string, any>;\n\nconst DANGEROUS_KEY_SEGMENTS = new Set([\n \"__proto__\",\n \"constructor\",\n \"prototype\"\n]);\n\nfunction assertSafeKeySegment(segment: string): void {\n if (DANGEROUS_KEY_SEGMENTS.has(segment)) {\n throw new Error(\n `Unsafe key segment \"${segment}\" is not allowed.`\n );\n }\n}\n\nexport function flattenObject(\n obj: Record<string, any>,\n parentKey = \"\",\n result: FlatObject = Object.create(null)\n): FlatObject {\n for (const key of Object.keys(obj)) {\n assertSafeKeySegment(key);\n const value = obj[key];\n const newKey = parentKey ? `${parentKey}.${key}` : key;\n\n if (\n value &&\n typeof value === \"object\" &&\n !Array.isArray(value)\n ) {\n flattenObject(value, newKey, result);\n } else {\n result[newKey] = value;\n }\n }\n\n return result;\n}\n\nexport function unflattenObject(flatObj: FlatObject): Record<string, any> {\n const result: Record<string, any> = Object.create(null);\n\n for (const flatKey of Object.keys(flatObj)) {\n const keys = flatKey.split(\".\");\n let current = result;\n\n keys.forEach((key, index) => {\n assertSafeKeySegment(key);\n const isLast = index === keys.length - 1;\n\n if (isLast) {\n current[key] = flatObj[flatKey];\n } else {\n if (!current[key] || typeof current[key] !== \"object\") {\n current[key] = Object.create(null);\n }\n current = current[key];\n }\n });\n }\n\n return result;\n}\n\nexport function getAllFlatKeys(obj: Record<string, any>): string[] {\n return Object.keys(flattenObject(obj));\n}\n\nexport function removeEmptyObjects(obj: any): any {\n if (Array.isArray(obj)) {\n return obj;\n }\n\n if (obj !== null && typeof obj === \"object\") {\n const cleaned: any = Object.create(null);\n\n for (const key of Object.keys(obj)) {\n assertSafeKeySegment(key);\n const value = removeEmptyObjects(obj[key]);\n\n if (\n value !== undefined &&\n (typeof value !== \"object\" || Object.keys(value).length > 0)\n ) {\n cleaned[key] = value;\n }\n }\n\n return cleaned;\n }\n\n return obj;\n}\n","export function validateNoStructuralConflict(\n flatObject: Record<string, any>,\n newKey: string\n): void {\n const parts = newKey.split(\".\");\n\n // Parent conflict check\n for (let i = 1; i < parts.length; i++) {\n const parentPath = parts.slice(0, i).join(\".\");\n\n if (flatObject[parentPath] !== undefined) {\n throw new Error(\n `Structural conflict detected:\\n\\n` +\n `Cannot create key \"${newKey}\" because \"${parentPath}\" ` +\n `is already defined as a non-object value.\\n\\n` +\n `Resolve conflict before proceeding.`\n );\n }\n }\n\n // Child conflict check\n const prefix = `${newKey}.`;\n\n for (const existingKey of Object.keys(flatObject)) {\n if (existingKey.startsWith(prefix)) {\n throw new Error(\n `Structural conflict detected:\\n\\n` +\n `Cannot create key \"${newKey}\" because it would overwrite nested keys like \"${existingKey}\".\\n\\n` +\n `Resolve conflict before proceeding.`\n );\n }\n }\n}","import chalk from \"chalk\";\nimport type { CommandContext } from \"../context/types.js\";\nimport {\n flattenObject,\n unflattenObject\n} from \"../core/object-utils.js\";\nimport { validateNoStructuralConflict } from \"../core/key-validator.js\";\nimport { confirmAction } from \"../core/confirmation.js\";\n\ninterface UpdateKeyOptions {\n value: string;\n locale?: string;\n}\n\nexport async function updateKeyCommand(\n context: CommandContext,\n key: string,\n options: UpdateKeyOptions\n): Promise<void> {\n const { config, fileManager, options: globalOptions } = context;\n const { yes, dryRun, ci } = globalOptions;\n\n const { value, locale } = options;\n\n if (!key || value === undefined) {\n throw new Error(\"Both key and --value are required.\");\n }\n\n const targetLocale = locale ?? config.defaultLocale;\n\n if (!config.supportedLocales.includes(targetLocale)) {\n throw new Error(\n `Locale \"${targetLocale}\" is not defined in configuration.`\n );\n }\n\n console.log(chalk.cyan(`\\nPreparing to update key:`));\n console.log(chalk.yellow(` ${key}`));\n console.log(chalk.gray(` Locale: ${targetLocale}\\n`));\n\n const nested = await fileManager.readLocale(targetLocale);\n const flat = flattenObject(nested);\n\n // Strict structural validation\n validateNoStructuralConflict(flat, key);\n\n if (flat[key] === undefined) {\n throw new Error(\n `Key \"${key}\" does not exist in locale \"${targetLocale}\".`\n );\n }\n\n console.log(\n chalk.white(\n `Old value: ${chalk.gray(JSON.stringify(flat[key]))}`\n )\n );\n console.log(\n chalk.white(\n `New value: ${chalk.green(JSON.stringify(value))}`\n )\n );\n\n if (ci && !yes) {\n throw new Error(\n `CI mode: key \"${key}\" in \"${targetLocale}\" would be updated. Re-run with --yes to apply.`\n );\n }\n\n const confirmed = await confirmAction(\n \"\\nDo you want to continue?\",\n { skip: yes ?? false, ci: ci ?? false }\n );\n\n if (!confirmed) {\n console.log(chalk.red(\"\\nOperation cancelled.\"));\n return;\n }\n\n flat[key] = value;\n\n const rebuilt =\n config.keyStyle === \"nested\"\n ? unflattenObject(flat)\n : flat;\n\n await fileManager.writeLocale(targetLocale, rebuilt, {\n dryRun: dryRun ?? false\n });\n\n if (dryRun) {\n console.log(\n chalk.yellow(\"\\n[DRY RUN] No files were modified.\")\n );\n } else {\n console.log(\n chalk.green(\n `\\n✔ Successfully updated \"${key}\" in ${targetLocale}.json`\n )\n );\n }\n}\n","import chalk from \"chalk\";\nimport type { CommandContext } from \"../context/types.js\";\nimport {\n flattenObject,\n unflattenObject,\n removeEmptyObjects\n} from \"../core/object-utils.js\";\nimport { confirmAction } from \"../core/confirmation.js\";\n\nexport async function removeKeyCommand(\n context: CommandContext,\n key: string\n): Promise<void> {\n const { config, fileManager, options } = context;\n const { yes, dryRun, ci } = options;\n\n if (!key) {\n throw new Error(\"Key is required.\");\n }\n\n const locales = config.supportedLocales;\n\n console.log(chalk.cyan(`\\nPreparing to remove key:`));\n console.log(chalk.yellow(` ${key}\\n`));\n\n const localesContainingKey: string[] = [];\n\n // First pass: check existence\n for (const locale of locales) {\n const nested = await fileManager.readLocale(locale);\n const flat = flattenObject(nested);\n\n if (flat[key] !== undefined) {\n localesContainingKey.push(locale);\n }\n }\n\n if (localesContainingKey.length === 0) {\n throw new Error(\n `Key \"${key}\" does not exist in any locale.`\n );\n }\n\n console.log(chalk.white(\"This operation will update:\"));\n localesContainingKey.forEach(l =>\n console.log(chalk.gray(` • ${l}.json`))\n );\n\n if (ci && !yes) {\n throw new Error(\n `CI mode: key \"${key}\" would be removed from ${localesContainingKey.length} locale(s). Re-run with --yes to apply.`\n );\n }\n\n const confirmed = await confirmAction(\n \"\\nThis will remove the key from ALL locales. Continue?\",\n yes !== undefined ? { skip: yes, ci: ci ?? false } : { ci: ci ?? false }\n );\n\n if (!confirmed) {\n console.log(chalk.red(\"\\nOperation cancelled.\"));\n return;\n }\n\n // Second pass: remove\n for (const locale of locales) {\n const nested = await fileManager.readLocale(locale);\n const flat = flattenObject(nested);\n\n if (flat[key] !== undefined) {\n delete flat[key];\n }\n\n const rebuilt =\n config.keyStyle === \"nested\"\n ? removeEmptyObjects(unflattenObject(flat))\n : flat;\n\n await fileManager.writeLocale(locale, rebuilt, dryRun !== undefined ? { dryRun } : undefined);\n }\n\n if (dryRun) {\n console.log(\n chalk.yellow(\"\\n[DRY RUN] No files were modified.\")\n );\n } else {\n localesContainingKey.forEach(l =>\n console.log(chalk.green(`✔ Updated ${l}.json`))\n );\n\n console.log(\n chalk.green(\"\\n✨ Key removed successfully from all locales.\")\n );\n }\n}\n","import fs from \"fs-extra\";\nimport { glob } from \"glob\";\nimport chalk from \"chalk\";\nimport { flattenObject, unflattenObject } from \"../core/object-utils.js\";\nimport { confirmAction } from \"../core/confirmation.js\";\nimport type { CommandContext } from \"../context/types.js\";\n\nexport async function cleanUnusedCommand(\n context: CommandContext\n) {\n const { config, fileManager, options } = context;\n\n const { dryRun, yes, ci } = options;\n\n console.log(chalk.cyan(\"\\nScanning project for translation usage...\\n\"));\n\n const patterns = config.compiledUsagePatterns;\n\n if (!patterns || patterns.length === 0) {\n throw new Error(\n \"No usagePatterns defined in config.\"\n );\n }\n\n // Scan project files\n const files = await glob(\"src/**/*.{ts,tsx,js,jsx,html}\");\n\n const usedKeys = new Set<string>();\n\n for (const file of files) {\n const content = await fs.readFile(file, \"utf8\");\n\n for (const regex of patterns) {\n regex.lastIndex = 0;\n\n let match;\n\n while ((match = regex.exec(content))) {\n const key = match.groups?.key ?? match[1];\n\n if (key) {\n usedKeys.add(key);\n }\n }\n }\n }\n\n console.log(\n chalk.gray(`Found ${usedKeys.size} used keys in project\\n`)\n );\n\n // Read default locale\n const defaultLocale = config.defaultLocale;\n const nested = await fileManager.readLocale(defaultLocale);\n const flat = flattenObject(nested);\n\n const localeKeys = Object.keys(flat);\n\n const unusedKeys = localeKeys.filter(\n key => !usedKeys.has(key)\n );\n\n if (unusedKeys.length === 0) {\n console.log(\n chalk.green(\"✔ No unused translation keys found.\\n\")\n );\n return;\n }\n\n console.log(\n chalk.yellow(`Unused keys (${unusedKeys.length}):`)\n );\n\n unusedKeys.slice(0, 20).forEach(key =>\n console.log(` - ${key}`)\n );\n\n if (unusedKeys.length > 20) {\n console.log(\n chalk.gray(\n `... and ${unusedKeys.length - 20} more`\n )\n );\n }\n\n console.log(\"\");\n\n if (ci && !yes) {\n throw new Error(\n `CI mode: ${unusedKeys.length} unused key(s) would be removed. Re-run with --yes to apply.`\n );\n }\n\n const confirmed = await confirmAction(\n `This will remove ${unusedKeys.length} keys from ALL locales. Continue?`,\n { skip: yes ?? false, ci: ci ?? false }\n );\n\n if (!confirmed) {\n console.log(chalk.red(\"\\nOperation cancelled.\\n\"));\n return;\n }\n\n const locales = config.supportedLocales;\n\n for (const locale of locales) {\n const nestedLocale = await fileManager.readLocale(locale);\n const flatLocale = flattenObject(nestedLocale);\n\n for (const key of unusedKeys) {\n delete flatLocale[key];\n }\n\n const rebuilt =\n config.keyStyle === \"nested\"\n ? unflattenObject(flatLocale)\n : flatLocale;\n\n await fileManager.writeLocale(locale, rebuilt, {\n dryRun: dryRun ?? false\n });\n\n console.log(chalk.green(`✔ Updated ${locale}.json`));\n }\n\n if (dryRun) {\n console.log(\n chalk.yellow(\"\\n[DRY RUN] No files were modified.\\n\")\n );\n } else {\n console.log(\n chalk.green(\n `\\n✨ Removed ${unusedKeys.length} unused keys from all locales.\\n`\n )\n );\n }\n}\n"],"mappings":"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","names":["chalk","fs","path","fs","inquirer","path","path","fs","inquirer","answers","chalk","chalk","chalk","chalk","chalk","chalk","chalk","chalk","chalk","chalk","fs","chalk","chalk","fs","chalk"]}
1
+ {"version":3,"sources":["../src/bin/cli.ts","../src/config/config-loader.ts","../src/core/file-manager.ts","../src/context/build-context.ts","../src/commands/init.ts","../src/core/confirmation.ts","../src/commands/add-lang.ts","../src/commands/remove-lang.ts","../src/commands/add-key.ts","../src/core/object-utils.ts","../src/core/key-validator.ts","../src/commands/update-key.ts","../src/commands/remove-key.ts","../src/commands/clean-unused.ts","../src/commands/validate.ts","../src/providers/google.ts","../src/providers/openai.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport { Command } from \"commander\";\nimport chalk from \"chalk\";\nimport { buildContext } from \"../context/build-context.js\";\nimport { initCommand } from \"../commands/init.js\";\nimport { addLang } from \"../commands/add-lang.js\";\nimport { removeLangCommand } from \"../commands/remove-lang.js\";\nimport { addKeyCommand } from \"../commands/add-key.js\";\nimport { updateKeyCommand } from \"../commands/update-key.js\";\nimport { removeKeyCommand } from \"../commands/remove-key.js\";\nimport { cleanUnusedCommand } from \"../commands/clean-unused.js\";\nimport { validateCommand } from \"../commands/validate.js\";\nimport { GoogleTranslator } from \"../providers/google.js\";\nimport { OpenAITranslator } from \"../providers/openai.js\";\nimport type { Translator } from \"../providers/translator.js\";\n\nconst program = new Command();\n\nprogram\n .name(\"i18n-ai-cli\")\n .description(\"Professional CLI tool for managing translation files\")\n .version(\"1.0.0\");\n\n// Global options helper\nfunction withGlobalOptions(command: Command): Command {\n return command\n .option(\"-y, --yes\", \"Skip confirmation prompts\")\n .option(\"--dry-run\", \"Preview changes without writing files\")\n .option(\"--ci\", \"Run in CI mode (no prompts, exit on issues)\")\n .option(\"-f, --force\", \"Force operation even if validation fails\");\n}\n\n// Language Commands\nwithGlobalOptions(\n program\n .command(\"init\")\n .description(\"Create an i18n-cli configuration file\")\n .action(async (options) => {\n await initCommand(options);\n })\n);\n\nwithGlobalOptions(\n program\n .command(\"add:lang <lang>\")\n .option(\"--from <locale>\", \"Clone from existing locale\")\n .option(\"--strict\", \"Enable strict mode\")\n .description(\"Add new language locale\")\n .action(async (lang, options) => {\n const context = await buildContext(options);\n await addLang(lang, options, context);\n })\n);\n\nwithGlobalOptions(\n program\n .command(\"remove:lang\")\n .argument(\"<lang>\", \"Language code to remove\")\n .description(\"Remove a language translation file\")\n .action(async (lang, options) => {\n const context = await buildContext(options);\n await removeLangCommand(context, lang);\n })\n);\n\n//\n// Key Commands\n//\nwithGlobalOptions(\n program\n .command(\"add:key\")\n .argument(\"<key>\", \"Translation key (e.g., auth.login.title)\")\n .requiredOption(\"-v, --value <value>\", \"Value for default locale\")\n .description(\"Add new translation key to all locales\")\n .action(async (key, options) => {\n const context = await buildContext(options);\n await addKeyCommand(context, key, options);\n })\n);\n\nwithGlobalOptions(\n program\n .command(\"update:key\")\n .argument(\"<key>\", \"Translation key\")\n .requiredOption(\"-v, --value <value>\", \"New value\")\n .option(\"-l, --locale <locale>\", \"Specific locale to update\")\n .description(\"Update translation key\")\n .action(async (key, options) => {\n const context = await buildContext(options);\n await updateKeyCommand(context, key, options);\n })\n);\n\nwithGlobalOptions(\n program\n .command(\"remove:key\")\n .argument(\"<key>\", \"Translation key to remove\")\n .description(\"Remove translation key from all locales\")\n .action(async (key, options) => {\n const context = await buildContext(options);\n await removeKeyCommand(context, key);\n })\n);\n\n// Clean Command\nwithGlobalOptions(\n program\n .command(\"clean:unused\")\n .description(\"Remove unused translation keys from all locales\")\n .action(async (options) => {\n const context = await buildContext(options);\n await cleanUnusedCommand(context);\n })\n);\n\n// Validate Command\nwithGlobalOptions(\n program\n .command(\"validate\")\n .description(\"Validate & auto-correct existing translation files\")\n .option(\n \"-p, --provider <provider>\",\n \"Translation provider for missing keys (google, openai)\"\n )\n .action(async (options) => {\n const context = await buildContext(options);\n\n let translator: Translator | undefined;\n\n if (options.provider) {\n const provider = options.provider as string;\n\n if (provider === \"google\") {\n translator = new GoogleTranslator();\n } else if (provider === \"openai\") {\n translator = new OpenAITranslator();\n } else {\n throw new Error(\n `Unknown translation provider \"${provider}\". Use \"google\" or \"openai\".`\n );\n }\n } else if (process.env.OPENAI_API_KEY) {\n translator = new OpenAITranslator();\n } else {\n translator = new GoogleTranslator();\n }\n\n await validateCommand(context, { translator });\n })\n);\n\n// Global Error Handling\nprogram.exitOverride();\n\ntry {\n await program.parseAsync(process.argv);\n} catch (err: any) {\n console.error(chalk.red(\"❌ Error:\"), err.message);\n process.exitCode = 1;\n}\n","import fs from \"fs-extra\";\nimport path from \"path\";\nimport { z } from \"zod\";\nimport type { I18nConfig } from \"./types.js\";\n\nexport const CONFIG_FILE_NAME = \"i18n-cli.config.json\";\n\nconst ConfigSchema = z.object({\n localesPath: z.string().min(1),\n defaultLocale: z.string().min(2),\n supportedLocales: z.array(z.string().min(2)),\n keyStyle: z.enum([\"flat\", \"nested\"]).default(\"nested\"),\n usagePatterns: z.array(z.string()).default([]),\n autoSort: z.boolean().default(true)\n});\n\ntype ParsedConfig = z.infer<typeof ConfigSchema>;\n\nfunction resolveConfigPath(): string {\n const cwd = process.cwd();\n return path.join(cwd, CONFIG_FILE_NAME);\n}\n\nexport async function loadConfig(): Promise<I18nConfig> {\n const configPath = resolveConfigPath();\n\n if (!(await fs.pathExists(configPath))) {\n throw new Error(\n `Configuration file \"${CONFIG_FILE_NAME}\" not found in project root.\\n` +\n `Run \"i18n-cli init\" to create one.`\n );\n }\n\n let rawConfig: unknown;\n\n try {\n rawConfig = await fs.readJson(configPath);\n } catch (err) {\n throw new Error(\n `Failed to parse ${CONFIG_FILE_NAME}. Ensure it contains valid JSON.`\n );\n }\n\n const parsed = ConfigSchema.safeParse(rawConfig);\n\n if (!parsed.success) {\n const errors = parsed.error.issues\n .map(e => `• ${e.path.join(\".\")}: ${e.message}`)\n .join(\"\\n\");\n\n throw new Error(\n `Invalid configuration in ${CONFIG_FILE_NAME}:\\n${errors}`\n );\n }\n\n const config = parsed.data;\n\n validateConfigLogic(config);\n const compiledUsagePatterns = compileUsagePatterns(\n config.usagePatterns\n );\n\n return {\n ...config,\n compiledUsagePatterns\n };\n}\n\nfunction validateConfigLogic(config: ParsedConfig): void {\n if (!config.supportedLocales.includes(config.defaultLocale)) {\n throw new Error(\n `defaultLocale \"${config.defaultLocale}\" must be included in supportedLocales.`\n );\n }\n\n const duplicates = findDuplicates(config.supportedLocales);\n if (duplicates.length > 0) {\n throw new Error(\n `Duplicate locales found in supportedLocales: ${duplicates.join(\", \")}`\n );\n }\n}\n\nexport function compileUsagePatterns(patterns: string[]): RegExp[] {\n if (patterns.length === 0) {\n return [];\n }\n\n return patterns.map((pattern, index) => {\n let regex: RegExp;\n\n try {\n regex = new RegExp(pattern, \"g\");\n } catch (err) {\n throw new Error(\n `Invalid regex in usagePatterns[${index}]: ${String(err)}`\n );\n }\n\n const groupCount = countCapturingGroups(pattern);\n if (groupCount === 0) {\n throw new Error(\n `usagePatterns[${index}] must include a capturing group (use a named group like \"(?<key>...)\" or a standard \"(...)\").`\n );\n }\n\n return regex;\n });\n}\n\nfunction countCapturingGroups(pattern: string): number {\n let count = 0;\n let inCharClass = false;\n\n for (let i = 0; i < pattern.length; i++) {\n const char = pattern[i];\n\n if (char === \"\\\\\") {\n i += 1;\n continue;\n }\n\n if (char === \"[\") {\n inCharClass = true;\n continue;\n }\n\n if (char === \"]\" && inCharClass) {\n inCharClass = false;\n continue;\n }\n\n if (inCharClass) {\n continue;\n }\n\n if (char !== \"(\") {\n continue;\n }\n\n const next = pattern[i + 1];\n if (next !== \"?\") {\n count += 1;\n continue;\n }\n\n const next2 = pattern[i + 2];\n if (next2 !== \"<\") {\n continue;\n }\n\n const next3 = pattern[i + 3];\n if (next3 === \"=\" || next3 === \"!\") {\n continue;\n }\n\n count += 1;\n }\n\n return count;\n}\n\nfunction findDuplicates(arr: string[]): string[] {\n const seen = new Set<string>();\n const duplicates: string[] = [];\n\n for (const item of arr) {\n if (seen.has(item)) {\n duplicates.push(item);\n }\n seen.add(item);\n }\n\n return duplicates;\n}\n","import fs from \"fs-extra\";\nimport path from \"path\";\nimport type { I18nConfig } from \"../config/types.js\";\n\nexport class FileManager {\n private localesPath: string;\n private config: I18nConfig;\n\n constructor(config: I18nConfig) {\n this.config = config;\n this.localesPath = path.resolve(process.cwd(), config.localesPath);\n }\n\n getLocaleFilePath(locale: string): string {\n return path.join(this.localesPath, `${locale}.json`);\n }\n\n async ensureLocalesDirectory(): Promise<void> {\n await fs.ensureDir(this.localesPath);\n }\n\n async localeExists(locale: string): Promise<boolean> {\n const filePath = this.getLocaleFilePath(locale);\n return fs.pathExists(filePath);\n }\n\n async listLocales(): Promise<string[]> {\n return this.config.supportedLocales;\n }\n\n async readLocale(locale: string): Promise<Record<string, any>> {\n const filePath = this.getLocaleFilePath(locale);\n\n if (!(await fs.pathExists(filePath))) {\n throw new Error(`Locale file \"${locale}.json\" does not exist.`);\n }\n\n try {\n return await fs.readJson(filePath);\n } catch {\n throw new Error(`Invalid JSON in \"${locale}.json\".`);\n }\n }\n\n async writeLocale(\n locale: string,\n data: Record<string, any>,\n options?: { dryRun?: boolean }\n ): Promise<void> {\n const filePath = this.getLocaleFilePath(locale);\n\n const finalData = this.config.autoSort\n ? this.sortKeysRecursively(data)\n : data;\n\n if (options?.dryRun) {\n return;\n }\n\n await fs.writeJson(filePath, finalData, { spaces: 2 });\n }\n\n async deleteLocale(\n locale: string,\n options?: { dryRun?: boolean }\n ): Promise<void> {\n const filePath = this.getLocaleFilePath(locale);\n\n if (!(await fs.pathExists(filePath))) {\n throw new Error(`Locale \"${locale}\" does not exist.`);\n }\n\n if (options?.dryRun) {\n return;\n }\n\n await fs.remove(filePath);\n }\n\n async createLocale(\n locale: string,\n initialData: Record<string, any>,\n options?: { dryRun?: boolean }\n ): Promise<void> {\n await this.ensureLocalesDirectory();\n\n const filePath = this.getLocaleFilePath(locale);\n\n if (await fs.pathExists(filePath)) {\n throw new Error(`Locale \"${locale}\" already exists.`);\n }\n\n if (options?.dryRun) {\n return;\n }\n\n await fs.writeJson(filePath, initialData, { spaces: 2 });\n }\n\n private sortKeysRecursively(obj: any): any {\n if (Array.isArray(obj)) {\n return obj.map(item => this.sortKeysRecursively(item));\n }\n\n if (obj !== null && typeof obj === \"object\") {\n return Object.keys(obj)\n .sort()\n .reduce((acc: any, key) => {\n acc[key] = this.sortKeysRecursively(obj[key]);\n return acc;\n }, Object.create(null));\n }\n\n return obj;\n }\n \n}\n","import { loadConfig } from \"../config/config-loader.js\";\nimport { FileManager } from \"../core/file-manager.js\";\nimport type { CommandContext, GlobalOptions } from \"./types.js\";\n\nexport async function buildContext(\n options: GlobalOptions\n): Promise<CommandContext> {\n const config = await loadConfig();\n const fileManager = new FileManager(config);\n\n return {\n config,\n fileManager,\n options\n };\n}","import chalk from \"chalk\";\nimport fs from \"fs-extra\";\nimport inquirer from \"inquirer\";\nimport path from \"path\";\nimport { CONFIG_FILE_NAME, compileUsagePatterns } from \"../config/config-loader.js\";\nimport type { KeyStyle } from \"../config/types.js\";\nimport type { GlobalOptions } from \"../context/types.js\";\nimport { confirmAction } from \"../core/confirmation.js\";\n\ninterface InitConfigFile {\n localesPath: string;\n defaultLocale: string;\n supportedLocales: string[];\n keyStyle: KeyStyle;\n usagePatterns: string[];\n autoSort: boolean;\n}\n\nconst DEFAULT_USAGE_PATTERNS = [\n \"t\\\\(['\\\"](.*?)['\\\"]\\\\)\",\n \"translate\\\\(['\\\"](.*?)['\\\"]\\\\)\",\n \"i18n\\\\.t\\\\(['\\\"](.*?)['\\\"]\\\\)\"\n];\n\nexport async function initCommand(\n options: GlobalOptions\n): Promise<void> {\n const { yes, dryRun, ci, force } = options;\n const configPath = path.join(process.cwd(), CONFIG_FILE_NAME);\n const configExists = await fs.pathExists(configPath);\n\n if (configExists && !force) {\n throw new Error(\n `Configuration file \"${CONFIG_FILE_NAME}\" already exists. ` +\n `Use --force to overwrite.`\n );\n }\n\n const canPrompt = process.stdout.isTTY && !yes && !ci;\n\n let config: InitConfigFile;\n\n if (canPrompt) {\n const answers = await inquirer.prompt([\n {\n type: \"input\",\n name: \"localesPath\",\n message: \"Locales directory\",\n default: \"./locales\",\n validate: (input: string) =>\n input.trim().length > 0 || \"Please provide a locales path.\"\n },\n {\n type: \"input\",\n name: \"defaultLocale\",\n message: \"Default locale\",\n default: \"en\",\n validate: (input: string) =>\n input.trim().length >= 2 || \"Default locale must be at least 2 characters.\"\n },\n {\n type: \"input\",\n name: \"supportedLocales\",\n message: \"Supported locales (comma-separated)\",\n default: (answers: { defaultLocale: string }) =>\n answers.defaultLocale\n },\n {\n type: \"list\",\n name: \"keyStyle\",\n message: \"Key style\",\n choices: [\"nested\", \"flat\"],\n default: \"nested\"\n },\n {\n type: \"confirm\",\n name: \"autoSort\",\n message: \"Auto-sort keys?\",\n default: true\n },\n {\n type: \"confirm\",\n name: \"useDefaultUsagePatterns\",\n message: \"Use default usagePatterns?\",\n default: true\n }\n ]);\n\n let usagePatterns: string[] = DEFAULT_USAGE_PATTERNS;\n\n if (!answers.useDefaultUsagePatterns) {\n usagePatterns = [];\n let addMore = true;\n\n while (addMore) {\n const { pattern } = await inquirer.prompt([\n {\n type: \"input\",\n name: \"pattern\",\n message: \"Add usage pattern (regex)\",\n validate: (input: string) =>\n input.trim().length > 0 || \"Pattern cannot be empty.\"\n }\n ]);\n\n usagePatterns.push(pattern.trim());\n\n const { again } = await inquirer.prompt([\n {\n type: \"confirm\",\n name: \"again\",\n message: \"Add another pattern?\",\n default: false\n }\n ]);\n\n addMore = again;\n }\n }\n\n const supportedLocales = parseLocales(\n answers.supportedLocales\n );\n\n config = {\n localesPath: answers.localesPath.trim(),\n defaultLocale: answers.defaultLocale.trim(),\n supportedLocales,\n keyStyle: answers.keyStyle,\n usagePatterns,\n autoSort: answers.autoSort\n };\n } else {\n config = {\n localesPath: \"./locales\",\n defaultLocale: \"en\",\n supportedLocales: [\"en\"],\n keyStyle: \"nested\",\n usagePatterns: DEFAULT_USAGE_PATTERNS,\n autoSort: true\n };\n }\n\n config.supportedLocales = normalizeLocales(\n config.supportedLocales,\n config.defaultLocale\n );\n\n compileUsagePatterns(config.usagePatterns);\n\n if (ci && !yes) {\n const action = configExists ? \"overwritten\" : \"created\";\n throw new Error(\n `CI mode: configuration file would be ${action}. Re-run with --yes to apply.`\n );\n }\n\n if (configExists && !yes) {\n const confirmed = await confirmAction(\n `This will overwrite \"${CONFIG_FILE_NAME}\". Continue?`,\n { skip: false, ci: ci ?? false }\n );\n\n if (!confirmed) {\n console.log(chalk.red(\"\\nOperation cancelled.\"));\n return;\n }\n }\n\n if (dryRun) {\n console.log(chalk.yellow(\"\\n[DRY RUN] Configuration not written.\"));\n return;\n }\n\n await fs.writeJson(configPath, config, { spaces: 2 });\n\n await maybeInitLocales(config, { dryRun: false });\n\n console.log(\n chalk.green(`\\n✔ Created ${CONFIG_FILE_NAME} successfully.`)\n );\n}\n\nfunction parseLocales(input: string): string[] {\n return input\n .split(\",\")\n .map(locale => locale.trim())\n .filter(Boolean);\n}\n\nfunction normalizeLocales(\n locales: string[],\n defaultLocale: string\n): string[] {\n const unique = new Set<string>();\n\n for (const locale of locales) {\n if (locale.length > 0) {\n unique.add(locale);\n }\n }\n\n if (!unique.has(defaultLocale)) {\n unique.add(defaultLocale);\n }\n\n return Array.from(unique);\n}\n\nasync function maybeInitLocales(\n config: InitConfigFile,\n options: { dryRun: boolean }\n): Promise<void> {\n const localesPath = path.resolve(\n process.cwd(),\n config.localesPath\n );\n\n if (options.dryRun) {\n return;\n }\n\n await fs.ensureDir(localesPath);\n\n // Strip .json extension if present to avoid double extension\n const defaultLocale = config.defaultLocale.replace(/\\.json$/i, '');\n\n const defaultLocaleFile = path.join(\n localesPath,\n `${defaultLocale}.json`\n );\n\n if (await fs.pathExists(defaultLocaleFile)) {\n return;\n }\n\n await fs.writeJson(defaultLocaleFile, {}, { spaces: 2 });\n}\n","import inquirer from \"inquirer\";\n\ninterface ConfirmOptions {\n skip?: boolean; // used when --yes flag is passed\n defaultValue?: boolean;\n ci?: boolean;\n}\n\nexport async function confirmAction(\n message: string,\n options: ConfirmOptions = {}\n): Promise<boolean> {\n const { skip = false, defaultValue = false, ci = false } = options;\n\n // If --yes is passed, skip prompt\n if (skip) {\n return true;\n }\n\n // If running in CI mode, require explicit confirmation via --yes\n if (ci) {\n throw new Error(\n \"Confirmation required in CI mode. Re-run with --yes to proceed.\"\n );\n }\n\n // If running in non-interactive environment\n if (!process.stdout.isTTY) {\n return defaultValue;\n }\n\n const { confirmed } = await inquirer.prompt([\n {\n type: \"confirm\",\n name: \"confirmed\",\n message,\n default: defaultValue\n }\n ]);\n\n return confirmed;\n}\n","import chalk from \"chalk\";\nimport ISO6391 from \"iso-639-1\";\nimport type { CommandContext } from \"../context/types.js\";\nimport { confirmAction } from \"../core/confirmation.js\";\n\ninterface AddLangOptions {\n from?: string;\n strict?: boolean;\n}\n\nfunction isValidLocale(code: string): boolean {\n // Accept en or en-US format\n const parts = code.split(\"-\");\n\n if (parts.length === 1) {\n return ISO6391.validate(parts[0]!);\n }\n\n if (parts.length === 2) {\n return ISO6391.validate(parts[0]!);\n }\n\n return false;\n}\n\nexport async function addLang(\n lang: string,\n options: AddLangOptions,\n context: CommandContext\n): Promise<void> {\n const { config, fileManager } = context;\n const { yes, dryRun, ci } = context.options;\n\n const locale = lang.trim();\n\n if (!isValidLocale(locale)) {\n throw new Error(`Invalid language code: ${locale}`);\n }\n\n if (config.supportedLocales.includes(locale)) {\n throw new Error(`Language ${locale} already exists`);\n }\n\n const exists = await fileManager.localeExists(locale);\n if (exists) {\n throw new Error(`File already exists: ${locale}.json`);\n }\n\n let baseContent: Record<string, unknown> = {};\n\n // If clone from existing locale\n if (options.from) {\n const baseLocale = options.from;\n\n if (!config.supportedLocales.includes(baseLocale)) {\n throw new Error(`Base locale ${baseLocale} does not exist`);\n }\n\n baseContent = await fileManager.readLocale(baseLocale);\n }\n\n console.log(chalk.cyan(`\\nPreparing to add locale:`));\n console.log(chalk.yellow(` ${locale}\\n`));\n\n if (ci && !yes) {\n throw new Error(\n `CI mode: locale \"${locale}\" would be created. Re-run with --yes to apply.`\n );\n }\n\n const confirmed = await confirmAction(\n `This will create new locale \"${locale}\". Continue?`,\n { skip: yes ?? false, ci: ci ?? false }\n );\n\n if (!confirmed) {\n console.log(chalk.red(\"\\nOperation cancelled.\"));\n return;\n }\n\n await fileManager.createLocale(locale, baseContent, { dryRun: dryRun ?? false });\n\n if (dryRun) {\n console.log(\n chalk.yellow(\"\\n[DRY RUN] No files were modified.\")\n );\n } else {\n console.log(\n chalk.green(`\\n✔ Locale \"${locale}\" created successfully.`)\n );\n console.log(\n chalk.gray(\n `Note: Add \"${locale}\" to supportedLocales in config manually.`\n )\n );\n }\n}\n","import chalk from \"chalk\";\nimport type { CommandContext } from \"../context/types.js\";\nimport { confirmAction } from \"../core/confirmation.js\";\n\nexport async function removeLangCommand(\n context: CommandContext,\n lang: string\n): Promise<void> {\n const { config, fileManager, options } = context;\n const { yes, dryRun, ci } = options;\n\n const locale = lang.trim();\n\n // Validate locale exists\n if (!config.supportedLocales.includes(locale)) {\n throw new Error(\n `Locale \"${locale}\" is not in supportedLocales.`\n );\n }\n\n // Prevent removing default locale\n if (locale === config.defaultLocale) {\n throw new Error(\n `Cannot remove default locale \"${locale}\". ` +\n `Change defaultLocale first.`\n );\n }\n\n // Check if file exists\n const exists = await fileManager.localeExists(locale);\n if (!exists) {\n throw new Error(\n `Locale file \"${locale}.json\" does not exist.`\n );\n }\n\n console.log(chalk.cyan(`\\nPreparing to remove locale:`));\n console.log(chalk.yellow(` ${locale}\\n`));\n\n if (ci && !yes) {\n throw new Error(\n `CI mode: locale \"${locale}\" would be removed. Re-run with --yes to apply.`\n );\n }\n\n const confirmed = await confirmAction(\n `This will permanently delete \"${locale}.json\". Continue?`,\n { skip: yes ?? false, ci: ci ?? false }\n );\n\n if (!confirmed) {\n console.log(chalk.red(\"\\nOperation cancelled.\"));\n return;\n }\n\n // Delete the locale file\n await fileManager.deleteLocale(locale, { dryRun: dryRun ?? false });\n\n if (dryRun) {\n console.log(\n chalk.yellow(\"\\n[DRY RUN] No files were modified.\")\n );\n } else {\n console.log(\n chalk.green(`\\n✔ Locale \"${locale}\" removed successfully.`)\n );\n console.log(\n chalk.gray(\n `Note: Remove \"${locale}\" from supportedLocales in config manually.`\n )\n );\n }\n}\n","import chalk from \"chalk\";\nimport type { CommandContext } from \"../context/types.js\";\nimport { flattenObject, unflattenObject } from \"../core/object-utils.js\";\nimport { validateNoStructuralConflict } from \"../core/key-validator.js\";\nimport { confirmAction } from \"../core/confirmation.js\";\n\nexport async function addKeyCommand(\n context: CommandContext,\n key: string,\n options: { value: string }\n): Promise<void> {\n const { config, fileManager } = context;\n const { yes, dryRun, ci } = context.options;\n\n const value = options.value;\n\n if (!key || !value) {\n throw new Error(\"Both key and --value are required.\");\n }\n\n const locales = config.supportedLocales;\n\n console.log(chalk.cyan(`\\nPreparing to add key:`));\n console.log(chalk.yellow(` ${key}\\n`));\n\n const updatedLocales: string[] = [];\n\n for (const locale of locales) {\n const nested = await fileManager.readLocale(locale);\n const flat = flattenObject(nested);\n\n // Strict mode validation\n validateNoStructuralConflict(flat, key);\n\n if (flat[key] !== undefined) {\n throw new Error(\n `Key \"${key}\" already exists in locale \"${locale}\". Use update:key instead.`\n );\n }\n\n updatedLocales.push(locale);\n }\n\n console.log(chalk.white(\"This operation will update:\"));\n updatedLocales.forEach(l =>\n console.log(chalk.gray(` • ${l}.json`))\n );\n\n if (ci && !yes) {\n throw new Error(\n `CI mode: key \"${key}\" would be added to ${updatedLocales.length} locale(s). Re-run with --yes to apply.`\n );\n }\n\n const confirmed = await confirmAction(\n \"\\nDo you want to continue?\",\n { skip: yes ?? false, ci: ci ?? false }\n );\n\n if (!confirmed) {\n console.log(chalk.red(\"\\nOperation cancelled.\"));\n return;\n }\n\n for (const locale of locales) {\n const nested = await fileManager.readLocale(locale);\n const flat = flattenObject(nested);\n\n flat[key] = locale === config.defaultLocale ? value : \"\";\n\n const finalData =\n config.keyStyle === \"nested\"\n ? unflattenObject(flat)\n : flat;\n\n await fileManager.writeLocale(locale, finalData, { dryRun: dryRun ?? false });\n }\n\n if (dryRun) {\n console.log(\n chalk.yellow(\"\\n[DRY RUN] No files were modified.\")\n );\n } else {\n updatedLocales.forEach(l =>\n console.log(chalk.green(`✔ Updated ${l}.json`))\n );\n\n console.log(\n chalk.green(\"\\n✨ Key added successfully across all locales.\")\n );\n }\n}\n","export type FlatObject = Record<string, any>;\n\nconst DANGEROUS_KEY_SEGMENTS = new Set([\n \"__proto__\",\n \"constructor\",\n \"prototype\"\n]);\n\nfunction assertSafeKeySegment(segment: string): void {\n if (DANGEROUS_KEY_SEGMENTS.has(segment)) {\n throw new Error(\n `Unsafe key segment \"${segment}\" is not allowed.`\n );\n }\n}\n\nexport function flattenObject(\n obj: Record<string, any>,\n parentKey = \"\",\n result: FlatObject = Object.create(null)\n): FlatObject {\n for (const key of Object.keys(obj)) {\n assertSafeKeySegment(key);\n const value = obj[key];\n const newKey = parentKey ? `${parentKey}.${key}` : key;\n\n if (\n value &&\n typeof value === \"object\" &&\n !Array.isArray(value)\n ) {\n flattenObject(value, newKey, result);\n } else {\n result[newKey] = value;\n }\n }\n\n return result;\n}\n\nexport function unflattenObject(flatObj: FlatObject): Record<string, any> {\n const result: Record<string, any> = Object.create(null);\n\n for (const flatKey of Object.keys(flatObj)) {\n const keys = flatKey.split(\".\");\n let current = result;\n\n keys.forEach((key, index) => {\n assertSafeKeySegment(key);\n const isLast = index === keys.length - 1;\n\n if (isLast) {\n current[key] = flatObj[flatKey];\n } else {\n if (!current[key] || typeof current[key] !== \"object\") {\n current[key] = Object.create(null);\n }\n current = current[key];\n }\n });\n }\n\n return result;\n}\n\nexport function getAllFlatKeys(obj: Record<string, any>): string[] {\n return Object.keys(flattenObject(obj));\n}\n\nexport function removeEmptyObjects(obj: any): any {\n if (Array.isArray(obj)) {\n return obj;\n }\n\n if (obj !== null && typeof obj === \"object\") {\n const cleaned: any = Object.create(null);\n\n for (const key of Object.keys(obj)) {\n assertSafeKeySegment(key);\n const value = removeEmptyObjects(obj[key]);\n\n if (\n value !== undefined &&\n (typeof value !== \"object\" || Object.keys(value).length > 0)\n ) {\n cleaned[key] = value;\n }\n }\n\n return cleaned;\n }\n\n return obj;\n}\n","export function validateNoStructuralConflict(\n flatObject: Record<string, any>,\n newKey: string\n): void {\n const parts = newKey.split(\".\");\n\n // Parent conflict check\n for (let i = 1; i < parts.length; i++) {\n const parentPath = parts.slice(0, i).join(\".\");\n\n if (flatObject[parentPath] !== undefined) {\n throw new Error(\n `Structural conflict detected:\\n\\n` +\n `Cannot create key \"${newKey}\" because \"${parentPath}\" ` +\n `is already defined as a non-object value.\\n\\n` +\n `Resolve conflict before proceeding.`\n );\n }\n }\n\n // Child conflict check\n const prefix = `${newKey}.`;\n\n for (const existingKey of Object.keys(flatObject)) {\n if (existingKey.startsWith(prefix)) {\n throw new Error(\n `Structural conflict detected:\\n\\n` +\n `Cannot create key \"${newKey}\" because it would overwrite nested keys like \"${existingKey}\".\\n\\n` +\n `Resolve conflict before proceeding.`\n );\n }\n }\n}","import chalk from \"chalk\";\nimport type { CommandContext } from \"../context/types.js\";\nimport {\n flattenObject,\n unflattenObject\n} from \"../core/object-utils.js\";\nimport { validateNoStructuralConflict } from \"../core/key-validator.js\";\nimport { confirmAction } from \"../core/confirmation.js\";\n\ninterface UpdateKeyOptions {\n value: string;\n locale?: string;\n}\n\nexport async function updateKeyCommand(\n context: CommandContext,\n key: string,\n options: UpdateKeyOptions\n): Promise<void> {\n const { config, fileManager, options: globalOptions } = context;\n const { yes, dryRun, ci } = globalOptions;\n\n const { value, locale } = options;\n\n if (!key || value === undefined) {\n throw new Error(\"Both key and --value are required.\");\n }\n\n const targetLocale = locale ?? config.defaultLocale;\n\n if (!config.supportedLocales.includes(targetLocale)) {\n throw new Error(\n `Locale \"${targetLocale}\" is not defined in configuration.`\n );\n }\n\n console.log(chalk.cyan(`\\nPreparing to update key:`));\n console.log(chalk.yellow(` ${key}`));\n console.log(chalk.gray(` Locale: ${targetLocale}\\n`));\n\n const nested = await fileManager.readLocale(targetLocale);\n const flat = flattenObject(nested);\n\n // Strict structural validation\n validateNoStructuralConflict(flat, key);\n\n if (flat[key] === undefined) {\n throw new Error(\n `Key \"${key}\" does not exist in locale \"${targetLocale}\".`\n );\n }\n\n console.log(\n chalk.white(\n `Old value: ${chalk.gray(JSON.stringify(flat[key]))}`\n )\n );\n console.log(\n chalk.white(\n `New value: ${chalk.green(JSON.stringify(value))}`\n )\n );\n\n if (ci && !yes) {\n throw new Error(\n `CI mode: key \"${key}\" in \"${targetLocale}\" would be updated. Re-run with --yes to apply.`\n );\n }\n\n const confirmed = await confirmAction(\n \"\\nDo you want to continue?\",\n { skip: yes ?? false, ci: ci ?? false }\n );\n\n if (!confirmed) {\n console.log(chalk.red(\"\\nOperation cancelled.\"));\n return;\n }\n\n flat[key] = value;\n\n const rebuilt =\n config.keyStyle === \"nested\"\n ? unflattenObject(flat)\n : flat;\n\n await fileManager.writeLocale(targetLocale, rebuilt, {\n dryRun: dryRun ?? false\n });\n\n if (dryRun) {\n console.log(\n chalk.yellow(\"\\n[DRY RUN] No files were modified.\")\n );\n } else {\n console.log(\n chalk.green(\n `\\n✔ Successfully updated \"${key}\" in ${targetLocale}.json`\n )\n );\n }\n}\n","import chalk from \"chalk\";\nimport type { CommandContext } from \"../context/types.js\";\nimport {\n flattenObject,\n unflattenObject,\n removeEmptyObjects\n} from \"../core/object-utils.js\";\nimport { confirmAction } from \"../core/confirmation.js\";\n\nexport async function removeKeyCommand(\n context: CommandContext,\n key: string\n): Promise<void> {\n const { config, fileManager, options } = context;\n const { yes, dryRun, ci } = options;\n\n if (!key) {\n throw new Error(\"Key is required.\");\n }\n\n const locales = config.supportedLocales;\n\n console.log(chalk.cyan(`\\nPreparing to remove key:`));\n console.log(chalk.yellow(` ${key}\\n`));\n\n const localesContainingKey: string[] = [];\n\n // First pass: check existence\n for (const locale of locales) {\n const nested = await fileManager.readLocale(locale);\n const flat = flattenObject(nested);\n\n if (flat[key] !== undefined) {\n localesContainingKey.push(locale);\n }\n }\n\n if (localesContainingKey.length === 0) {\n throw new Error(\n `Key \"${key}\" does not exist in any locale.`\n );\n }\n\n console.log(chalk.white(\"This operation will update:\"));\n localesContainingKey.forEach(l =>\n console.log(chalk.gray(` • ${l}.json`))\n );\n\n if (ci && !yes) {\n throw new Error(\n `CI mode: key \"${key}\" would be removed from ${localesContainingKey.length} locale(s). Re-run with --yes to apply.`\n );\n }\n\n const confirmed = await confirmAction(\n \"\\nThis will remove the key from ALL locales. Continue?\",\n yes !== undefined ? { skip: yes, ci: ci ?? false } : { ci: ci ?? false }\n );\n\n if (!confirmed) {\n console.log(chalk.red(\"\\nOperation cancelled.\"));\n return;\n }\n\n // Second pass: remove\n for (const locale of locales) {\n const nested = await fileManager.readLocale(locale);\n const flat = flattenObject(nested);\n\n if (flat[key] !== undefined) {\n delete flat[key];\n }\n\n const rebuilt =\n config.keyStyle === \"nested\"\n ? removeEmptyObjects(unflattenObject(flat))\n : flat;\n\n await fileManager.writeLocale(locale, rebuilt, dryRun !== undefined ? { dryRun } : undefined);\n }\n\n if (dryRun) {\n console.log(\n chalk.yellow(\"\\n[DRY RUN] No files were modified.\")\n );\n } else {\n localesContainingKey.forEach(l =>\n console.log(chalk.green(`✔ Updated ${l}.json`))\n );\n\n console.log(\n chalk.green(\"\\n✨ Key removed successfully from all locales.\")\n );\n }\n}\n","import fs from \"fs-extra\";\nimport { glob } from \"glob\";\nimport chalk from \"chalk\";\nimport { flattenObject, unflattenObject } from \"../core/object-utils.js\";\nimport { confirmAction } from \"../core/confirmation.js\";\nimport type { CommandContext } from \"../context/types.js\";\n\nexport async function cleanUnusedCommand(\n context: CommandContext\n) {\n const { config, fileManager, options } = context;\n\n const { dryRun, yes, ci } = options;\n\n console.log(chalk.cyan(\"\\nScanning project for translation usage...\\n\"));\n\n const patterns = config.compiledUsagePatterns;\n\n if (!patterns || patterns.length === 0) {\n throw new Error(\n \"No usagePatterns defined in config.\"\n );\n }\n\n // Scan project files\n const files = await glob(\"src/**/*.{ts,tsx,js,jsx,html}\");\n\n const usedKeys = new Set<string>();\n\n for (const file of files) {\n const content = await fs.readFile(file, \"utf8\");\n\n for (const regex of patterns) {\n regex.lastIndex = 0;\n\n let match;\n\n while ((match = regex.exec(content))) {\n const key = match.groups?.key ?? match[1];\n\n if (key) {\n usedKeys.add(key);\n }\n }\n }\n }\n\n console.log(\n chalk.gray(`Found ${usedKeys.size} used keys in project\\n`)\n );\n\n // Read default locale\n const defaultLocale = config.defaultLocale;\n const nested = await fileManager.readLocale(defaultLocale);\n const flat = flattenObject(nested);\n\n const localeKeys = Object.keys(flat);\n\n const unusedKeys = localeKeys.filter(\n key => !usedKeys.has(key)\n );\n\n if (unusedKeys.length === 0) {\n console.log(\n chalk.green(\"✔ No unused translation keys found.\\n\")\n );\n return;\n }\n\n console.log(\n chalk.yellow(`Unused keys (${unusedKeys.length}):`)\n );\n\n unusedKeys.slice(0, 20).forEach(key =>\n console.log(` - ${key}`)\n );\n\n if (unusedKeys.length > 20) {\n console.log(\n chalk.gray(\n `... and ${unusedKeys.length - 20} more`\n )\n );\n }\n\n console.log(\"\");\n\n if (ci && !yes) {\n throw new Error(\n `CI mode: ${unusedKeys.length} unused key(s) would be removed. Re-run with --yes to apply.`\n );\n }\n\n const confirmed = await confirmAction(\n `This will remove ${unusedKeys.length} keys from ALL locales. Continue?`,\n { skip: yes ?? false, ci: ci ?? false }\n );\n\n if (!confirmed) {\n console.log(chalk.red(\"\\nOperation cancelled.\\n\"));\n return;\n }\n\n const locales = config.supportedLocales;\n\n for (const locale of locales) {\n const nestedLocale = await fileManager.readLocale(locale);\n const flatLocale = flattenObject(nestedLocale);\n\n for (const key of unusedKeys) {\n delete flatLocale[key];\n }\n\n const rebuilt =\n config.keyStyle === \"nested\"\n ? unflattenObject(flatLocale)\n : flatLocale;\n\n await fileManager.writeLocale(locale, rebuilt, {\n dryRun: dryRun ?? false\n });\n\n console.log(chalk.green(`✔ Updated ${locale}.json`));\n }\n\n if (dryRun) {\n console.log(\n chalk.yellow(\"\\n[DRY RUN] No files were modified.\\n\")\n );\n } else {\n console.log(\n chalk.green(\n `\\n✨ Removed ${unusedKeys.length} unused keys from all locales.\\n`\n )\n );\n }\n}\n","import chalk from \"chalk\";\nimport { flattenObject, unflattenObject } from \"../core/object-utils.js\";\nimport { confirmAction } from \"../core/confirmation.js\";\nimport type { CommandContext } from \"../context/types.js\";\nimport type {\n Translator,\n ValidateOptions,\n ValidationReport,\n} from \"../providers/translator.js\";\n\nfunction detectTypeMismatches(\n referenceFlat: Record<string, unknown>,\n localeFlat: Record<string, unknown>\n): { key: string; expected: string; actual: string }[] {\n const mismatches: { key: string; expected: string; actual: string }[] = [];\n\n for (const key of Object.keys(referenceFlat)) {\n if (!(key in localeFlat)) continue;\n\n const refType = typeof referenceFlat[key];\n const locType = typeof localeFlat[key];\n\n if (refType !== locType) {\n mismatches.push({ key, expected: refType, actual: locType });\n }\n }\n\n return mismatches;\n}\n\nfunction printReport(reports: ValidationReport[]): void {\n let totalIssues = 0;\n\n for (const { locale, issues } of reports) {\n const issueCount =\n issues.missingKeys.length +\n issues.extraKeys.length +\n issues.typeMismatches.length;\n\n if (issueCount === 0) {\n console.log(chalk.green(` ✔ ${locale}.json — no issues`));\n continue;\n }\n\n totalIssues += issueCount;\n console.log(chalk.yellow(` ✘ ${locale}.json — ${issueCount} issue(s)`));\n\n if (issues.missingKeys.length > 0) {\n console.log(chalk.red(` Missing keys (${issues.missingKeys.length}):`));\n for (const key of issues.missingKeys.slice(0, 10)) {\n console.log(` - ${key}`);\n }\n if (issues.missingKeys.length > 10) {\n console.log(\n chalk.gray(` ... and ${issues.missingKeys.length - 10} more`)\n );\n }\n }\n\n if (issues.extraKeys.length > 0) {\n console.log(chalk.red(` Extra keys (${issues.extraKeys.length}):`));\n for (const key of issues.extraKeys.slice(0, 10)) {\n console.log(` - ${key}`);\n }\n if (issues.extraKeys.length > 10) {\n console.log(\n chalk.gray(` ... and ${issues.extraKeys.length - 10} more`)\n );\n }\n }\n\n if (issues.typeMismatches.length > 0) {\n console.log(\n chalk.red(` Type mismatches (${issues.typeMismatches.length}):`)\n );\n for (const m of issues.typeMismatches.slice(0, 10)) {\n console.log(\n ` - ${m.key}: expected ${m.expected}, got ${m.actual}`\n );\n }\n if (issues.typeMismatches.length > 10) {\n console.log(\n chalk.gray(\n ` ... and ${issues.typeMismatches.length - 10} more`\n )\n );\n }\n }\n }\n\n console.log(\"\");\n\n if (totalIssues === 0) {\n console.log(chalk.green(\"✔ All translation files are valid.\\n\"));\n } else {\n console.log(\n chalk.yellow(`Found ${totalIssues} issue(s) across locale files.\\n`)\n );\n }\n}\n\nasync function translateKey(\n translator: Translator,\n sourceText: string,\n targetLocale: string,\n sourceLocale: string\n): Promise<string> {\n if (typeof sourceText !== \"string\" || sourceText === \"\") {\n return \"\";\n }\n\n const result = await translator.translate({\n text: sourceText,\n targetLocale,\n sourceLocale,\n });\n\n return result.text;\n}\n\nexport async function validateCommand(\n context: CommandContext,\n validateOptions: ValidateOptions = {}\n): Promise<void> {\n const { config, fileManager, options } = context;\n const { dryRun, yes, ci } = options;\n const { translator } = validateOptions;\n\n console.log(chalk.cyan(\"\\nValidating translation files...\\n\"));\n\n const defaultLocale = config.defaultLocale;\n const referenceData = await fileManager.readLocale(defaultLocale);\n const referenceFlat = flattenObject(referenceData);\n const referenceKeys = new Set(Object.keys(referenceFlat));\n\n const otherLocales = config.supportedLocales.filter(\n (l) => l !== defaultLocale\n );\n\n // Phase 1: Collect issues\n const reports: ValidationReport[] = [];\n\n for (const locale of otherLocales) {\n const localeData = await fileManager.readLocale(locale);\n const localeFlat = flattenObject(localeData);\n const localeKeys = new Set(Object.keys(localeFlat));\n\n const missingKeys = [...referenceKeys].filter((k) => !localeKeys.has(k));\n const extraKeys = [...localeKeys].filter((k) => !referenceKeys.has(k));\n const typeMismatches = detectTypeMismatches(referenceFlat, localeFlat);\n\n reports.push({\n locale,\n issues: { missingKeys, extraKeys, typeMismatches },\n });\n }\n\n printReport(reports);\n\n const fixableReports = reports.filter(\n (r) =>\n r.issues.missingKeys.length > 0 ||\n r.issues.extraKeys.length > 0 ||\n r.issues.typeMismatches.length > 0\n );\n\n if (fixableReports.length === 0) {\n return;\n }\n\n // Phase 2: Auto-correct\n if (ci && !yes) {\n throw new Error(\n `CI mode: validation found issues in ${fixableReports.length} locale(s). Re-run with --yes to auto-correct.`\n );\n }\n\n const confirmMsg = translator\n ? \"Auto-correct these issues? (translates missing keys, removes extra keys, re-translates type mismatches)\"\n : \"Auto-correct these issues? (adds missing keys as empty strings, removes extra keys, fixes type mismatches)\";\n\n const confirmed = await confirmAction(confirmMsg, {\n skip: yes ?? false,\n ci: ci ?? false,\n });\n\n if (!confirmed) {\n console.log(chalk.red(\"\\nAuto-correction cancelled.\\n\"));\n return;\n }\n\n for (const { locale, issues } of fixableReports) {\n const localeData = await fileManager.readLocale(locale);\n const localeFlat = flattenObject(localeData);\n\n // Collect keys that need translation\n const keysToTranslate = [\n ...issues.missingKeys,\n ...issues.typeMismatches.map((m) => m.key),\n ];\n\n if (translator && keysToTranslate.length > 0) {\n console.log(\n chalk.gray(\n ` Translating ${keysToTranslate.length} key(s) to ${locale}...`\n )\n );\n\n for (const key of keysToTranslate) {\n const sourceText = String(referenceFlat[key] ?? \"\");\n localeFlat[key] = await translateKey(\n translator,\n sourceText,\n locale,\n defaultLocale\n );\n }\n } else {\n // No translator — fall back to empty strings\n for (const key of keysToTranslate) {\n localeFlat[key] = \"\";\n }\n }\n\n // Remove extra keys\n for (const key of issues.extraKeys) {\n delete localeFlat[key];\n }\n\n const rebuilt =\n config.keyStyle === \"nested\"\n ? unflattenObject(localeFlat)\n : localeFlat;\n\n await fileManager.writeLocale(locale, rebuilt, {\n dryRun: dryRun ?? false,\n });\n\n console.log(chalk.green(`✔ Fixed ${locale}.json`));\n }\n\n if (dryRun) {\n console.log(\n chalk.yellow(\"\\n[DRY RUN] No files were modified.\\n\")\n );\n } else {\n console.log(\n chalk.green(\n `\\n✨ Auto-corrected ${fixableReports.length} locale file(s).\\n`\n )\n );\n }\n}\n","import { translate } from \"@vitalets/google-translate-api\";\nimport type {\n Translator,\n TranslationRequest,\n TranslationResult,\n GoogleTranslatorOptions\n} from \"./translator.js\";\n\nexport class GoogleTranslator implements Translator {\n readonly name = \"google\";\n private options: GoogleTranslatorOptions;\n\n constructor(options: GoogleTranslatorOptions = {}) {\n this.options = options;\n }\n\n async translate(request: TranslationRequest): Promise<TranslationResult> {\n const { text, targetLocale, sourceLocale } = request;\n const { from, host, fetchOptions } = this.options;\n const translateOptions: {\n to: string;\n from?: string;\n host?: string;\n fetchOptions?: Record<string, unknown>;\n } = { to: targetLocale };\n\n if (host !== undefined) {\n translateOptions.host = host;\n }\n\n if (fetchOptions !== undefined) {\n translateOptions.fetchOptions = fetchOptions;\n }\n\n if (sourceLocale !== undefined) {\n translateOptions.from = sourceLocale;\n } else if (from !== undefined) {\n translateOptions.from = from;\n }\n\n const result = await translate(text, translateOptions);\n\n return {\n text: result.text,\n detectedSourceLocale: result.raw?.src,\n provider: this.name\n };\n }\n}\n","import OpenAI from \"openai\";\nimport type {\n Translator,\n TranslationRequest,\n TranslationResult,\n OpenAITranslatorOptions,\n} from \"./translator.js\";\n\nexport class OpenAITranslator implements Translator {\n readonly name = \"openai\";\n private client: OpenAI;\n private model: string;\n\n constructor(options: OpenAITranslatorOptions = {}) {\n const apiKey = options.apiKey ?? process.env.OPENAI_API_KEY;\n\n if (!apiKey) {\n throw new Error(\n \"OpenAI API key is required. Provide it via the 'apiKey' constructor option or set the OPENAI_API_KEY environment variable.\"\n );\n }\n\n this.model = options.model ?? \"gpt-3.5-turbo\";\n this.client = new OpenAI({\n apiKey,\n ...(options.baseUrl ? { baseURL: options.baseUrl } : {}),\n });\n }\n\n async translate(request: TranslationRequest): Promise<TranslationResult> {\n const { text, targetLocale, sourceLocale, context } = request;\n\n const sourcePart = sourceLocale\n ? ` from ${sourceLocale}`\n : \"\";\n\n const systemMessage = `You are a professional translator. Translate the given text${sourcePart} to ${targetLocale}. Return ONLY the translated text, nothing else. Do not add quotes, explanations, or any extra formatting.`;\n\n const userMessage = context\n ? `Context: ${context}\\n\\n${text}`\n : text;\n\n const response = await this.client.chat.completions.create({\n model: this.model,\n temperature: 0.3,\n messages: [\n { role: \"system\", content: systemMessage },\n { role: \"user\", content: userMessage },\n ],\n });\n\n const content = response.choices[0]?.message?.content?.trim() ?? \"\";\n\n return {\n text: content,\n provider: this.name,\n };\n }\n}\n"],"mappings":"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","names":["chalk","fs","path","fs","inquirer","path","path","fs","inquirer","answers","chalk","chalk","chalk","chalk","chalk","chalk","chalk","chalk","chalk","chalk","fs","chalk","chalk","fs","chalk","chalk","chalk"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "i18n-ai-cli",
3
- "version": "1.0.1",
3
+ "version": "1.0.3",
4
4
  "description": "AI-powered CLI tool for managing translation files in internationalized applications",
5
5
  "main": "./dist/cli.js",
6
6
  "exports": {