i18n-ai-cli 1.0.2 → 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 +45 -0
- package/dist/cli.js +284 -2
- package/dist/cli.js.map +1 -1
- package/package.json +1 -1
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.
|
|
@@ -71,6 +72,9 @@ i18n-ai-cli add:key welcome.message --value "Welcome to our app"
|
|
|
71
72
|
|
|
72
73
|
# Clean up unused keys
|
|
73
74
|
i18n-ai-cli clean:unused
|
|
75
|
+
|
|
76
|
+
# Validate translation files
|
|
77
|
+
i18n-ai-cli validate
|
|
74
78
|
```
|
|
75
79
|
|
|
76
80
|
## Configuration
|
|
@@ -203,6 +207,28 @@ Example: `i18n-ai-cli remove:key auth.login.title`
|
|
|
203
207
|
|
|
204
208
|
Removes the key from all locales.
|
|
205
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
|
+
|
|
206
232
|
### Maintenance Commands
|
|
207
233
|
|
|
208
234
|
#### Clean unused keys
|
|
@@ -270,6 +296,16 @@ i18n-ai-cli add:lang de --from en
|
|
|
270
296
|
i18n-ai-cli remove:key auth.legacy --dry-run
|
|
271
297
|
```
|
|
272
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
|
+
|
|
273
309
|
### Skip confirmation prompts
|
|
274
310
|
```bash
|
|
275
311
|
i18n-ai-cli clean:unused --yes
|
|
@@ -285,6 +321,15 @@ To apply changes in CI:
|
|
|
285
321
|
i18n-ai-cli clean:unused --ci --yes
|
|
286
322
|
```
|
|
287
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
|
+
|
|
288
333
|
### Initialize in non-interactive mode
|
|
289
334
|
```bash
|
|
290
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
|
|
5
|
+
import chalk9 from "chalk";
|
|
6
6
|
|
|
7
7
|
// src/config/config-loader.ts
|
|
8
8
|
import fs from "fs-extra";
|
|
@@ -957,6 +957,262 @@ async function cleanUnusedCommand(context) {
|
|
|
957
957
|
}
|
|
958
958
|
}
|
|
959
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
|
+
|
|
960
1216
|
// src/bin/cli.ts
|
|
961
1217
|
var program = new Command();
|
|
962
1218
|
program.name("i18n-ai-cli").description("Professional CLI tool for managing translation files").version("1.0.0");
|
|
@@ -1004,11 +1260,37 @@ withGlobalOptions(
|
|
|
1004
1260
|
await cleanUnusedCommand(context);
|
|
1005
1261
|
})
|
|
1006
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
|
+
);
|
|
1007
1289
|
program.exitOverride();
|
|
1008
1290
|
try {
|
|
1009
1291
|
await program.parseAsync(process.argv);
|
|
1010
1292
|
} catch (err) {
|
|
1011
|
-
console.error(
|
|
1293
|
+
console.error(chalk9.red("\u274C Error:"), err.message);
|
|
1012
1294
|
process.exitCode = 1;
|
|
1013
1295
|
}
|
|
1014
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 // 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"],"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"]}
|