lingo.dev 0.100.1 → 0.102.0

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/build/cli.cjs CHANGED
@@ -22,16 +22,17 @@ function getSettings(explicitApiKey) {
22
22
  _envVarsInfo();
23
23
  return {
24
24
  auth: {
25
- apiKey: explicitApiKey || env.LINGODOTDEV_API_KEY || _optionalChain([systemFile, 'access', _34 => _34.auth, 'optionalAccess', _35 => _35.apiKey]) || defaults2.auth.apiKey,
26
- apiUrl: env.LINGODOTDEV_API_URL || _optionalChain([systemFile, 'access', _36 => _36.auth, 'optionalAccess', _37 => _37.apiUrl]) || defaults2.auth.apiUrl,
27
- webUrl: env.LINGODOTDEV_WEB_URL || _optionalChain([systemFile, 'access', _38 => _38.auth, 'optionalAccess', _39 => _39.webUrl]) || defaults2.auth.webUrl
25
+ apiKey: explicitApiKey || env.LINGODOTDEV_API_KEY || _optionalChain([systemFile, 'access', _35 => _35.auth, 'optionalAccess', _36 => _36.apiKey]) || defaults2.auth.apiKey,
26
+ apiUrl: env.LINGODOTDEV_API_URL || _optionalChain([systemFile, 'access', _37 => _37.auth, 'optionalAccess', _38 => _38.apiUrl]) || defaults2.auth.apiUrl,
27
+ webUrl: env.LINGODOTDEV_WEB_URL || _optionalChain([systemFile, 'access', _39 => _39.auth, 'optionalAccess', _40 => _40.webUrl]) || defaults2.auth.webUrl
28
28
  },
29
29
  llm: {
30
- openaiApiKey: env.OPENAI_API_KEY || _optionalChain([systemFile, 'access', _40 => _40.llm, 'optionalAccess', _41 => _41.openaiApiKey]),
31
- anthropicApiKey: env.ANTHROPIC_API_KEY || _optionalChain([systemFile, 'access', _42 => _42.llm, 'optionalAccess', _43 => _43.anthropicApiKey]),
32
- groqApiKey: env.GROQ_API_KEY || _optionalChain([systemFile, 'access', _44 => _44.llm, 'optionalAccess', _45 => _45.groqApiKey]),
33
- googleApiKey: env.GOOGLE_API_KEY || _optionalChain([systemFile, 'access', _46 => _46.llm, 'optionalAccess', _47 => _47.googleApiKey]),
34
- openrouterApiKey: env.OPENROUTER_API_KEY || _optionalChain([systemFile, 'access', _48 => _48.llm, 'optionalAccess', _49 => _49.openrouterApiKey])
30
+ openaiApiKey: env.OPENAI_API_KEY || _optionalChain([systemFile, 'access', _41 => _41.llm, 'optionalAccess', _42 => _42.openaiApiKey]),
31
+ anthropicApiKey: env.ANTHROPIC_API_KEY || _optionalChain([systemFile, 'access', _43 => _43.llm, 'optionalAccess', _44 => _44.anthropicApiKey]),
32
+ groqApiKey: env.GROQ_API_KEY || _optionalChain([systemFile, 'access', _45 => _45.llm, 'optionalAccess', _46 => _46.groqApiKey]),
33
+ googleApiKey: env.GOOGLE_API_KEY || _optionalChain([systemFile, 'access', _47 => _47.llm, 'optionalAccess', _48 => _48.googleApiKey]),
34
+ openrouterApiKey: env.OPENROUTER_API_KEY || _optionalChain([systemFile, 'access', _49 => _49.llm, 'optionalAccess', _50 => _50.openrouterApiKey]),
35
+ mistralApiKey: env.MISTRAL_API_KEY || _optionalChain([systemFile, 'access', _51 => _51.llm, 'optionalAccess', _52 => _52.mistralApiKey])
35
36
  }
36
37
  };
37
38
  }
@@ -61,7 +62,8 @@ var SettingsSchema = _zod2.default.object({
61
62
  anthropicApiKey: _zod2.default.string().optional(),
62
63
  groqApiKey: _zod2.default.string().optional(),
63
64
  googleApiKey: _zod2.default.string().optional(),
64
- openrouterApiKey: _zod2.default.string().optional()
65
+ openrouterApiKey: _zod2.default.string().optional(),
66
+ mistralApiKey: _zod2.default.string().optional()
65
67
  })
66
68
  });
67
69
  var SETTINGS_KEYS = flattenZodObject(
@@ -86,7 +88,8 @@ function _loadEnv() {
86
88
  ANTHROPIC_API_KEY: _zod2.default.string().optional(),
87
89
  GROQ_API_KEY: _zod2.default.string().optional(),
88
90
  GOOGLE_API_KEY: _zod2.default.string().optional(),
89
- OPENROUTER_API_KEY: _zod2.default.string().optional()
91
+ OPENROUTER_API_KEY: _zod2.default.string().optional(),
92
+ MISTRAL_API_KEY: _zod2.default.string().optional()
90
93
  }).passthrough().parse(process.env);
91
94
  }
92
95
  function _loadSystemFile() {
@@ -104,7 +107,8 @@ function _loadSystemFile() {
104
107
  anthropicApiKey: _zod2.default.string().optional(),
105
108
  groqApiKey: _zod2.default.string().optional(),
106
109
  googleApiKey: _zod2.default.string().optional(),
107
- openrouterApiKey: _zod2.default.string().optional()
110
+ openrouterApiKey: _zod2.default.string().optional(),
111
+ mistralApiKey: _zod2.default.string().optional()
108
112
  }).optional()
109
113
  }).passthrough().parse(data);
110
114
  }
@@ -137,42 +141,48 @@ Please use LINGODOTDEV_API_KEY instead.
137
141
  function _envVarsInfo() {
138
142
  const env = _loadEnv();
139
143
  const systemFile = _loadSystemFile();
140
- if (env.LINGODOTDEV_API_KEY && _optionalChain([systemFile, 'access', _50 => _50.auth, 'optionalAccess', _51 => _51.apiKey])) {
144
+ if (env.LINGODOTDEV_API_KEY && _optionalChain([systemFile, 'access', _53 => _53.auth, 'optionalAccess', _54 => _54.apiKey])) {
141
145
  console.info(
142
146
  "\x1B[36m%s\x1B[0m",
143
147
  `\u2139\uFE0F Using LINGODOTDEV_API_KEY env var instead of credentials from user config`
144
148
  );
145
149
  }
146
- if (env.OPENAI_API_KEY && _optionalChain([systemFile, 'access', _52 => _52.llm, 'optionalAccess', _53 => _53.openaiApiKey])) {
150
+ if (env.OPENAI_API_KEY && _optionalChain([systemFile, 'access', _55 => _55.llm, 'optionalAccess', _56 => _56.openaiApiKey])) {
147
151
  console.info(
148
152
  "\x1B[36m%s\x1B[0m",
149
153
  `\u2139\uFE0F Using OPENAI_API_KEY env var instead of key from user config.`
150
154
  );
151
155
  }
152
- if (env.ANTHROPIC_API_KEY && _optionalChain([systemFile, 'access', _54 => _54.llm, 'optionalAccess', _55 => _55.anthropicApiKey])) {
156
+ if (env.ANTHROPIC_API_KEY && _optionalChain([systemFile, 'access', _57 => _57.llm, 'optionalAccess', _58 => _58.anthropicApiKey])) {
153
157
  console.info(
154
158
  "\x1B[36m%s\x1B[0m",
155
159
  `\u2139\uFE0F Using ANTHROPIC_API_KEY env var instead of key from user config`
156
160
  );
157
161
  }
158
- if (env.GROQ_API_KEY && _optionalChain([systemFile, 'access', _56 => _56.llm, 'optionalAccess', _57 => _57.groqApiKey])) {
162
+ if (env.GROQ_API_KEY && _optionalChain([systemFile, 'access', _59 => _59.llm, 'optionalAccess', _60 => _60.groqApiKey])) {
159
163
  console.info(
160
164
  "\x1B[36m%s\x1B[0m",
161
165
  `\u2139\uFE0F Using GROQ_API_KEY env var instead of key from user config`
162
166
  );
163
167
  }
164
- if (env.GOOGLE_API_KEY && _optionalChain([systemFile, 'access', _58 => _58.llm, 'optionalAccess', _59 => _59.googleApiKey])) {
168
+ if (env.GOOGLE_API_KEY && _optionalChain([systemFile, 'access', _61 => _61.llm, 'optionalAccess', _62 => _62.googleApiKey])) {
165
169
  console.info(
166
170
  "\x1B[36m%s\x1B[0m",
167
171
  `\u2139\uFE0F Using GOOGLE_API_KEY env var instead of key from user config`
168
172
  );
169
173
  }
170
- if (env.OPENROUTER_API_KEY && _optionalChain([systemFile, 'access', _60 => _60.llm, 'optionalAccess', _61 => _61.openrouterApiKey])) {
174
+ if (env.OPENROUTER_API_KEY && _optionalChain([systemFile, 'access', _63 => _63.llm, 'optionalAccess', _64 => _64.openrouterApiKey])) {
171
175
  console.info(
172
176
  "\x1B[36m%s\x1B[0m",
173
177
  `\u2139\uFE0F Using OPENROUTER_API_KEY env var instead of key from user config`
174
178
  );
175
179
  }
180
+ if (env.MISTRAL_API_KEY && _optionalChain([systemFile, 'access', _65 => _65.llm, 'optionalAccess', _66 => _66.mistralApiKey])) {
181
+ console.info(
182
+ "\x1B[36m%s\x1B[0m",
183
+ `\u2139\uFE0F Using MISTRAL_API_KEY env var instead of key from user config`
184
+ );
185
+ }
176
186
  if (env.LINGODOTDEV_API_URL) {
177
187
  console.info(
178
188
  "\x1B[36m%s\x1B[0m",
@@ -217,9 +227,12 @@ var CLIError = class extends Error {
217
227
  // src/cli/utils/cloudflare-status.ts
218
228
  async function checkCloudflareStatus() {
219
229
  try {
220
- const response = await fetch("https://www.cloudflarestatus.com/api/v2/status.json", {
221
- signal: AbortSignal.timeout(5e3)
222
- });
230
+ const response = await fetch(
231
+ "https://www.cloudflarestatus.com/api/v2/status.json",
232
+ {
233
+ signal: AbortSignal.timeout(5e3)
234
+ }
235
+ );
223
236
  if (response.ok) {
224
237
  return await response.json();
225
238
  }
@@ -248,7 +261,7 @@ function createAuthenticator(params) {
248
261
  });
249
262
  if (res.ok) {
250
263
  const payload = await res.json();
251
- if (!_optionalChain([payload, 'optionalAccess', _62 => _62.email])) {
264
+ if (!_optionalChain([payload, 'optionalAccess', _67 => _67.email])) {
252
265
  return null;
253
266
  }
254
267
  return {
@@ -378,7 +391,9 @@ async function renderBanner() {
378
391
  }
379
392
  async function renderHero() {
380
393
  console.log(
381
- `\u26A1\uFE0F ${_chalk2.default.hex(colors.green)("Lingo.dev")} - open-source, AI-powered i18n CLI for web & mobile localization.`
394
+ `\u26A1\uFE0F ${_chalk2.default.hex(colors.green)(
395
+ "Lingo.dev"
396
+ )} - open-source, AI-powered i18n CLI for web & mobile localization.`
382
397
  );
383
398
  console.log("");
384
399
  const label1 = "\u2B50 GitHub Repo:";
@@ -386,13 +401,19 @@ async function renderHero() {
386
401
  const label3 = "\u{1F4AC} 24/7 Support:";
387
402
  const maxLabelWidth = 17;
388
403
  console.log(
389
- `${_chalk2.default.hex(colors.blue)(label1.padEnd(maxLabelWidth))} ${_chalk2.default.hex(colors.blue)("https://lingo.dev/go/gh")}`
404
+ `${_chalk2.default.hex(colors.blue)(label1.padEnd(maxLabelWidth))} ${_chalk2.default.hex(
405
+ colors.blue
406
+ )("https://lingo.dev/go/gh")}`
390
407
  );
391
408
  console.log(
392
- `${_chalk2.default.hex(colors.blue)(label2.padEnd(maxLabelWidth + 1))} ${_chalk2.default.hex(colors.blue)("https://lingo.dev/go/docs")}`
409
+ `${_chalk2.default.hex(colors.blue)(label2.padEnd(maxLabelWidth + 1))} ${_chalk2.default.hex(
410
+ colors.blue
411
+ )("https://lingo.dev/go/docs")}`
393
412
  );
394
413
  console.log(
395
- `${_chalk2.default.hex(colors.blue)(label3.padEnd(maxLabelWidth + 1))} ${_chalk2.default.hex(colors.blue)("hi@lingo.dev")}`
414
+ `${_chalk2.default.hex(colors.blue)(label3.padEnd(maxLabelWidth + 1))} ${_chalk2.default.hex(
415
+ colors.blue
416
+ )("hi@lingo.dev")}`
396
417
  );
397
418
  }
398
419
  async function waitForUserPrompt(message) {
@@ -545,6 +566,10 @@ function _getConfigFilePath() {
545
566
 
546
567
 
547
568
 
569
+
570
+
571
+
572
+
548
573
  var _prompts = require('@inquirer/prompts');
549
574
 
550
575
  // src/cli/utils/find-locale-paths.ts
@@ -583,13 +608,17 @@ function findLocaleFilesWithExtension(ext2) {
583
608
  ignore: ["node_modules/**", "package*.json", "i18n.json", "lingo.json"]
584
609
  });
585
610
  const localeFilePattern = new RegExp(`/([a-z]{2}(-[A-Z]{2})?)${ext2}$`);
586
- const localeDirectoryPattern = new RegExp(`/([a-z]{2}(-[A-Z]{2})?)/[^/]+${ext2}$`);
611
+ const localeDirectoryPattern = new RegExp(
612
+ `/([a-z]{2}(-[A-Z]{2})?)/[^/]+${ext2}$`
613
+ );
587
614
  const potentialLocaleFiles = files.filter(
588
615
  (file) => localeFilePattern.test(file) || localeDirectoryPattern.test(file)
589
616
  );
590
617
  const potantialLocaleFilesAndPatterns = potentialLocaleFiles.map((file) => {
591
618
  const matchPotentialLocales = Array.from(
592
- file.matchAll(new RegExp(`/([a-z]{2}(-[A-Z]{2})?|[^/]+)(?=/|${ext2})`, "g"))
619
+ file.matchAll(
620
+ new RegExp(`/([a-z]{2}(-[A-Z]{2})?|[^/]+)(?=/|${ext2})`, "g")
621
+ )
593
622
  );
594
623
  const potantialLocales = matchPotentialLocales.map((match2) => match2[1]);
595
624
  return { file, potantialLocales };
@@ -603,10 +632,12 @@ function findLocaleFilesWithExtension(ext2) {
603
632
  }
604
633
  return { file, locale: null };
605
634
  }).filter(({ locale }) => locale !== null);
606
- const localeFilesAndPatterns = potantialLocaleFilesAndPatterns.map(({ file, locale }) => {
607
- const pattern = file.replaceAll(new RegExp(`/${locale}${ext2}`, "g"), `/[locale]${ext2}`).replaceAll(new RegExp(`/${locale}/`, "g"), `/[locale]/`).replaceAll(new RegExp(`/${locale}/`, "g"), `/[locale]/`);
608
- return { pattern, file };
609
- });
635
+ const localeFilesAndPatterns = potantialLocaleFilesAndPatterns.map(
636
+ ({ file, locale }) => {
637
+ const pattern = file.replaceAll(new RegExp(`/${locale}${ext2}`, "g"), `/[locale]${ext2}`).replaceAll(new RegExp(`/${locale}/`, "g"), `/[locale]/`).replaceAll(new RegExp(`/${locale}/`, "g"), `/[locale]/`);
638
+ return { pattern, file };
639
+ }
640
+ );
610
641
  const grouppedFilesAndPatterns = _lodash2.default.groupBy(localeFilesAndPatterns, "pattern");
611
642
  const patterns = Object.keys(grouppedFilesAndPatterns);
612
643
  const defaultPatterns = [`i18n/[locale]${ext2}`];
@@ -764,7 +795,9 @@ async function initCICD(spinner) {
764
795
  message: "Would you like to use Lingo.dev in your CI/CD?"
765
796
  });
766
797
  if (!init) {
767
- spinner.warn("CI/CD not initialized. To set it up later, see docs: https://lingo.dev/ci");
798
+ spinner.warn(
799
+ "CI/CD not initialized. To set it up later, see docs: https://lingo.dev/ci"
800
+ );
768
801
  return;
769
802
  }
770
803
  const selectedPlatforms = await _prompts.checkbox.call(void 0, {
@@ -895,7 +928,9 @@ var throwHelpError = (option, value) => {
895
928
  Do you need support for ${value} ${option}? Type "help" and we will.`
896
929
  );
897
930
  };
898
- var init_default = new (0, _interactivecommander.InteractiveCommand)().command("init").description("Initialize Lingo.dev project").helpOption("-h, --help", "Show help").addOption(new (0, _interactivecommander.InteractiveOption)("-f --force", "Overwrite existing config").prompt(void 0).default(false)).addOption(
931
+ var init_default = new (0, _interactivecommander.InteractiveCommand)().command("init").description("Initialize Lingo.dev project").helpOption("-h, --help", "Show help").addOption(
932
+ new (0, _interactivecommander.InteractiveOption)("-f --force", "Overwrite existing config").prompt(void 0).default(false)
933
+ ).addOption(
899
934
  new (0, _interactivecommander.InteractiveOption)("-s --source <locale>", "Source locale").argParser((value) => {
900
935
  try {
901
936
  __spec.resolveLocaleCode.call(void 0, value);
@@ -924,7 +959,10 @@ var init_default = new (0, _interactivecommander.InteractiveCommand)().command("
924
959
  return value;
925
960
  }).default("json")
926
961
  ).addOption(
927
- new (0, _interactivecommander.InteractiveOption)("-p, --paths [path...]", "List of paths for the bucket").argParser((value) => {
962
+ new (0, _interactivecommander.InteractiveOption)(
963
+ "-p, --paths [path...]",
964
+ "List of paths for the bucket"
965
+ ).argParser((value) => {
928
966
  if (!value || value.length === 0) return [];
929
967
  const values = value.includes(",") ? value.split(",") : value.split(" ");
930
968
  for (const p of values) {
@@ -985,7 +1023,9 @@ var init_default = new (0, _interactivecommander.InteractiveCommand)().command("
985
1023
  }
986
1024
  if (selectedPatterns.length === 0) {
987
1025
  const useDefault = await _prompts.confirm.call(void 0, {
988
- message: `Use (and create) default path ${defaultPatterns.join(", ")}?`
1026
+ message: `Use (and create) default path ${defaultPatterns.join(
1027
+ ", "
1028
+ )}?`
989
1029
  });
990
1030
  if (useDefault) {
991
1031
  ensurePatterns(defaultPatterns, options.source);
@@ -1009,7 +1049,9 @@ var init_default = new (0, _interactivecommander.InteractiveCommand)().command("
1009
1049
  spinner.succeed("Lingo.dev project initialized");
1010
1050
  if (isInteractive) {
1011
1051
  await initCICD(spinner);
1012
- const openDocs = await _prompts.confirm.call(void 0, { message: "Would you like to see our docs?" });
1052
+ const openDocs = await _prompts.confirm.call(void 0, {
1053
+ message: "Would you like to see our docs?"
1054
+ });
1013
1055
  if (openDocs) {
1014
1056
  openUrl("/go/docs");
1015
1057
  }
@@ -1034,13 +1076,15 @@ var init_default = new (0, _interactivecommander.InteractiveCommand)().command("
1034
1076
  });
1035
1077
  const auth2 = await newAuthenticator.whoami();
1036
1078
  if (auth2) {
1037
- _ora2.default.call(void 0, ).succeed(`Authenticated as ${_optionalChain([auth2, 'optionalAccess', _63 => _63.email])}`);
1079
+ _ora2.default.call(void 0, ).succeed(`Authenticated as ${_optionalChain([auth2, 'optionalAccess', _68 => _68.email])}`);
1038
1080
  } else {
1039
1081
  _ora2.default.call(void 0, ).fail("Authentication failed.");
1040
1082
  }
1041
1083
  }
1042
1084
  } else {
1043
- _ora2.default.call(void 0, ).warn("You are not logged in. Run `npx lingo.dev@latest auth --login` to login.");
1085
+ _ora2.default.call(void 0, ).warn(
1086
+ "You are not logged in. Run `npx lingo.dev@latest auth --login` to login."
1087
+ );
1044
1088
  }
1045
1089
  } else {
1046
1090
  _ora2.default.call(void 0, ).succeed(`Authenticated as ${auth.email}`);
@@ -1119,7 +1163,7 @@ function getBuckets(i18nConfig) {
1119
1163
  const includeItems = bucketEntry.include.map(
1120
1164
  (item) => resolveBucketItem(item)
1121
1165
  );
1122
- const excludeItems = _optionalChain([bucketEntry, 'access', _64 => _64.exclude, 'optionalAccess', _65 => _65.map, 'call', _66 => _66(
1166
+ const excludeItems = _optionalChain([bucketEntry, 'access', _69 => _69.exclude, 'optionalAccess', _70 => _70.map, 'call', _71 => _71(
1123
1167
  (item) => resolveBucketItem(item)
1124
1168
  )]);
1125
1169
  const config = {
@@ -1157,7 +1201,7 @@ function extractPathPatterns(sourceLocale, include, exclude) {
1157
1201
  delimiter: pattern.delimiter
1158
1202
  }))
1159
1203
  );
1160
- const excludedPatterns = _optionalChain([exclude, 'optionalAccess', _67 => _67.flatMap, 'call', _68 => _68(
1204
+ const excludedPatterns = _optionalChain([exclude, 'optionalAccess', _72 => _72.flatMap, 'call', _73 => _73(
1161
1205
  (pattern) => expandPlaceholderedGlob(
1162
1206
  pattern.path,
1163
1207
  __spec.resolveOverriddenLocale.call(void 0, sourceLocale, pattern.delimiter)
@@ -1229,7 +1273,13 @@ function resolveBucketItem(bucketItem) {
1229
1273
 
1230
1274
  // src/cli/cmd/show/files.ts
1231
1275
 
1232
- var files_default = new (0, _interactivecommander.Command)().command("files").description("Print out the list of files managed by Lingo.dev").option("--source", "Only show source files, files containing the original translations").option("--target", "Only show target files, files containing translated content").helpOption("-h, --help", "Show help").action(async (type) => {
1276
+ var files_default = new (0, _interactivecommander.Command)().command("files").description("Print out the list of files managed by Lingo.dev").option(
1277
+ "--source",
1278
+ "Only show source files, files containing the original translations"
1279
+ ).option(
1280
+ "--target",
1281
+ "Only show target files, files containing translated content"
1282
+ ).helpOption("-h, --help", "Show help").action(async (type) => {
1233
1283
  const ora = _ora2.default.call(void 0, );
1234
1284
  try {
1235
1285
  try {
@@ -1243,12 +1293,26 @@ var files_default = new (0, _interactivecommander.Command)().command("files").de
1243
1293
  const buckets = getBuckets(i18nConfig);
1244
1294
  for (const bucket of buckets) {
1245
1295
  for (const bucketConfig of bucket.paths) {
1246
- const sourceLocale = __spec.resolveOverriddenLocale.call(void 0, i18nConfig.locale.source, bucketConfig.delimiter);
1247
- const sourcePath = bucketConfig.pathPattern.replace(/\[locale\]/g, sourceLocale);
1248
- const targetPaths = i18nConfig.locale.targets.map((_targetLocale) => {
1249
- const targetLocale = __spec.resolveOverriddenLocale.call(void 0, _targetLocale, bucketConfig.delimiter);
1250
- return bucketConfig.pathPattern.replace(/\[locale\]/g, targetLocale);
1251
- });
1296
+ const sourceLocale = __spec.resolveOverriddenLocale.call(void 0,
1297
+ i18nConfig.locale.source,
1298
+ bucketConfig.delimiter
1299
+ );
1300
+ const sourcePath = bucketConfig.pathPattern.replace(
1301
+ /\[locale\]/g,
1302
+ sourceLocale
1303
+ );
1304
+ const targetPaths = i18nConfig.locale.targets.map(
1305
+ (_targetLocale) => {
1306
+ const targetLocale = __spec.resolveOverriddenLocale.call(void 0,
1307
+ _targetLocale,
1308
+ bucketConfig.delimiter
1309
+ );
1310
+ return bucketConfig.pathPattern.replace(
1311
+ /\[locale\]/g,
1312
+ targetLocale
1313
+ );
1314
+ }
1315
+ );
1252
1316
  const result = [];
1253
1317
  if (!type.source && !type.target) {
1254
1318
  result.push(sourcePath, ...targetPaths);
@@ -1328,7 +1392,9 @@ Available keys:
1328
1392
  console.error(
1329
1393
  _dedent2.default`
1330
1394
  ${_chalk2.default.red("\u2716")} Unknown configuration key: ${_chalk2.default.bold(key)}
1331
- Run ${_chalk2.default.dim("lingo.dev config unset --help")} to see available keys.
1395
+ Run ${_chalk2.default.dim(
1396
+ "lingo.dev config unset --help"
1397
+ )} to see available keys.
1332
1398
  `
1333
1399
  );
1334
1400
  process.exitCode = 1;
@@ -1410,12 +1476,12 @@ function composeLoaders(...loaders) {
1410
1476
  return {
1411
1477
  init: async () => {
1412
1478
  for (const loader of loaders) {
1413
- await _optionalChain([loader, 'access', _69 => _69.init, 'optionalCall', _70 => _70()]);
1479
+ await _optionalChain([loader, 'access', _74 => _74.init, 'optionalCall', _75 => _75()]);
1414
1480
  }
1415
1481
  },
1416
1482
  setDefaultLocale(locale) {
1417
1483
  for (const loader of loaders) {
1418
- _optionalChain([loader, 'access', _71 => _71.setDefaultLocale, 'optionalCall', _72 => _72(locale)]);
1484
+ _optionalChain([loader, 'access', _76 => _76.setDefaultLocale, 'optionalCall', _77 => _77(locale)]);
1419
1485
  }
1420
1486
  return this;
1421
1487
  },
@@ -1448,7 +1514,7 @@ function createLoader(lDefinition) {
1448
1514
  if (state.initCtx) {
1449
1515
  return state.initCtx;
1450
1516
  }
1451
- state.initCtx = await _optionalChain([lDefinition, 'access', _73 => _73.init, 'optionalCall', _74 => _74()]);
1517
+ state.initCtx = await _optionalChain([lDefinition, 'access', _78 => _78.init, 'optionalCall', _79 => _79()]);
1452
1518
  return state.initCtx;
1453
1519
  },
1454
1520
  setDefaultLocale(locale) {
@@ -1553,7 +1619,7 @@ function createNormalizeLoader() {
1553
1619
  return normalized;
1554
1620
  },
1555
1621
  push: async (locale, data, originalInput) => {
1556
- const keysMap = _nullishCoalesce(_optionalChain([originalInput, 'optionalAccess', _75 => _75.keysMap]), () => ( {}));
1622
+ const keysMap = _nullishCoalesce(_optionalChain([originalInput, 'optionalAccess', _80 => _80.keysMap]), () => ( {}));
1557
1623
  const input2 = mapDenormalizedKeys(data, keysMap);
1558
1624
  const denormalized = _flat.unflatten.call(void 0, input2, {
1559
1625
  delimiter: "/",
@@ -1627,13 +1693,17 @@ function createTextFileLoader(pathPattern) {
1627
1693
  const trimmedResult = result.trim();
1628
1694
  return trimmedResult;
1629
1695
  },
1630
- async push(locale, data, _33, originalLocale) {
1696
+ async push(locale, data, _34, originalLocale) {
1631
1697
  const draftPath = pathPattern.replaceAll("[locale]", locale);
1632
1698
  const finalPath = path12.default.resolve(draftPath);
1633
1699
  const dirPath = path12.default.dirname(finalPath);
1634
1700
  await _promises4.default.mkdir(dirPath, { recursive: true });
1635
1701
  const trimmedPayload = data.trim();
1636
- const trailingNewLine = await getTrailingNewLine(pathPattern, locale, originalLocale);
1702
+ const trailingNewLine = await getTrailingNewLine(
1703
+ pathPattern,
1704
+ locale,
1705
+ originalLocale
1706
+ );
1637
1707
  let finalPayload = trimmedPayload + trailingNewLine;
1638
1708
  await _promises4.default.writeFile(finalPath, finalPayload, {
1639
1709
  encoding: "utf-8",
@@ -1656,8 +1726,8 @@ async function getTrailingNewLine(pathPattern, locale, originalLocale) {
1656
1726
  if (!templateData) {
1657
1727
  templateData = await readFileForLocale(pathPattern, originalLocale);
1658
1728
  }
1659
- if (_optionalChain([templateData, 'optionalAccess', _76 => _76.match, 'call', _77 => _77(/[\r\n]$/)])) {
1660
- const ending = _optionalChain([templateData, 'optionalAccess', _78 => _78.includes, 'call', _79 => _79("\r\n")]) ? "\r\n" : _optionalChain([templateData, 'optionalAccess', _80 => _80.includes, 'call', _81 => _81("\r")]) ? "\r" : "\n";
1729
+ if (_optionalChain([templateData, 'optionalAccess', _81 => _81.match, 'call', _82 => _82(/[\r\n]$/)])) {
1730
+ const ending = _optionalChain([templateData, 'optionalAccess', _83 => _83.includes, 'call', _84 => _84("\r\n")]) ? "\r\n" : _optionalChain([templateData, 'optionalAccess', _85 => _85.includes, 'call', _86 => _86("\r")]) ? "\r" : "\n";
1661
1731
  return ending;
1662
1732
  }
1663
1733
  return "";
@@ -1727,15 +1797,22 @@ function createRootKeyLoader(replaceAll = false) {
1727
1797
  function createFlutterLoader() {
1728
1798
  return createLoader({
1729
1799
  async pull(locale, input2) {
1730
- const result = _lodash2.default.pickBy(input2, (value, key) => !key.startsWith("@"));
1800
+ const result = _lodash2.default.pickBy(input2, (value, key) => !_isMetadataKey(key));
1731
1801
  return result;
1732
1802
  },
1733
1803
  async push(locale, data, originalInput) {
1734
- const result = _lodash2.default.merge({}, originalInput, { "@@locale": locale }, data);
1804
+ const metadata = _lodash2.default.pickBy(
1805
+ originalInput,
1806
+ (value, key) => _isMetadataKey(key)
1807
+ );
1808
+ const result = _lodash2.default.merge({}, metadata, { "@@locale": locale }, data);
1735
1809
  return result;
1736
1810
  }
1737
1811
  });
1738
1812
  }
1813
+ function _isMetadataKey(key) {
1814
+ return key.startsWith("@");
1815
+ }
1739
1816
 
1740
1817
  // src/cli/loaders/android.ts
1741
1818
  var _xml2js = require('xml2js');
@@ -1921,7 +1998,7 @@ var _sync3 = require('csv-stringify/sync');
1921
1998
 
1922
1999
  function detectKeyColumnName(csvString) {
1923
2000
  const row = _sync.parse.call(void 0, csvString)[0];
1924
- const firstColumn = _optionalChain([row, 'optionalAccess', _82 => _82[0], 'optionalAccess', _83 => _83.trim, 'call', _84 => _84()]);
2001
+ const firstColumn = _optionalChain([row, 'optionalAccess', _87 => _87[0], 'optionalAccess', _88 => _88.trim, 'call', _89 => _89()]);
1925
2002
  return firstColumn || "KEY";
1926
2003
  }
1927
2004
  function createCsvLoader() {
@@ -1930,7 +2007,9 @@ function createCsvLoader() {
1930
2007
  function _createCsvLoader() {
1931
2008
  return createLoader({
1932
2009
  async pull(locale, input2) {
1933
- const keyColumnName = detectKeyColumnName(input2.split("\n").find((l) => l.length));
2010
+ const keyColumnName = detectKeyColumnName(
2011
+ input2.split("\n").find((l) => l.length)
2012
+ );
1934
2013
  const inputParsed = _sync.parse.call(void 0, input2, {
1935
2014
  columns: true,
1936
2015
  skip_empty_lines: true,
@@ -1958,7 +2037,9 @@ function _createCsvLoader() {
1958
2037
  ...row,
1959
2038
  [locale]: items[row[keyColumnName]] || row[locale] || ""
1960
2039
  }));
1961
- const existingKeys = new Set(inputParsed.map((row) => row[keyColumnName]));
2040
+ const existingKeys = new Set(
2041
+ inputParsed.map((row) => row[keyColumnName])
2042
+ );
1962
2043
  Object.entries(items).forEach(([key, value]) => {
1963
2044
  if (!existingKeys.has(key)) {
1964
2045
  const newRow = {
@@ -2019,7 +2100,7 @@ function createHtmlLoader() {
2019
2100
  break;
2020
2101
  }
2021
2102
  const siblings = Array.from(parent.childNodes).filter(
2022
- (n) => n.nodeType === 1 || n.nodeType === 3 && _optionalChain([n, 'access', _85 => _85.textContent, 'optionalAccess', _86 => _86.trim, 'call', _87 => _87()])
2103
+ (n) => n.nodeType === 1 || n.nodeType === 3 && _optionalChain([n, 'access', _90 => _90.textContent, 'optionalAccess', _91 => _91.trim, 'call', _92 => _92()])
2023
2104
  );
2024
2105
  const index = siblings.indexOf(current);
2025
2106
  if (index !== -1) {
@@ -2054,15 +2135,23 @@ function createHtmlLoader() {
2054
2135
  result[getPath(element, attr)] = value;
2055
2136
  }
2056
2137
  });
2057
- Array.from(element.childNodes).filter((n) => n.nodeType === 1 || n.nodeType === 3 && _optionalChain([n, 'access', _88 => _88.textContent, 'optionalAccess', _89 => _89.trim, 'call', _90 => _90()])).forEach(processNode);
2138
+ Array.from(element.childNodes).filter(
2139
+ (n) => n.nodeType === 1 || n.nodeType === 3 && _optionalChain([n, 'access', _93 => _93.textContent, 'optionalAccess', _94 => _94.trim, 'call', _95 => _95()])
2140
+ ).forEach(processNode);
2058
2141
  }
2059
2142
  };
2060
- Array.from(document.head.childNodes).filter((n) => n.nodeType === 1 || n.nodeType === 3 && _optionalChain([n, 'access', _91 => _91.textContent, 'optionalAccess', _92 => _92.trim, 'call', _93 => _93()])).forEach(processNode);
2061
- Array.from(document.body.childNodes).filter((n) => n.nodeType === 1 || n.nodeType === 3 && _optionalChain([n, 'access', _94 => _94.textContent, 'optionalAccess', _95 => _95.trim, 'call', _96 => _96()])).forEach(processNode);
2143
+ Array.from(document.head.childNodes).filter(
2144
+ (n) => n.nodeType === 1 || n.nodeType === 3 && _optionalChain([n, 'access', _96 => _96.textContent, 'optionalAccess', _97 => _97.trim, 'call', _98 => _98()])
2145
+ ).forEach(processNode);
2146
+ Array.from(document.body.childNodes).filter(
2147
+ (n) => n.nodeType === 1 || n.nodeType === 3 && _optionalChain([n, 'access', _99 => _99.textContent, 'optionalAccess', _100 => _100.trim, 'call', _101 => _101()])
2148
+ ).forEach(processNode);
2062
2149
  return result;
2063
2150
  },
2064
2151
  async push(locale, data, originalInput) {
2065
- const dom = new (0, _jsdom.JSDOM)(_nullishCoalesce(originalInput, () => ( "<!DOCTYPE html><html><head></head><body></body></html>")));
2152
+ const dom = new (0, _jsdom.JSDOM)(
2153
+ _nullishCoalesce(originalInput, () => ( "<!DOCTYPE html><html><head></head><body></body></html>"))
2154
+ );
2066
2155
  const document = dom.window.document;
2067
2156
  const htmlElement = document.documentElement;
2068
2157
  htmlElement.setAttribute("lang", locale);
@@ -2080,7 +2169,7 @@ function createHtmlLoader() {
2080
2169
  for (let i = 0; i < indices.length; i++) {
2081
2170
  const index = parseInt(indices[i]);
2082
2171
  const siblings = Array.from(parent.childNodes).filter(
2083
- (n) => n.nodeType === 1 || n.nodeType === 3 && _optionalChain([n, 'access', _97 => _97.textContent, 'optionalAccess', _98 => _98.trim, 'call', _99 => _99()])
2172
+ (n) => n.nodeType === 1 || n.nodeType === 3 && _optionalChain([n, 'access', _102 => _102.textContent, 'optionalAccess', _103 => _103.trim, 'call', _104 => _104()])
2084
2173
  );
2085
2174
  if (index >= siblings.length) {
2086
2175
  if (i === indices.length - 1) {
@@ -2131,19 +2220,26 @@ function createMarkdownLoader() {
2131
2220
  yaml: yamlEngine
2132
2221
  }
2133
2222
  });
2134
- const sections = content.split(SECTION_REGEX).map((section) => _nullishCoalesce(_optionalChain([section, 'optionalAccess', _100 => _100.trim, 'call', _101 => _101()]), () => ( ""))).filter(Boolean);
2223
+ const sections = content.split(SECTION_REGEX).map((section) => _nullishCoalesce(_optionalChain([section, 'optionalAccess', _105 => _105.trim, 'call', _106 => _106()]), () => ( ""))).filter(Boolean);
2135
2224
  return {
2136
2225
  ...Object.fromEntries(
2137
2226
  sections.map((section, index) => [`${MD_SECTION_PREFIX}${index}`, section]).filter(([, section]) => Boolean(section))
2138
2227
  ),
2139
- ...Object.fromEntries(Object.entries(frontmatter).map(([key, value]) => [`${FM_ATTR_PREFIX}${key}`, value]))
2228
+ ...Object.fromEntries(
2229
+ Object.entries(frontmatter).map(([key, value]) => [
2230
+ `${FM_ATTR_PREFIX}${key}`,
2231
+ value
2232
+ ])
2233
+ )
2140
2234
  };
2141
2235
  },
2142
2236
  async push(locale, data) {
2143
2237
  const frontmatter = Object.fromEntries(
2144
2238
  Object.entries(data).filter(([key]) => key.startsWith(FM_ATTR_PREFIX)).map(([key, value]) => [key.replace(FM_ATTR_PREFIX, ""), value])
2145
2239
  );
2146
- let content = Object.entries(data).filter(([key]) => key.startsWith(MD_SECTION_PREFIX)).sort(([a], [b]) => Number(a.split("-").pop()) - Number(b.split("-").pop())).map(([, value]) => _nullishCoalesce(_optionalChain([value, 'optionalAccess', _102 => _102.trim, 'call', _103 => _103()]), () => ( ""))).filter(Boolean).join("\n\n");
2240
+ let content = Object.entries(data).filter(([key]) => key.startsWith(MD_SECTION_PREFIX)).sort(
2241
+ ([a], [b]) => Number(a.split("-").pop()) - Number(b.split("-").pop())
2242
+ ).map(([, value]) => _nullishCoalesce(_optionalChain([value, 'optionalAccess', _107 => _107.trim, 'call', _108 => _108()]), () => ( ""))).filter(Boolean).join("\n\n");
2147
2243
  if (Object.keys(frontmatter).length > 0) {
2148
2244
  content = `
2149
2245
  ${content}`;
@@ -2176,7 +2272,7 @@ function createPropertiesLoader() {
2176
2272
  return result;
2177
2273
  },
2178
2274
  async push(locale, payload) {
2179
- const result = Object.entries(payload).filter(([_33, value]) => value != null).map(([key, value]) => `${key}=${value}`).join("\n");
2275
+ const result = Object.entries(payload).filter(([_34, value]) => value != null).map(([key, value]) => `${key}=${value}`).join("\n");
2180
2276
  return result;
2181
2277
  }
2182
2278
  });
@@ -2187,7 +2283,7 @@ function isSkippableLine(line) {
2187
2283
  function parsePropertyLine(line) {
2188
2284
  const [key, ...valueParts] = line.split("=");
2189
2285
  return {
2190
- key: _optionalChain([key, 'optionalAccess', _104 => _104.trim, 'call', _105 => _105()]) || "",
2286
+ key: _optionalChain([key, 'optionalAccess', _109 => _109.trim, 'call', _110 => _110()]) || "",
2191
2287
  value: valueParts.join("=").trim()
2192
2288
  };
2193
2289
  }
@@ -2268,12 +2364,14 @@ function createXcodeXcstringsLoader(defaultLocale) {
2268
2364
  async pull(locale, input2, initCtx) {
2269
2365
  const resultData = {};
2270
2366
  const isSourceLanguage = locale === defaultLocale;
2271
- for (const [translationKey, _translationEntity] of Object.entries(input2.strings)) {
2367
+ for (const [translationKey, _translationEntity] of Object.entries(
2368
+ input2.strings
2369
+ )) {
2272
2370
  const rootTranslationEntity = _translationEntity;
2273
2371
  if (rootTranslationEntity.shouldTranslate === false) {
2274
2372
  continue;
2275
2373
  }
2276
- const langTranslationEntity = _optionalChain([rootTranslationEntity, 'optionalAccess', _106 => _106.localizations, 'optionalAccess', _107 => _107[locale]]);
2374
+ const langTranslationEntity = _optionalChain([rootTranslationEntity, 'optionalAccess', _111 => _111.localizations, 'optionalAccess', _112 => _112[locale]]);
2277
2375
  if (langTranslationEntity) {
2278
2376
  if ("stringUnit" in langTranslationEntity) {
2279
2377
  resultData[translationKey] = langTranslationEntity.stringUnit.value;
@@ -2282,7 +2380,7 @@ function createXcodeXcstringsLoader(defaultLocale) {
2282
2380
  resultData[translationKey] = {};
2283
2381
  const pluralForms = langTranslationEntity.variations.plural;
2284
2382
  for (const form in pluralForms) {
2285
- if (_optionalChain([pluralForms, 'access', _108 => _108[form], 'optionalAccess', _109 => _109.stringUnit, 'optionalAccess', _110 => _110.value])) {
2383
+ if (_optionalChain([pluralForms, 'access', _113 => _113[form], 'optionalAccess', _114 => _114.stringUnit, 'optionalAccess', _115 => _115.value])) {
2286
2384
  resultData[translationKey][form] = pluralForms[form].stringUnit.value;
2287
2385
  }
2288
2386
  }
@@ -2297,7 +2395,10 @@ function createXcodeXcstringsLoader(defaultLocale) {
2297
2395
  async push(locale, payload, originalInput) {
2298
2396
  const langDataToMerge = {};
2299
2397
  langDataToMerge.strings = {};
2300
- const input2 = _lodash2.default.cloneDeep(originalInput) || { sourceLanguage: locale, strings: {} };
2398
+ const input2 = _lodash2.default.cloneDeep(originalInput) || {
2399
+ sourceLanguage: locale,
2400
+ strings: {}
2401
+ };
2301
2402
  for (const [key, value] of Object.entries(payload)) {
2302
2403
  if (value === null || value === void 0) {
2303
2404
  continue;
@@ -2305,7 +2406,7 @@ function createXcodeXcstringsLoader(defaultLocale) {
2305
2406
  const hasDoNotTranslateFlag = originalInput && originalInput.strings && originalInput.strings[key] && originalInput.strings[key].shouldTranslate === false;
2306
2407
  if (typeof value === "string") {
2307
2408
  langDataToMerge.strings[key] = {
2308
- extractionState: _optionalChain([originalInput, 'optionalAccess', _111 => _111.strings, 'optionalAccess', _112 => _112[key], 'optionalAccess', _113 => _113.extractionState]),
2409
+ extractionState: _optionalChain([originalInput, 'optionalAccess', _116 => _116.strings, 'optionalAccess', _117 => _117[key], 'optionalAccess', _118 => _118.extractionState]),
2309
2410
  localizations: {
2310
2411
  [locale]: {
2311
2412
  stringUnit: {
@@ -2343,11 +2444,22 @@ function createXcodeXcstringsLoader(defaultLocale) {
2343
2444
  }
2344
2445
  }
2345
2446
  }
2346
- const result = _lodash2.default.merge({}, originalInput, langDataToMerge);
2447
+ const originalInputWithoutLocale = originalInput ? _removeLocale(originalInput, locale) : {};
2448
+ const result = _lodash2.default.merge({}, originalInputWithoutLocale, langDataToMerge);
2347
2449
  return result;
2348
2450
  }
2349
2451
  });
2350
2452
  }
2453
+ function _removeLocale(input2, locale) {
2454
+ const { sourceLanguage, strings } = input2;
2455
+ const newStrings = _lodash2.default.cloneDeep(strings);
2456
+ for (const [key, value] of Object.entries(newStrings)) {
2457
+ if (_optionalChain([value, 'access', _119 => _119.localizations, 'optionalAccess', _120 => _120[locale]])) {
2458
+ delete value.localizations[locale];
2459
+ }
2460
+ }
2461
+ return { sourceLanguage, strings: newStrings };
2462
+ }
2351
2463
 
2352
2464
  // src/cli/loaders/prettier.ts
2353
2465
 
@@ -2425,36 +2537,29 @@ async function formatDataWithPrettier(data, filePath, options) {
2425
2537
 
2426
2538
  var _isurl = require('is-url'); var _isurl2 = _interopRequireDefault(_isurl);
2427
2539
  var _datefns = require('date-fns');
2428
- function createUnlocalizableLoader(isCacheRestore = false, returnUnlocalizedKeys = false) {
2429
- const rules = {
2430
- isEmpty: (v) => _lodash2.default.isEmpty(v),
2431
- isNumber: (v) => typeof v === "number" || /^[0-9]+$/.test(v),
2432
- isBoolean: (v) => _lodash2.default.isBoolean(v),
2433
- isIsoDate: (v) => _lodash2.default.isString(v) && _isIsoDate(v),
2434
- isSystemId: (v) => _lodash2.default.isString(v) && _isSystemId(v),
2435
- isUrl: (v) => _lodash2.default.isString(v) && _isurl2.default.call(void 0, v)
2436
- };
2540
+ function createUnlocalizableLoader(returnUnlocalizedKeys = false) {
2437
2541
  return createLoader({
2438
2542
  async pull(locale, input2) {
2439
- const passthroughKeys = Object.entries(input2).filter(([key, value]) => {
2440
- for (const [ruleName, rule] of Object.entries(rules)) {
2441
- if (rule(value)) {
2442
- return true;
2443
- }
2444
- }
2445
- return false;
2446
- }).map(([key, _33]) => key);
2447
- const result = _lodash2.default.omitBy(input2, (_33, key) => passthroughKeys.includes(key));
2543
+ const unlocalizableKeys = _getUnlocalizableKeys(input2);
2544
+ const result = _lodash2.default.omitBy(
2545
+ input2,
2546
+ (_34, key) => unlocalizableKeys.includes(key)
2547
+ );
2448
2548
  if (returnUnlocalizedKeys) {
2449
- result.unlocalizable = _lodash2.default.omitBy(input2, (_33, key) => !passthroughKeys.includes(key));
2549
+ result.unlocalizable = _lodash2.default.omitBy(
2550
+ input2,
2551
+ (_34, key) => !unlocalizableKeys.includes(key)
2552
+ );
2450
2553
  }
2451
2554
  return result;
2452
2555
  },
2453
2556
  async push(locale, data, originalInput) {
2454
- if (isCacheRestore) {
2455
- return _lodash2.default.merge({}, data);
2456
- }
2457
- const result = _lodash2.default.merge({}, originalInput, data);
2557
+ const unlocalizableKeys = _getUnlocalizableKeys(originalInput);
2558
+ const result = _lodash2.default.merge(
2559
+ {},
2560
+ data,
2561
+ _lodash2.default.omitBy(originalInput, (_34, key) => !unlocalizableKeys.includes(key))
2562
+ );
2458
2563
  return result;
2459
2564
  }
2460
2565
  });
@@ -2465,6 +2570,27 @@ function _isSystemId(v) {
2465
2570
  function _isIsoDate(v) {
2466
2571
  return _datefns.isValid.call(void 0, _datefns.parseISO.call(void 0, v));
2467
2572
  }
2573
+ function _getUnlocalizableKeys(input2) {
2574
+ const rules = {
2575
+ isEmpty: (v) => _lodash2.default.isEmpty(v),
2576
+ isNumber: (v) => typeof v === "number" || /^[0-9]+$/.test(v),
2577
+ isBoolean: (v) => _lodash2.default.isBoolean(v),
2578
+ isIsoDate: (v) => _lodash2.default.isString(v) && _isIsoDate(v),
2579
+ isSystemId: (v) => _lodash2.default.isString(v) && _isSystemId(v),
2580
+ isUrl: (v) => _lodash2.default.isString(v) && _isurl2.default.call(void 0, v)
2581
+ };
2582
+ if (!input2) {
2583
+ return [];
2584
+ }
2585
+ return Object.entries(input2).filter(([key, value]) => {
2586
+ for (const [ruleName, rule] of Object.entries(rules)) {
2587
+ if (rule(value)) {
2588
+ return true;
2589
+ }
2590
+ }
2591
+ return false;
2592
+ }).map(([key, _34]) => key);
2593
+ }
2468
2594
 
2469
2595
  // src/cli/loaders/po/index.ts
2470
2596
 
@@ -2488,7 +2614,7 @@ function createPoDataLoader(params) {
2488
2614
  Object.entries(entries).forEach(([msgid, entry]) => {
2489
2615
  if (msgid && entry.msgid) {
2490
2616
  const context = entry.msgctxt || "";
2491
- const fullEntry = _optionalChain([parsedPo, 'access', _114 => _114.translations, 'access', _115 => _115[context], 'optionalAccess', _116 => _116[msgid]]);
2617
+ const fullEntry = _optionalChain([parsedPo, 'access', _121 => _121.translations, 'access', _122 => _122[context], 'optionalAccess', _123 => _123[msgid]]);
2492
2618
  if (fullEntry) {
2493
2619
  result[msgid] = fullEntry;
2494
2620
  }
@@ -2498,8 +2624,8 @@ function createPoDataLoader(params) {
2498
2624
  return result;
2499
2625
  },
2500
2626
  async push(locale, data, originalInput, originalLocale, pullInput) {
2501
- const currentSections = _optionalChain([pullInput, 'optionalAccess', _117 => _117.split, 'call', _118 => _118("\n\n"), 'access', _119 => _119.filter, 'call', _120 => _120(Boolean)]) || [];
2502
- const originalSections = _optionalChain([originalInput, 'optionalAccess', _121 => _121.split, 'call', _122 => _122("\n\n"), 'access', _123 => _123.filter, 'call', _124 => _124(Boolean)]) || [];
2627
+ const currentSections = _optionalChain([pullInput, 'optionalAccess', _124 => _124.split, 'call', _125 => _125("\n\n"), 'access', _126 => _126.filter, 'call', _127 => _127(Boolean)]) || [];
2628
+ const originalSections = _optionalChain([originalInput, 'optionalAccess', _128 => _128.split, 'call', _129 => _129("\n\n"), 'access', _130 => _130.filter, 'call', _131 => _131(Boolean)]) || [];
2503
2629
  const result = originalSections.map((section) => {
2504
2630
  const sectionPo = _gettextparser2.default.po.parse(section);
2505
2631
  if (Object.keys(sectionPo.translations).length === 0) {
@@ -2568,8 +2694,8 @@ function createPoContentLoader() {
2568
2694
  {
2569
2695
  ...entry,
2570
2696
  msgstr: [
2571
- _optionalChain([data, 'access', _125 => _125[entry.msgid], 'optionalAccess', _126 => _126.singular]),
2572
- _optionalChain([data, 'access', _127 => _127[entry.msgid], 'optionalAccess', _128 => _128.plural]) || null
2697
+ _optionalChain([data, 'access', _132 => _132[entry.msgid], 'optionalAccess', _133 => _133.singular]),
2698
+ _optionalChain([data, 'access', _134 => _134[entry.msgid], 'optionalAccess', _135 => _135.plural]) || null
2573
2699
  ].filter(Boolean)
2574
2700
  }
2575
2701
  ]).fromPairs().value();
@@ -2736,16 +2862,24 @@ function createDatoFilterLoader() {
2736
2862
  for (const [modelId, modelInfo] of _lodash2.default.entries(result)) {
2737
2863
  for (const record of modelInfo.records) {
2738
2864
  for (const [fieldId, fieldValue] of _lodash2.default.entries(record)) {
2739
- const fieldInfo = modelInfo.fields.find((field) => field.api_key === fieldId);
2865
+ const fieldInfo = modelInfo.fields.find(
2866
+ (field) => field.api_key === fieldId
2867
+ );
2740
2868
  if (fieldInfo) {
2741
2869
  const sourceFieldValue = _lodash2.default.get(fieldValue, [originalLocale]);
2742
- const targetFieldValue = _lodash2.default.get(data, [modelId, record.id, fieldId]);
2870
+ const targetFieldValue = _lodash2.default.get(data, [
2871
+ modelId,
2872
+ record.id,
2873
+ fieldId
2874
+ ]);
2743
2875
  if (targetFieldValue) {
2744
2876
  _lodash2.default.set(record, [fieldId, locale], targetFieldValue);
2745
2877
  } else {
2746
2878
  _lodash2.default.set(record, [fieldId, locale], sourceFieldValue);
2747
2879
  }
2748
- _lodash2.default.chain(fieldValue).keys().reject((loc) => loc === locale || loc === originalLocale).filter((loc) => _lodash2.default.isEmpty(_lodash2.default.get(fieldValue, [loc]))).forEach((loc) => _lodash2.default.set(record, [fieldId, loc], sourceFieldValue)).value();
2880
+ _lodash2.default.chain(fieldValue).keys().reject((loc) => loc === locale || loc === originalLocale).filter((loc) => _lodash2.default.isEmpty(_lodash2.default.get(fieldValue, [loc]))).forEach(
2881
+ (loc) => _lodash2.default.set(record, [fieldId, loc], sourceFieldValue)
2882
+ ).value();
2749
2883
  }
2750
2884
  }
2751
2885
  }
@@ -2763,7 +2897,9 @@ function createDatoFilterLoader() {
2763
2897
  var _cmaclientnode = require('@datocms/cma-client-node');
2764
2898
  function createDatoClient(params) {
2765
2899
  if (!params.apiKey) {
2766
- throw new Error("Missing required environment variable: DATO_API_TOKEN. Please set this variable and try again.");
2900
+ throw new Error(
2901
+ "Missing required environment variable: DATO_API_TOKEN. Please set this variable and try again."
2902
+ );
2767
2903
  }
2768
2904
  const dato = _cmaclientnode.buildClient.call(void 0, {
2769
2905
  apiToken: params.apiKey,
@@ -2810,11 +2946,16 @@ function createDatoClient(params) {
2810
2946
  findModels: async () => {
2811
2947
  try {
2812
2948
  const models = await dato.itemTypes.list();
2813
- const modelsWithoutBlocks = models.filter((model) => !model.modular_block);
2949
+ const modelsWithoutBlocks = models.filter(
2950
+ (model) => !model.modular_block
2951
+ );
2814
2952
  return modelsWithoutBlocks;
2815
2953
  } catch (_error) {
2816
2954
  throw new Error(
2817
- [`Failed to find models in DatoCMS.`, `Error: ${JSON.stringify(_error, null, 2)}`].join("\n\n")
2955
+ [
2956
+ `Failed to find models in DatoCMS.`,
2957
+ `Error: ${JSON.stringify(_error, null, 2)}`
2958
+ ].join("\n\n")
2818
2959
  );
2819
2960
  }
2820
2961
  },
@@ -2845,7 +2986,9 @@ function createDatoClient(params) {
2845
2986
  only_valid: "true",
2846
2987
  ids: !records.length ? void 0 : records.join(",")
2847
2988
  }
2848
- }).catch((error) => Promise.reject(_optionalChain([error, 'optionalAccess', _129 => _129.response, 'optionalAccess', _130 => _130.body, 'optionalAccess', _131 => _131.data, 'optionalAccess', _132 => _132[0]]) || error));
2989
+ }).catch(
2990
+ (error) => Promise.reject(_optionalChain([error, 'optionalAccess', _136 => _136.response, 'optionalAccess', _137 => _137.body, 'optionalAccess', _138 => _138.data, 'optionalAccess', _139 => _139[0]]) || error)
2991
+ );
2849
2992
  },
2850
2993
  findRecordsForModel: async (modelId, records) => {
2851
2994
  try {
@@ -2855,9 +2998,11 @@ function createDatoClient(params) {
2855
2998
  filter: {
2856
2999
  type: modelId,
2857
3000
  only_valid: "true",
2858
- ids: !_optionalChain([records, 'optionalAccess', _133 => _133.length]) ? void 0 : records.join(",")
3001
+ ids: !_optionalChain([records, 'optionalAccess', _140 => _140.length]) ? void 0 : records.join(",")
2859
3002
  }
2860
- }).catch((error) => Promise.reject(_optionalChain([error, 'optionalAccess', _134 => _134.response, 'optionalAccess', _135 => _135.body, 'optionalAccess', _136 => _136.data, 'optionalAccess', _137 => _137[0]]) || error));
3003
+ }).catch(
3004
+ (error) => Promise.reject(_optionalChain([error, 'optionalAccess', _141 => _141.response, 'optionalAccess', _142 => _142.body, 'optionalAccess', _143 => _143.data, 'optionalAccess', _144 => _144[0]]) || error)
3005
+ );
2861
3006
  return result;
2862
3007
  } catch (_error) {
2863
3008
  throw new Error(
@@ -2871,9 +3016,11 @@ function createDatoClient(params) {
2871
3016
  },
2872
3017
  updateRecord: async (id, payload) => {
2873
3018
  try {
2874
- await dato.items.update(id, payload).catch((error) => Promise.reject(_optionalChain([error, 'optionalAccess', _138 => _138.response, 'optionalAccess', _139 => _139.body, 'optionalAccess', _140 => _140.data, 'optionalAccess', _141 => _141[0]]) || error));
3019
+ await dato.items.update(id, payload).catch(
3020
+ (error) => Promise.reject(_optionalChain([error, 'optionalAccess', _145 => _145.response, 'optionalAccess', _146 => _146.body, 'optionalAccess', _147 => _147.data, 'optionalAccess', _148 => _148[0]]) || error)
3021
+ );
2875
3022
  } catch (_error) {
2876
- if (_optionalChain([_error, 'optionalAccess', _142 => _142.attributes, 'optionalAccess', _143 => _143.details, 'optionalAccess', _144 => _144.message])) {
3023
+ if (_optionalChain([_error, 'optionalAccess', _149 => _149.attributes, 'optionalAccess', _150 => _150.details, 'optionalAccess', _151 => _151.message])) {
2877
3024
  throw new Error(
2878
3025
  [
2879
3026
  `${_error.attributes.details.message}`,
@@ -2894,9 +3041,11 @@ function createDatoClient(params) {
2894
3041
  },
2895
3042
  enableFieldLocalization: async (args) => {
2896
3043
  try {
2897
- await dato.fields.update(`${args.modelId}::${args.fieldId}`, { localized: true }).catch((error) => Promise.reject(_optionalChain([error, 'optionalAccess', _145 => _145.response, 'optionalAccess', _146 => _146.body, 'optionalAccess', _147 => _147.data, 'optionalAccess', _148 => _148[0]]) || error));
3044
+ await dato.fields.update(`${args.modelId}::${args.fieldId}`, { localized: true }).catch(
3045
+ (error) => Promise.reject(_optionalChain([error, 'optionalAccess', _152 => _152.response, 'optionalAccess', _153 => _153.body, 'optionalAccess', _154 => _154.data, 'optionalAccess', _155 => _155[0]]) || error)
3046
+ );
2898
3047
  } catch (_error) {
2899
- if (_optionalChain([_error, 'optionalAccess', _149 => _149.attributes, 'optionalAccess', _150 => _150.code]) === "NOT_FOUND") {
3048
+ if (_optionalChain([_error, 'optionalAccess', _156 => _156.attributes, 'optionalAccess', _157 => _157.code]) === "NOT_FOUND") {
2900
3049
  throw new Error(
2901
3050
  [
2902
3051
  `Field "${args.fieldId}" not found in model "${args.modelId}".`,
@@ -2904,9 +3053,12 @@ function createDatoClient(params) {
2904
3053
  ].join("\n\n")
2905
3054
  );
2906
3055
  }
2907
- if (_optionalChain([_error, 'optionalAccess', _151 => _151.attributes, 'optionalAccess', _152 => _152.details, 'optionalAccess', _153 => _153.message])) {
3056
+ if (_optionalChain([_error, 'optionalAccess', _158 => _158.attributes, 'optionalAccess', _159 => _159.details, 'optionalAccess', _160 => _160.message])) {
2908
3057
  throw new Error(
2909
- [`${_error.attributes.details.message}`, `Error: ${JSON.stringify(_error, null, 2)}`].join("\n\n")
3058
+ [
3059
+ `${_error.attributes.details.message}`,
3060
+ `Error: ${JSON.stringify(_error, null, 2)}`
3061
+ ].join("\n\n")
2910
3062
  );
2911
3063
  }
2912
3064
  throw new Error(
@@ -2958,9 +3110,16 @@ function createDatoApiLoader(config, onConfigUpdate) {
2958
3110
  result.models[modelId] = { fields: [], records: [] };
2959
3111
  const fieldInfos = await getFieldDetails(dato, fields);
2960
3112
  const fieldChoices = createFieldChoices(fieldInfos);
2961
- const selectedFields = await promptFieldSelection(modelName, fieldChoices);
3113
+ const selectedFields = await promptFieldSelection(
3114
+ modelName,
3115
+ fieldChoices
3116
+ );
2962
3117
  for (const fieldInfo of fieldInfos) {
2963
- const isLocalized = await updateFieldLocalization(dato, fieldInfo, selectedFields.includes(fieldInfo.id));
3118
+ const isLocalized = await updateFieldLocalization(
3119
+ dato,
3120
+ fieldInfo,
3121
+ selectedFields.includes(fieldInfo.id)
3122
+ );
2964
3123
  if (isLocalized) {
2965
3124
  result.models[modelId].fields.push(fieldInfo);
2966
3125
  updatedConfig.models[modelId].fields = _lodash2.default.uniq([
@@ -2970,9 +3129,18 @@ function createDatoApiLoader(config, onConfigUpdate) {
2970
3129
  }
2971
3130
  }
2972
3131
  const records = await dato.findRecordsForModel(modelId);
2973
- const recordChoices = createRecordChoices(records, _optionalChain([config, 'access', _154 => _154.models, 'access', _155 => _155[modelId], 'optionalAccess', _156 => _156.records]) || [], project);
2974
- const selectedRecords = await promptRecordSelection(modelName, recordChoices);
2975
- result.models[modelId].records = records.filter((record) => selectedRecords.includes(record.id));
3132
+ const recordChoices = createRecordChoices(
3133
+ records,
3134
+ _optionalChain([config, 'access', _161 => _161.models, 'access', _162 => _162[modelId], 'optionalAccess', _163 => _163.records]) || [],
3135
+ project
3136
+ );
3137
+ const selectedRecords = await promptRecordSelection(
3138
+ modelName,
3139
+ recordChoices
3140
+ );
3141
+ result.models[modelId].records = records.filter(
3142
+ (record) => selectedRecords.includes(record.id)
3143
+ );
2976
3144
  updatedConfig.models[modelId].records = selectedRecords;
2977
3145
  }
2978
3146
  }
@@ -2982,14 +3150,14 @@ function createDatoApiLoader(config, onConfigUpdate) {
2982
3150
  },
2983
3151
  async pull(locale, input2, initCtx) {
2984
3152
  const result = {};
2985
- for (const modelId of _lodash2.default.keys(_optionalChain([initCtx, 'optionalAccess', _157 => _157.models]) || {})) {
2986
- let records = _optionalChain([initCtx, 'optionalAccess', _158 => _158.models, 'access', _159 => _159[modelId], 'access', _160 => _160.records]) || [];
3153
+ for (const modelId of _lodash2.default.keys(_optionalChain([initCtx, 'optionalAccess', _164 => _164.models]) || {})) {
3154
+ let records = _optionalChain([initCtx, 'optionalAccess', _165 => _165.models, 'access', _166 => _166[modelId], 'access', _167 => _167.records]) || [];
2987
3155
  const recordIds = records.map((record) => record.id);
2988
3156
  records = await dato.findRecords(recordIds);
2989
3157
  console.log(`Fetched ${records.length} records for model ${modelId}`);
2990
3158
  if (records.length > 0) {
2991
3159
  result[modelId] = {
2992
- fields: _optionalChain([initCtx, 'optionalAccess', _161 => _161.models, 'optionalAccess', _162 => _162[modelId], 'optionalAccess', _163 => _163.fields]) || [],
3160
+ fields: _optionalChain([initCtx, 'optionalAccess', _168 => _168.models, 'optionalAccess', _169 => _169[modelId], 'optionalAccess', _170 => _170.fields]) || [],
2993
3161
  records
2994
3162
  };
2995
3163
  }
@@ -3000,7 +3168,9 @@ function createDatoApiLoader(config, onConfigUpdate) {
3000
3168
  for (const modelId of _lodash2.default.keys(data)) {
3001
3169
  for (let i = 0; i < data[modelId].records.length; i++) {
3002
3170
  const record = data[modelId].records[i];
3003
- console.log(`Updating record ${i + 1}/${data[modelId].records.length} for model ${modelId}...`);
3171
+ console.log(
3172
+ `Updating record ${i + 1}/${data[modelId].records.length} for model ${modelId}...`
3173
+ );
3004
3174
  await dato.updateRecord(record.id, record);
3005
3175
  }
3006
3176
  }
@@ -3039,7 +3209,9 @@ async function promptFieldSelection(modelName, choices) {
3039
3209
  }
3040
3210
  async function updateFieldLocalization(dato, fieldInfo, shouldBeLocalized) {
3041
3211
  if (shouldBeLocalized !== fieldInfo.localized) {
3042
- console.log(`${shouldBeLocalized ? "Enabling" : "Disabling"} localization for ${fieldInfo.label}...`);
3212
+ console.log(
3213
+ `${shouldBeLocalized ? "Enabling" : "Disabling"} localization for ${fieldInfo.label}...`
3214
+ );
3043
3215
  await dato.updateField(fieldInfo.id, { localized: shouldBeLocalized });
3044
3216
  }
3045
3217
  return shouldBeLocalized;
@@ -3048,7 +3220,7 @@ function createRecordChoices(records, selectedIds = [], project) {
3048
3220
  return records.map((record) => ({
3049
3221
  name: `${record.id} - https://${project.internal_domain}/editor/item_types/${record.item_type.id}/items/${record.id}`,
3050
3222
  value: record.id,
3051
- checked: _optionalChain([selectedIds, 'optionalAccess', _164 => _164.includes, 'call', _165 => _165(record.id)])
3223
+ checked: _optionalChain([selectedIds, 'optionalAccess', _171 => _171.includes, 'call', _172 => _172(record.id)])
3052
3224
  }));
3053
3225
  }
3054
3226
  async function promptRecordSelection(modelName, choices) {
@@ -3112,9 +3284,21 @@ function createDatoExtractLoader() {
3112
3284
  for (const [virtualRecordId, record] of _lodash2.default.entries(modelInfo)) {
3113
3285
  for (const [fieldName, fieldValue] of _lodash2.default.entries(record)) {
3114
3286
  const [, recordId] = virtualRecordId.split("_");
3115
- const originalFieldValue = _lodash2.default.get(originalInput, [modelId, recordId, fieldName]);
3116
- const rawValue = createRawDatoValue(fieldValue, originalFieldValue, true);
3117
- _lodash2.default.set(result, [modelId, recordId, fieldName], rawValue || originalFieldValue);
3287
+ const originalFieldValue = _lodash2.default.get(originalInput, [
3288
+ modelId,
3289
+ recordId,
3290
+ fieldName
3291
+ ]);
3292
+ const rawValue = createRawDatoValue(
3293
+ fieldValue,
3294
+ originalFieldValue,
3295
+ true
3296
+ );
3297
+ _lodash2.default.set(
3298
+ result,
3299
+ [modelId, recordId, fieldName],
3300
+ rawValue || originalFieldValue
3301
+ );
3118
3302
  }
3119
3303
  }
3120
3304
  }
@@ -3184,7 +3368,11 @@ function createRawDatoValue(parsedDatoValue, originalRawDatoValue, isClean = fal
3184
3368
  case "single_block":
3185
3369
  return deserializeBlock(parsedDatoValue, originalRawDatoValue, isClean);
3186
3370
  case "rich_text":
3187
- return deserializeBlockList(parsedDatoValue, originalRawDatoValue, isClean);
3371
+ return deserializeBlockList(
3372
+ parsedDatoValue,
3373
+ originalRawDatoValue,
3374
+ isClean
3375
+ );
3188
3376
  case "json":
3189
3377
  return JSON.stringify(parsedDatoValue, null, 2);
3190
3378
  case "video":
@@ -3201,7 +3389,11 @@ function serializeStructuredText(rawStructuredText) {
3201
3389
  return serializeStructuredTextNode(rawStructuredText);
3202
3390
  function serializeStructuredTextNode(node, path17 = [], acc = {}) {
3203
3391
  if ("document" in node) {
3204
- return serializeStructuredTextNode(node.document, [...path17, "document"], acc);
3392
+ return serializeStructuredTextNode(
3393
+ node.document,
3394
+ [...path17, "document"],
3395
+ acc
3396
+ );
3205
3397
  }
3206
3398
  if (!_lodash2.default.isNil(node.value)) {
3207
3399
  acc[[...path17, "value"].join(".")] = node.value;
@@ -3210,7 +3402,11 @@ function serializeStructuredText(rawStructuredText) {
3210
3402
  }
3211
3403
  if (node.children) {
3212
3404
  for (let i = 0; i < node.children.length; i++) {
3213
- serializeStructuredTextNode(node.children[i], [...path17, i.toString()], acc);
3405
+ serializeStructuredTextNode(
3406
+ node.children[i],
3407
+ [...path17, i.toString()],
3408
+ acc
3409
+ );
3214
3410
  }
3215
3411
  }
3216
3412
  return acc;
@@ -3253,7 +3449,11 @@ function deserializeVideo(parsedVideo, originalRawVideo) {
3253
3449
  function deserializeBlock(payload, rawNode, isClean = false) {
3254
3450
  const result = _lodash2.default.cloneDeep(rawNode);
3255
3451
  for (const [attributeName, attributeValue] of _lodash2.default.entries(rawNode.attributes)) {
3256
- const rawValue = createRawDatoValue(payload[attributeName], attributeValue, isClean);
3452
+ const rawValue = createRawDatoValue(
3453
+ payload[attributeName],
3454
+ attributeValue,
3455
+ isClean
3456
+ );
3257
3457
  _lodash2.default.set(result, ["attributes", attributeName], rawValue);
3258
3458
  }
3259
3459
  if (isClean) {
@@ -3265,13 +3465,19 @@ function deserializeSeo(parsedSeo, originalRawSeo) {
3265
3465
  return _lodash2.default.chain(parsedSeo).pick(["title", "description"]).defaults(originalRawSeo).value();
3266
3466
  }
3267
3467
  function deserializeBlockList(parsedBlockList, originalRawBlockList, isClean = false) {
3268
- return _lodash2.default.chain(parsedBlockList).map((block, i) => deserializeBlock(block, originalRawBlockList[i], isClean)).value();
3468
+ return _lodash2.default.chain(parsedBlockList).map(
3469
+ (block, i) => deserializeBlock(block, originalRawBlockList[i], isClean)
3470
+ ).value();
3269
3471
  }
3270
3472
  function deserializeStructuredText(parsedStructuredText, originalRawStructuredText) {
3271
3473
  const result = _lodash2.default.cloneDeep(originalRawStructuredText);
3272
3474
  for (const [path17, value] of _lodash2.default.entries(parsedStructuredText)) {
3273
3475
  const realPath = _lodash2.default.chain(path17.split(".")).flatMap((s) => !_lodash2.default.isNaN(_lodash2.default.toNumber(s)) ? ["children", s] : s).value();
3274
- const deserializedValue = createRawDatoValue(value, _lodash2.default.get(originalRawStructuredText, realPath), true);
3476
+ const deserializedValue = createRawDatoValue(
3477
+ value,
3478
+ _lodash2.default.get(originalRawStructuredText, realPath),
3479
+ true
3480
+ );
3275
3481
  _lodash2.default.set(result, realPath, deserializedValue);
3276
3482
  }
3277
3483
  return result;
@@ -3284,13 +3490,21 @@ function _isJson(rawDatoValue) {
3284
3490
  }
3285
3491
  }
3286
3492
  function _isFile(rawDatoValue) {
3287
- return _lodash2.default.isObject(rawDatoValue) && ["alt", "title", "custom_data", "focal_point", "upload_id"].every((key) => _lodash2.default.has(rawDatoValue, key));
3288
- }
3289
- function _isVideo(rawDatoValue) {
3290
- return _lodash2.default.isObject(rawDatoValue) && ["url", "title", "width", "height", "provider", "provider_uid", "thumbnail_url"].every(
3493
+ return _lodash2.default.isObject(rawDatoValue) && ["alt", "title", "custom_data", "focal_point", "upload_id"].every(
3291
3494
  (key) => _lodash2.default.has(rawDatoValue, key)
3292
3495
  );
3293
3496
  }
3497
+ function _isVideo(rawDatoValue) {
3498
+ return _lodash2.default.isObject(rawDatoValue) && [
3499
+ "url",
3500
+ "title",
3501
+ "width",
3502
+ "height",
3503
+ "provider",
3504
+ "provider_uid",
3505
+ "thumbnail_url"
3506
+ ].every((key) => _lodash2.default.has(rawDatoValue, key));
3507
+ }
3294
3508
 
3295
3509
  // src/cli/loaders/dato/index.ts
3296
3510
  function createDatoLoader(configFilePath) {
@@ -3300,13 +3514,20 @@ function createDatoLoader(configFilePath) {
3300
3514
  return composeLoaders(
3301
3515
  createDatoApiLoader(
3302
3516
  datoConfig,
3303
- (updatedConfig) => fs10.default.writeFileSync(configFilePath, _json52.default.stringify(updatedConfig, null, 2))
3517
+ (updatedConfig) => fs10.default.writeFileSync(
3518
+ configFilePath,
3519
+ _json52.default.stringify(updatedConfig, null, 2)
3520
+ )
3304
3521
  ),
3305
3522
  createDatoFilterLoader(),
3306
3523
  createDatoExtractLoader()
3307
3524
  );
3308
3525
  } catch (error) {
3309
- throw new Error([`Failed to parse DatoCMS config file.`, `Error: ${error.message}`].join("\n\n"));
3526
+ throw new Error(
3527
+ [`Failed to parse DatoCMS config file.`, `Error: ${error.message}`].join(
3528
+ "\n\n"
3529
+ )
3530
+ );
3310
3531
  }
3311
3532
  }
3312
3533
 
@@ -3318,7 +3539,7 @@ function createVttLoader() {
3318
3539
  if (!input2) {
3319
3540
  return "";
3320
3541
  }
3321
- const vtt = _optionalChain([_nodewebvtt2.default, 'access', _166 => _166.parse, 'call', _167 => _167(input2), 'optionalAccess', _168 => _168.cues]);
3542
+ const vtt = _optionalChain([_nodewebvtt2.default, 'access', _173 => _173.parse, 'call', _174 => _174(input2), 'optionalAccess', _175 => _175.cues]);
3322
3543
  if (Object.keys(vtt).length === 0) {
3323
3544
  return {};
3324
3545
  } else {
@@ -3372,7 +3593,7 @@ function variableExtractLoader(params) {
3372
3593
  for (let i = 0; i < matches.length; i++) {
3373
3594
  const match2 = matches[i];
3374
3595
  const currentValue = result[key].value;
3375
- const newValue = _optionalChain([currentValue, 'optionalAccess', _169 => _169.replace, 'call', _170 => _170(match2, `{variable:${i}}`)]);
3596
+ const newValue = _optionalChain([currentValue, 'optionalAccess', _176 => _176.replace, 'call', _177 => _177(match2, `{variable:${i}}`)]);
3376
3597
  result[key].value = newValue;
3377
3598
  result[key].variables[i] = match2;
3378
3599
  }
@@ -3386,7 +3607,7 @@ function variableExtractLoader(params) {
3386
3607
  for (let i = 0; i < valueObj.variables.length; i++) {
3387
3608
  const variable = valueObj.variables[i];
3388
3609
  const currentValue = result[key];
3389
- const newValue = _optionalChain([currentValue, 'optionalAccess', _171 => _171.replace, 'call', _172 => _172(`{variable:${i}}`, variable)]);
3610
+ const newValue = _optionalChain([currentValue, 'optionalAccess', _178 => _178.replace, 'call', _179 => _179(`{variable:${i}}`, variable)]);
3390
3611
  result[key] = newValue;
3391
3612
  }
3392
3613
  }
@@ -3455,7 +3676,9 @@ function formatPlutilStyle(jsonData, existingJson) {
3455
3676
  }
3456
3677
  if (Array.isArray(data)) {
3457
3678
  if (data.length === 0) return "[]";
3458
- const items2 = data.map((item) => `${nextIndent}${format(item, level + 1)}`);
3679
+ const items2 = data.map(
3680
+ (item) => `${nextIndent}${format(item, level + 1)}`
3681
+ );
3459
3682
  return `[
3460
3683
  ${items2.join(",\n")}
3461
3684
  ${currentIndent}]`;
@@ -3475,7 +3698,10 @@ ${currentIndent}}`;
3475
3698
  });
3476
3699
  const items = sortedKeys.map((key) => {
3477
3700
  const value = data[key];
3478
- return `${nextIndent}${JSON.stringify(key)} : ${format(value, level + 1)}`;
3701
+ return `${nextIndent}${JSON.stringify(key)} : ${format(
3702
+ value,
3703
+ level + 1
3704
+ )}`;
3479
3705
  });
3480
3706
  return `{
3481
3707
  ${items.join(",\n")}
@@ -3548,11 +3774,23 @@ function toPhpArray(data, shortSyntax = true, indentLevel = 1) {
3548
3774
  const arrayEnd = shortSyntax ? "]" : ")";
3549
3775
  if (Array.isArray(data)) {
3550
3776
  return `${arrayStart}
3551
- ${data.map((value) => `${indent(indentLevel)}${toPhpArray(value, shortSyntax, indentLevel + 1)}`).join(",\n")}
3777
+ ${data.map(
3778
+ (value) => `${indent(indentLevel)}${toPhpArray(
3779
+ value,
3780
+ shortSyntax,
3781
+ indentLevel + 1
3782
+ )}`
3783
+ ).join(",\n")}
3552
3784
  ${indent(indentLevel - 1)}${arrayEnd}`;
3553
3785
  }
3554
3786
  const output = `${arrayStart}
3555
- ${Object.entries(data).map(([key, value]) => `${indent(indentLevel)}'${key}' => ${toPhpArray(value, shortSyntax, indentLevel + 1)}`).join(",\n")}
3787
+ ${Object.entries(data).map(
3788
+ ([key, value]) => `${indent(indentLevel)}'${key}' => ${toPhpArray(
3789
+ value,
3790
+ shortSyntax,
3791
+ indentLevel + 1
3792
+ )}`
3793
+ ).join(",\n")}
3556
3794
  ${indent(indentLevel - 1)}${arrayEnd}`;
3557
3795
  return output;
3558
3796
  }
@@ -3569,7 +3807,7 @@ function createVueJsonLoader() {
3569
3807
  return createLoader({
3570
3808
  pull: async (locale, input2, ctx) => {
3571
3809
  const parsed = parseVueFile(input2);
3572
- return _nullishCoalesce(_optionalChain([parsed, 'optionalAccess', _173 => _173.i18n, 'optionalAccess', _174 => _174[locale]]), () => ( {}));
3810
+ return _nullishCoalesce(_optionalChain([parsed, 'optionalAccess', _180 => _180.i18n, 'optionalAccess', _181 => _181[locale]]), () => ( {}));
3573
3811
  },
3574
3812
  push: async (locale, data, originalInput) => {
3575
3813
  const parsed = parseVueFile(_nullishCoalesce(originalInput, () => ( "")));
@@ -3578,7 +3816,11 @@ function createVueJsonLoader() {
3578
3816
  }
3579
3817
  parsed.i18n[locale] = data;
3580
3818
  return `${parsed.before}<i18n>
3581
- ${JSON.stringify(parsed.i18n, null, 2)}
3819
+ ${JSON.stringify(
3820
+ parsed.i18n,
3821
+ null,
3822
+ 2
3823
+ )}
3582
3824
  </i18n>${parsed.after}`;
3583
3825
  }
3584
3826
  });
@@ -3750,7 +3992,7 @@ function updateStringsInObjectExpression(objectExpression, data) {
3750
3992
  objectExpression.properties.forEach((prop) => {
3751
3993
  if (!t.isObjectProperty(prop)) return;
3752
3994
  const key = getPropertyKey(prop);
3753
- const incomingVal = _optionalChain([data, 'optionalAccess', _175 => _175[key]]);
3995
+ const incomingVal = _optionalChain([data, 'optionalAccess', _182 => _182[key]]);
3754
3996
  if (incomingVal === void 0) {
3755
3997
  return;
3756
3998
  }
@@ -3786,7 +4028,7 @@ function updateStringsInArrayExpression(arrayExpression, incoming) {
3786
4028
  let modified = false;
3787
4029
  arrayExpression.elements.forEach((element, index) => {
3788
4030
  if (!element) return;
3789
- const incomingVal = _optionalChain([incoming, 'optionalAccess', _176 => _176[index]]);
4031
+ const incomingVal = _optionalChain([incoming, 'optionalAccess', _183 => _183[index]]);
3790
4032
  if (incomingVal === void 0) return;
3791
4033
  if (t.isStringLiteral(element) && typeof incomingVal === "string") {
3792
4034
  if (element.value !== incomingVal) {
@@ -3844,42 +4086,48 @@ function createInjectLocaleLoader(injectLocaleKeys) {
3844
4086
  if (!injectLocaleKeys) {
3845
4087
  return data;
3846
4088
  }
3847
- const omitKeys = injectLocaleKeys.filter((key) => {
3848
- return _lodash2.default.get(data, key) === locale;
3849
- });
4089
+ const omitKeys = _getKeysWithLocales(data, injectLocaleKeys, locale);
3850
4090
  const result = _lodash2.default.omit(data, omitKeys);
3851
4091
  return result;
3852
4092
  },
3853
4093
  async push(locale, data, originalInput, originalLocale) {
3854
- if (!injectLocaleKeys) {
4094
+ if (!injectLocaleKeys || !originalInput) {
3855
4095
  return data;
3856
4096
  }
3857
- const mergedData = _lodash2.default.merge({}, originalInput, data);
3858
- injectLocaleKeys.forEach((key) => {
3859
- if (_lodash2.default.get(mergedData, key) === originalLocale) {
3860
- _lodash2.default.set(mergedData, key, locale);
3861
- }
4097
+ const localeKeys = _getKeysWithLocales(
4098
+ originalInput,
4099
+ injectLocaleKeys,
4100
+ originalLocale
4101
+ );
4102
+ localeKeys.forEach((key) => {
4103
+ _lodash2.default.set(data, key, locale);
3862
4104
  });
3863
- return mergedData;
4105
+ return data;
3864
4106
  }
3865
4107
  });
3866
4108
  }
4109
+ function _getKeysWithLocales(data, injectLocaleKeys, locale) {
4110
+ return injectLocaleKeys.filter((key) => {
4111
+ return _lodash2.default.get(data, key) === locale;
4112
+ });
4113
+ }
3867
4114
 
3868
4115
  // src/cli/loaders/locked-keys.ts
3869
4116
 
3870
- function createLockedKeysLoader(lockedKeys, isCacheRestore = false) {
4117
+ function createLockedKeysLoader(lockedKeys) {
3871
4118
  return createLoader({
3872
- pull: async (locale, data) => _lodash2.default.chain(data).pickBy((value, key) => !lockedKeys.some((lockedKey) => key.startsWith(lockedKey))).value(),
4119
+ pull: async (locale, data) => {
4120
+ return _lodash2.default.pickBy(data, (value, key) => !_isLockedKey(key, lockedKeys));
4121
+ },
3873
4122
  push: async (locale, data, originalInput) => {
3874
- const lockedSubObject = _lodash2.default.chain(originalInput).pickBy((value, key) => lockedKeys.some((lockedKey) => key.startsWith(lockedKey))).value();
3875
- if (isCacheRestore) {
3876
- return _lodash2.default.merge({}, data, lockedSubObject);
3877
- } else {
3878
- return _lodash2.default.merge({}, originalInput, data, lockedSubObject);
3879
- }
4123
+ const lockedSubObject = _lodash2.default.chain(originalInput).pickBy((value, key) => _isLockedKey(key, lockedKeys)).value();
4124
+ return _lodash2.default.merge({}, data, lockedSubObject);
3880
4125
  }
3881
4126
  });
3882
4127
  }
4128
+ function _isLockedKey(key, lockedKeys) {
4129
+ return lockedKeys.some((lockedKey) => key.startsWith(lockedKey));
4130
+ }
3883
4131
 
3884
4132
  // src/cli/loaders/mdx2/frontmatter-split.ts
3885
4133
 
@@ -4062,7 +4310,7 @@ function createMdxSectionsSplit2Loader() {
4062
4310
  const content = _lodash2.default.chain(data.sections).values().join("\n\n").value();
4063
4311
  const result = {
4064
4312
  frontmatter: data.frontmatter,
4065
- codePlaceholders: _optionalChain([pullInput, 'optionalAccess', _177 => _177.codePlaceholders]) || {},
4313
+ codePlaceholders: _optionalChain([pullInput, 'optionalAccess', _184 => _184.codePlaceholders]) || {},
4066
4314
  content
4067
4315
  };
4068
4316
  return result;
@@ -4109,9 +4357,14 @@ function createMdxLockedPatternsLoader(defaultPatterns) {
4109
4357
  if (!pullInput) {
4110
4358
  return data;
4111
4359
  }
4112
- const { lockedPlaceholders } = extractLockedPatterns(pullInput, patterns);
4360
+ const { lockedPlaceholders } = extractLockedPatterns(
4361
+ pullInput,
4362
+ patterns
4363
+ );
4113
4364
  let result = data;
4114
- for (const [placeholder, original] of Object.entries(lockedPlaceholders)) {
4365
+ for (const [placeholder, original] of Object.entries(
4366
+ lockedPlaceholders
4367
+ )) {
4115
4368
  result = result.replaceAll(placeholder, original);
4116
4369
  }
4117
4370
  return result;
@@ -4205,7 +4458,10 @@ function parseEjsForTranslation(input2) {
4205
4458
  if (trimmedContent) {
4206
4459
  const key = `text_${counter++}`;
4207
4460
  translatable[key] = trimmedContent;
4208
- template += textPart.content.replace(trimmedContent, `__LINGO_PLACEHOLDER_${key}__`);
4461
+ template += textPart.content.replace(
4462
+ trimmedContent,
4463
+ `__LINGO_PLACEHOLDER_${key}__`
4464
+ );
4209
4465
  } else {
4210
4466
  template += textPart.content;
4211
4467
  }
@@ -4235,7 +4491,9 @@ function createEjsLoader() {
4235
4491
  const parseResult = parseEjsForTranslation(input2);
4236
4492
  return parseResult.translatable;
4237
4493
  } catch (error) {
4238
- console.warn("Warning: Could not parse EJS template, treating as plain text");
4494
+ console.warn(
4495
+ "Warning: Could not parse EJS template, treating as plain text"
4496
+ );
4239
4497
  return { content: input2.trim() };
4240
4498
  }
4241
4499
  },
@@ -4246,15 +4504,51 @@ function createEjsLoader() {
4246
4504
  try {
4247
4505
  const parseResult = parseEjsForTranslation(originalInput);
4248
4506
  const mergedTranslatable = { ...parseResult.translatable, ...data };
4249
- return reconstructEjsWithTranslation(parseResult.content, mergedTranslatable);
4507
+ return reconstructEjsWithTranslation(
4508
+ parseResult.content,
4509
+ mergedTranslatable
4510
+ );
4250
4511
  } catch (error) {
4251
- console.warn("Warning: Could not reconstruct EJS template, returning translated data");
4512
+ console.warn(
4513
+ "Warning: Could not reconstruct EJS template, returning translated data"
4514
+ );
4252
4515
  return Object.values(data).join("\n");
4253
4516
  }
4254
4517
  }
4255
4518
  });
4256
4519
  }
4257
4520
 
4521
+ // src/cli/loaders/ensure-key-order.ts
4522
+
4523
+ function createEnsureKeyOrderLoader() {
4524
+ return createLoader({
4525
+ pull: async (_locale, input2) => {
4526
+ return input2;
4527
+ },
4528
+ push: async (_locale, data, originalInput) => {
4529
+ if (!originalInput || !data) {
4530
+ return data;
4531
+ }
4532
+ return reorderKeys(data, originalInput);
4533
+ }
4534
+ });
4535
+ }
4536
+ function reorderKeys(data, originalInput) {
4537
+ if (!_lodash2.default.isObject(data) || _lodash2.default.isArray(data) || _lodash2.default.isDate(data)) {
4538
+ return data;
4539
+ }
4540
+ const orderedData = {};
4541
+ const originalKeys = Object.keys(originalInput);
4542
+ const dataKeys = new Set(Object.keys(data));
4543
+ for (const key of originalKeys) {
4544
+ if (dataKeys.has(key)) {
4545
+ orderedData[key] = reorderKeys(data[key], originalInput[key]);
4546
+ dataKeys.delete(key);
4547
+ }
4548
+ }
4549
+ return orderedData;
4550
+ }
4551
+
4258
4552
  // src/cli/loaders/index.ts
4259
4553
  function createBucketLoader(bucketType, bucketPathPattern, options, lockedKeys, lockedPatterns, ignoredKeys) {
4260
4554
  switch (bucketType) {
@@ -4264,23 +4558,19 @@ function createBucketLoader(bucketType, bucketPathPattern, options, lockedKeys,
4264
4558
  return composeLoaders(
4265
4559
  createTextFileLoader(bucketPathPattern),
4266
4560
  createAndroidLoader(),
4561
+ createEnsureKeyOrderLoader(),
4267
4562
  createFlatLoader(),
4268
4563
  createSyncLoader(),
4269
- createUnlocalizableLoader(
4270
- options.isCacheRestore,
4271
- options.returnUnlocalizedKeys
4272
- )
4564
+ createUnlocalizableLoader(options.returnUnlocalizedKeys)
4273
4565
  );
4274
4566
  case "csv":
4275
4567
  return composeLoaders(
4276
4568
  createTextFileLoader(bucketPathPattern),
4277
4569
  createCsvLoader(),
4570
+ createEnsureKeyOrderLoader(),
4278
4571
  createFlatLoader(),
4279
4572
  createSyncLoader(),
4280
- createUnlocalizableLoader(
4281
- options.isCacheRestore,
4282
- options.returnUnlocalizedKeys
4283
- )
4573
+ createUnlocalizableLoader(options.returnUnlocalizedKeys)
4284
4574
  );
4285
4575
  case "html":
4286
4576
  return composeLoaders(
@@ -4288,34 +4578,26 @@ function createBucketLoader(bucketType, bucketPathPattern, options, lockedKeys,
4288
4578
  createPrettierLoader({ parser: "html", bucketPathPattern }),
4289
4579
  createHtmlLoader(),
4290
4580
  createSyncLoader(),
4291
- createUnlocalizableLoader(
4292
- options.isCacheRestore,
4293
- options.returnUnlocalizedKeys
4294
- )
4581
+ createUnlocalizableLoader(options.returnUnlocalizedKeys)
4295
4582
  );
4296
4583
  case "ejs":
4297
4584
  return composeLoaders(
4298
4585
  createTextFileLoader(bucketPathPattern),
4299
4586
  createEjsLoader(),
4300
4587
  createSyncLoader(),
4301
- createUnlocalizableLoader(
4302
- options.isCacheRestore,
4303
- options.returnUnlocalizedKeys
4304
- )
4588
+ createUnlocalizableLoader(options.returnUnlocalizedKeys)
4305
4589
  );
4306
4590
  case "json":
4307
4591
  return composeLoaders(
4308
4592
  createTextFileLoader(bucketPathPattern),
4309
4593
  createPrettierLoader({ parser: "json", bucketPathPattern }),
4310
4594
  createJsonLoader(),
4595
+ createEnsureKeyOrderLoader(),
4311
4596
  createInjectLocaleLoader(options.injectLocale),
4312
4597
  createFlatLoader(),
4313
- createLockedKeysLoader(lockedKeys || [], options.isCacheRestore),
4598
+ createLockedKeysLoader(lockedKeys || []),
4314
4599
  createSyncLoader(),
4315
- createUnlocalizableLoader(
4316
- options.isCacheRestore,
4317
- options.returnUnlocalizedKeys
4318
- )
4600
+ createUnlocalizableLoader(options.returnUnlocalizedKeys)
4319
4601
  );
4320
4602
  case "markdown":
4321
4603
  return composeLoaders(
@@ -4323,10 +4605,7 @@ function createBucketLoader(bucketType, bucketPathPattern, options, lockedKeys,
4323
4605
  createPrettierLoader({ parser: "markdown", bucketPathPattern }),
4324
4606
  createMarkdownLoader(),
4325
4607
  createSyncLoader(),
4326
- createUnlocalizableLoader(
4327
- options.isCacheRestore,
4328
- options.returnUnlocalizedKeys
4329
- )
4608
+ createUnlocalizableLoader(options.returnUnlocalizedKeys)
4330
4609
  );
4331
4610
  case "mdx":
4332
4611
  return composeLoaders(
@@ -4341,55 +4620,43 @@ function createBucketLoader(bucketType, bucketPathPattern, options, lockedKeys,
4341
4620
  createMdxSectionsSplit2Loader(),
4342
4621
  createLocalizableMdxDocumentLoader(),
4343
4622
  createFlatLoader(),
4344
- createLockedKeysLoader(lockedKeys || [], options.isCacheRestore),
4623
+ createEnsureKeyOrderLoader(),
4624
+ createLockedKeysLoader(lockedKeys || []),
4345
4625
  createSyncLoader(),
4346
- createUnlocalizableLoader(
4347
- options.isCacheRestore,
4348
- options.returnUnlocalizedKeys
4349
- )
4626
+ createUnlocalizableLoader(options.returnUnlocalizedKeys)
4350
4627
  );
4351
4628
  case "po":
4352
4629
  return composeLoaders(
4353
4630
  createTextFileLoader(bucketPathPattern),
4354
4631
  createPoLoader(),
4355
4632
  createFlatLoader(),
4633
+ createEnsureKeyOrderLoader(),
4356
4634
  createSyncLoader(),
4357
4635
  createVariableLoader({ type: "python" }),
4358
- createUnlocalizableLoader(
4359
- options.isCacheRestore,
4360
- options.returnUnlocalizedKeys
4361
- )
4636
+ createUnlocalizableLoader(options.returnUnlocalizedKeys)
4362
4637
  );
4363
4638
  case "properties":
4364
4639
  return composeLoaders(
4365
4640
  createTextFileLoader(bucketPathPattern),
4366
4641
  createPropertiesLoader(),
4367
4642
  createSyncLoader(),
4368
- createUnlocalizableLoader(
4369
- options.isCacheRestore,
4370
- options.returnUnlocalizedKeys
4371
- )
4643
+ createUnlocalizableLoader(options.returnUnlocalizedKeys)
4372
4644
  );
4373
4645
  case "xcode-strings":
4374
4646
  return composeLoaders(
4375
4647
  createTextFileLoader(bucketPathPattern),
4376
4648
  createXcodeStringsLoader(),
4377
4649
  createSyncLoader(),
4378
- createUnlocalizableLoader(
4379
- options.isCacheRestore,
4380
- options.returnUnlocalizedKeys
4381
- )
4650
+ createUnlocalizableLoader(options.returnUnlocalizedKeys)
4382
4651
  );
4383
4652
  case "xcode-stringsdict":
4384
4653
  return composeLoaders(
4385
4654
  createTextFileLoader(bucketPathPattern),
4386
4655
  createXcodeStringsdictLoader(),
4387
4656
  createFlatLoader(),
4657
+ createEnsureKeyOrderLoader(),
4388
4658
  createSyncLoader(),
4389
- createUnlocalizableLoader(
4390
- options.isCacheRestore,
4391
- options.returnUnlocalizedKeys
4392
- )
4659
+ createUnlocalizableLoader(options.returnUnlocalizedKeys)
4393
4660
  );
4394
4661
  case "xcode-xcstrings":
4395
4662
  return composeLoaders(
@@ -4398,12 +4665,10 @@ function createBucketLoader(bucketType, bucketPathPattern, options, lockedKeys,
4398
4665
  createJsonLoader(),
4399
4666
  createXcodeXcstringsLoader(options.defaultLocale),
4400
4667
  createFlatLoader(),
4668
+ createEnsureKeyOrderLoader(),
4401
4669
  createSyncLoader(),
4402
4670
  createVariableLoader({ type: "ieee" }),
4403
- createUnlocalizableLoader(
4404
- options.isCacheRestore,
4405
- options.returnUnlocalizedKeys
4406
- )
4671
+ createUnlocalizableLoader(options.returnUnlocalizedKeys)
4407
4672
  );
4408
4673
  case "yaml":
4409
4674
  return composeLoaders(
@@ -4411,12 +4676,10 @@ function createBucketLoader(bucketType, bucketPathPattern, options, lockedKeys,
4411
4676
  createPrettierLoader({ parser: "yaml", bucketPathPattern }),
4412
4677
  createYamlLoader(),
4413
4678
  createFlatLoader(),
4414
- createLockedKeysLoader(lockedKeys || [], options.isCacheRestore),
4679
+ createEnsureKeyOrderLoader(),
4680
+ createLockedKeysLoader(lockedKeys || []),
4415
4681
  createSyncLoader(),
4416
- createUnlocalizableLoader(
4417
- options.isCacheRestore,
4418
- options.returnUnlocalizedKeys
4419
- )
4682
+ createUnlocalizableLoader(options.returnUnlocalizedKeys)
4420
4683
  );
4421
4684
  case "yaml-root-key":
4422
4685
  return composeLoaders(
@@ -4425,76 +4688,60 @@ function createBucketLoader(bucketType, bucketPathPattern, options, lockedKeys,
4425
4688
  createYamlLoader(),
4426
4689
  createRootKeyLoader(true),
4427
4690
  createFlatLoader(),
4691
+ createEnsureKeyOrderLoader(),
4428
4692
  createSyncLoader(),
4429
- createUnlocalizableLoader(
4430
- options.isCacheRestore,
4431
- options.returnUnlocalizedKeys
4432
- )
4693
+ createUnlocalizableLoader(options.returnUnlocalizedKeys)
4433
4694
  );
4434
4695
  case "flutter":
4435
4696
  return composeLoaders(
4436
4697
  createTextFileLoader(bucketPathPattern),
4437
4698
  createPrettierLoader({ parser: "json", bucketPathPattern }),
4438
4699
  createJsonLoader(),
4700
+ createEnsureKeyOrderLoader(),
4439
4701
  createFlutterLoader(),
4440
4702
  createFlatLoader(),
4441
4703
  createSyncLoader(),
4442
- createUnlocalizableLoader(
4443
- options.isCacheRestore,
4444
- options.returnUnlocalizedKeys
4445
- )
4704
+ createUnlocalizableLoader(options.returnUnlocalizedKeys)
4446
4705
  );
4447
4706
  case "xliff":
4448
4707
  return composeLoaders(
4449
4708
  createTextFileLoader(bucketPathPattern),
4450
4709
  createXliffLoader(),
4451
4710
  createFlatLoader(),
4711
+ createEnsureKeyOrderLoader(),
4452
4712
  createSyncLoader(),
4453
- createUnlocalizableLoader(
4454
- options.isCacheRestore,
4455
- options.returnUnlocalizedKeys
4456
- )
4713
+ createUnlocalizableLoader(options.returnUnlocalizedKeys)
4457
4714
  );
4458
4715
  case "xml":
4459
4716
  return composeLoaders(
4460
4717
  createTextFileLoader(bucketPathPattern),
4461
4718
  createXmlLoader(),
4462
4719
  createFlatLoader(),
4720
+ createEnsureKeyOrderLoader(),
4463
4721
  createSyncLoader(),
4464
- createUnlocalizableLoader(
4465
- options.isCacheRestore,
4466
- options.returnUnlocalizedKeys
4467
- )
4722
+ createUnlocalizableLoader(options.returnUnlocalizedKeys)
4468
4723
  );
4469
4724
  case "srt":
4470
4725
  return composeLoaders(
4471
4726
  createTextFileLoader(bucketPathPattern),
4472
4727
  createSrtLoader(),
4473
4728
  createSyncLoader(),
4474
- createUnlocalizableLoader(
4475
- options.isCacheRestore,
4476
- options.returnUnlocalizedKeys
4477
- )
4729
+ createUnlocalizableLoader(options.returnUnlocalizedKeys)
4478
4730
  );
4479
4731
  case "dato":
4480
4732
  return composeLoaders(
4481
4733
  createDatoLoader(bucketPathPattern),
4482
4734
  createSyncLoader(),
4483
4735
  createFlatLoader(),
4484
- createUnlocalizableLoader(
4485
- options.isCacheRestore,
4486
- options.returnUnlocalizedKeys
4487
- )
4736
+ createEnsureKeyOrderLoader(),
4737
+ createUnlocalizableLoader(options.returnUnlocalizedKeys)
4488
4738
  );
4489
4739
  case "vtt":
4490
4740
  return composeLoaders(
4491
4741
  createTextFileLoader(bucketPathPattern),
4492
4742
  createVttLoader(),
4493
4743
  createSyncLoader(),
4494
- createUnlocalizableLoader(
4495
- options.isCacheRestore,
4496
- options.returnUnlocalizedKeys
4497
- )
4744
+ createUnlocalizableLoader(options.returnUnlocalizedKeys)
4498
4745
  );
4499
4746
  case "php":
4500
4747
  return composeLoaders(
@@ -4502,10 +4749,8 @@ function createBucketLoader(bucketType, bucketPathPattern, options, lockedKeys,
4502
4749
  createPhpLoader(),
4503
4750
  createSyncLoader(),
4504
4751
  createFlatLoader(),
4505
- createUnlocalizableLoader(
4506
- options.isCacheRestore,
4507
- options.returnUnlocalizedKeys
4508
- )
4752
+ createEnsureKeyOrderLoader(),
4753
+ createUnlocalizableLoader(options.returnUnlocalizedKeys)
4509
4754
  );
4510
4755
  case "vue-json":
4511
4756
  return composeLoaders(
@@ -4513,10 +4758,8 @@ function createBucketLoader(bucketType, bucketPathPattern, options, lockedKeys,
4513
4758
  createVueJsonLoader(),
4514
4759
  createSyncLoader(),
4515
4760
  createFlatLoader(),
4516
- createUnlocalizableLoader(
4517
- options.isCacheRestore,
4518
- options.returnUnlocalizedKeys
4519
- )
4761
+ createEnsureKeyOrderLoader(),
4762
+ createUnlocalizableLoader(options.returnUnlocalizedKeys)
4520
4763
  );
4521
4764
  case "typescript":
4522
4765
  return composeLoaders(
@@ -4524,13 +4767,11 @@ function createBucketLoader(bucketType, bucketPathPattern, options, lockedKeys,
4524
4767
  createPrettierLoader({ parser: "typescript", bucketPathPattern }),
4525
4768
  createTypescriptLoader(),
4526
4769
  createFlatLoader(),
4770
+ createEnsureKeyOrderLoader(),
4527
4771
  createSyncLoader(),
4528
- createLockedKeysLoader(lockedKeys || [], options.isCacheRestore),
4772
+ createLockedKeysLoader(lockedKeys || []),
4529
4773
  createIgnoredKeysLoader(ignoredKeys || []),
4530
- createUnlocalizableLoader(
4531
- options.isCacheRestore,
4532
- options.returnUnlocalizedKeys
4533
- )
4774
+ createUnlocalizableLoader(options.returnUnlocalizedKeys)
4534
4775
  );
4535
4776
  }
4536
4777
  }
@@ -4636,7 +4877,7 @@ function createBasicTranslator(model, systemPrompt) {
4636
4877
  ]
4637
4878
  });
4638
4879
  const result = JSON.parse(response.text);
4639
- return _optionalChain([result, 'optionalAccess', _178 => _178.data]) || {};
4880
+ return _optionalChain([result, 'optionalAccess', _185 => _185.data]) || {};
4640
4881
  }
4641
4882
  }
4642
4883
  function extractPayloadChunks(payload) {
@@ -4679,6 +4920,7 @@ var _openai = require('@ai-sdk/openai');
4679
4920
  var _anthropic = require('@ai-sdk/anthropic');
4680
4921
  var _google = require('@ai-sdk/google');
4681
4922
  var _aisdkprovider = require('@openrouter/ai-sdk-provider');
4923
+ var _mistral = require('@ai-sdk/mistral');
4682
4924
  var _ollamaaiprovider = require('ollama-ai-provider');
4683
4925
  function createProcessor(provider, params) {
4684
4926
  if (!provider) {
@@ -4696,7 +4938,11 @@ function getPureModelProvider(provider) {
4696
4938
 
4697
4939
  To fix this issue:
4698
4940
  1. ${envVar ? `Set ${_chalk2.default.dim(envVar)} in your environment variables` : "Set the environment variable for your provider (if required)"}, or
4699
- 2. Remove the ${_chalk2.default.italic("provider")} node from your i18n.json configuration to switch to ${_chalk2.default.hex(colors.green)("Lingo.dev")}
4941
+ 2. Remove the ${_chalk2.default.italic(
4942
+ "provider"
4943
+ )} node from your i18n.json configuration to switch to ${_chalk2.default.hex(
4944
+ colors.green
4945
+ )("Lingo.dev")}
4700
4946
 
4701
4947
  ${_chalk2.default.hex(colors.blue)("Docs: https://lingo.dev/go/docs")}
4702
4948
  `;
@@ -4705,11 +4951,15 @@ function getPureModelProvider(provider) {
4705
4951
 
4706
4952
  To fix this issue:
4707
4953
  1. Switch to one of the supported providers, or
4708
- 2. Remove the ${_chalk2.default.italic("provider")} node from your i18n.json configuration to switch to ${_chalk2.default.hex(colors.green)("Lingo.dev")}
4954
+ 2. Remove the ${_chalk2.default.italic(
4955
+ "provider"
4956
+ )} node from your i18n.json configuration to switch to ${_chalk2.default.hex(
4957
+ colors.green
4958
+ )("Lingo.dev")}
4709
4959
 
4710
4960
  ${_chalk2.default.hex(colors.blue)("Docs: https://lingo.dev/go/docs")}
4711
4961
  `;
4712
- switch (_optionalChain([provider, 'optionalAccess', _179 => _179.id])) {
4962
+ switch (_optionalChain([provider, 'optionalAccess', _186 => _186.id])) {
4713
4963
  case "openai": {
4714
4964
  if (!process.env.OPENAI_API_KEY) {
4715
4965
  throw new Error(
@@ -4755,8 +5005,19 @@ function getPureModelProvider(provider) {
4755
5005
  case "ollama": {
4756
5006
  return _ollamaaiprovider.createOllama.call(void 0, )(provider.model);
4757
5007
  }
5008
+ case "mistral": {
5009
+ if (!process.env.MISTRAL_API_KEY) {
5010
+ throw new Error(
5011
+ createMissingKeyErrorMessage("Mistral", "MISTRAL_API_KEY")
5012
+ );
5013
+ }
5014
+ return _mistral.createMistral.call(void 0, {
5015
+ apiKey: process.env.MISTRAL_API_KEY,
5016
+ baseURL: provider.baseUrl
5017
+ })(provider.model);
5018
+ }
4758
5019
  default: {
4759
- throw new Error(createUnsupportedProviderErrorMessage(_optionalChain([provider, 'optionalAccess', _180 => _180.id])));
5020
+ throw new Error(createUnsupportedProviderErrorMessage(_optionalChain([provider, 'optionalAccess', _187 => _187.id])));
4760
5021
  }
4761
5022
  }
4762
5023
  }
@@ -4864,11 +5125,17 @@ function createDeltaProcessor(fileKey) {
4864
5125
  return checkIfFileExists(lockfilePath);
4865
5126
  },
4866
5127
  async calculateDelta(params) {
4867
- let added = _lodash2.default.difference(Object.keys(params.sourceData), Object.keys(params.targetData));
4868
- let removed = _lodash2.default.difference(Object.keys(params.targetData), Object.keys(params.sourceData));
4869
- const updated = _lodash2.default.filter(Object.keys(params.sourceData), (key) => {
4870
- return md5(params.sourceData[key]) !== params.checksums[key] && params.checksums[key];
4871
- });
5128
+ let added = _lodash2.default.difference(
5129
+ Object.keys(params.sourceData),
5130
+ Object.keys(params.targetData)
5131
+ );
5132
+ let removed = _lodash2.default.difference(
5133
+ Object.keys(params.targetData),
5134
+ Object.keys(params.sourceData)
5135
+ );
5136
+ const updated = Object.keys(params.sourceData).filter(
5137
+ (key) => md5(params.sourceData[key]) !== params.checksums[key] && params.checksums[key]
5138
+ );
4872
5139
  const renamed = [];
4873
5140
  for (const addedKey of added) {
4874
5141
  const addedHash = md5(params.sourceData[addedKey]);
@@ -4879,9 +5146,18 @@ function createDeltaProcessor(fileKey) {
4879
5146
  }
4880
5147
  }
4881
5148
  }
4882
- added = added.filter((key) => !renamed.some(([oldKey, newKey]) => newKey === key));
4883
- removed = removed.filter((key) => !renamed.some(([oldKey, newKey]) => oldKey === key));
4884
- const hasChanges = [added.length > 0, removed.length > 0, updated.length > 0, renamed.length > 0].some((v) => v);
5149
+ added = added.filter(
5150
+ (key) => !renamed.some(([oldKey, newKey]) => newKey === key)
5151
+ );
5152
+ removed = removed.filter(
5153
+ (key) => !renamed.some(([oldKey, newKey]) => oldKey === key)
5154
+ );
5155
+ const hasChanges = [
5156
+ added.length > 0,
5157
+ removed.length > 0,
5158
+ updated.length > 0,
5159
+ renamed.length > 0
5160
+ ].some((v) => v);
4885
5161
  return {
4886
5162
  added,
4887
5163
  removed,
@@ -4981,7 +5257,7 @@ var i18n_default = new (0, _interactivecommander.Command)().command("i18n").desc
4981
5257
  validateParams(i18nConfig, flags);
4982
5258
  ora.succeed("Localization configuration is valid");
4983
5259
  ora.start("Connecting to Lingo.dev Localization Engine...");
4984
- const isByokMode = !!_optionalChain([i18nConfig, 'optionalAccess', _181 => _181.provider]);
5260
+ const isByokMode = !!_optionalChain([i18nConfig, 'optionalAccess', _188 => _188.provider]);
4985
5261
  if (isByokMode) {
4986
5262
  authId = null;
4987
5263
  ora.succeed("Using external provider (BYOK mode)");
@@ -4995,16 +5271,16 @@ var i18n_default = new (0, _interactivecommander.Command)().command("i18n").desc
4995
5271
  flags
4996
5272
  });
4997
5273
  let buckets = getBuckets(i18nConfig);
4998
- if (_optionalChain([flags, 'access', _182 => _182.bucket, 'optionalAccess', _183 => _183.length])) {
5274
+ if (_optionalChain([flags, 'access', _189 => _189.bucket, 'optionalAccess', _190 => _190.length])) {
4999
5275
  buckets = buckets.filter(
5000
5276
  (bucket) => flags.bucket.includes(bucket.type)
5001
5277
  );
5002
5278
  }
5003
5279
  ora.succeed("Buckets retrieved");
5004
- if (_optionalChain([flags, 'access', _184 => _184.file, 'optionalAccess', _185 => _185.length])) {
5280
+ if (_optionalChain([flags, 'access', _191 => _191.file, 'optionalAccess', _192 => _192.length])) {
5005
5281
  buckets = buckets.map((bucket) => {
5006
5282
  const paths = bucket.paths.filter(
5007
- (path17) => flags.file.find((file) => _optionalChain([path17, 'access', _186 => _186.pathPattern, 'optionalAccess', _187 => _187.includes, 'call', _188 => _188(file)]))
5283
+ (path17) => flags.file.find((file) => _optionalChain([path17, 'access', _193 => _193.pathPattern, 'optionalAccess', _194 => _194.includes, 'call', _195 => _195(file)]))
5008
5284
  );
5009
5285
  return { ...bucket, paths };
5010
5286
  }).filter((bucket) => bucket.paths.length > 0);
@@ -5023,7 +5299,7 @@ var i18n_default = new (0, _interactivecommander.Command)().command("i18n").desc
5023
5299
  });
5024
5300
  }
5025
5301
  }
5026
- const targetLocales = _optionalChain([flags, 'access', _189 => _189.locale, 'optionalAccess', _190 => _190.length]) ? flags.locale : i18nConfig.locale.targets;
5302
+ const targetLocales = _optionalChain([flags, 'access', _196 => _196.locale, 'optionalAccess', _197 => _197.length]) ? flags.locale : i18nConfig.locale.targets;
5027
5303
  ora.start("Setting up localization cache...");
5028
5304
  const checkLockfileProcessor = createDeltaProcessor("");
5029
5305
  const lockfileExists = await checkLockfileProcessor.checkIfLockExists();
@@ -5039,7 +5315,6 @@ var i18n_default = new (0, _interactivecommander.Command)().command("i18n").desc
5039
5315
  bucket.type,
5040
5316
  bucketPath.pathPattern,
5041
5317
  {
5042
- isCacheRestore: false,
5043
5318
  defaultLocale: sourceLocale,
5044
5319
  injectLocale: bucket.injectLocale
5045
5320
  },
@@ -5074,7 +5349,6 @@ var i18n_default = new (0, _interactivecommander.Command)().command("i18n").desc
5074
5349
  bucket.type,
5075
5350
  bucketPath.pathPattern,
5076
5351
  {
5077
- isCacheRestore: false,
5078
5352
  defaultLocale: sourceLocale,
5079
5353
  returnUnlocalizedKeys: true,
5080
5354
  injectLocale: bucket.injectLocale
@@ -5160,7 +5434,6 @@ var i18n_default = new (0, _interactivecommander.Command)().command("i18n").desc
5160
5434
  bucket.type,
5161
5435
  bucketPath.pathPattern,
5162
5436
  {
5163
- isCacheRestore: false,
5164
5437
  defaultLocale: sourceLocale,
5165
5438
  injectLocale: bucket.injectLocale
5166
5439
  },
@@ -5197,7 +5470,7 @@ var i18n_default = new (0, _interactivecommander.Command)().command("i18n").desc
5197
5470
  if (flags.key) {
5198
5471
  processableData = _lodash2.default.pickBy(
5199
5472
  processableData,
5200
- (_33, key) => key === flags.key
5473
+ (_34, key) => key === flags.key
5201
5474
  );
5202
5475
  }
5203
5476
  if (flags.verbose) {
@@ -5367,12 +5640,12 @@ function validateParams(i18nConfig, flags) {
5367
5640
  message: "No buckets found in i18n.json. Please add at least one bucket containing i18n content.",
5368
5641
  docUrl: "bucketNotFound"
5369
5642
  });
5370
- } else if (_optionalChain([flags, 'access', _191 => _191.locale, 'optionalAccess', _192 => _192.some, 'call', _193 => _193((locale) => !i18nConfig.locale.targets.includes(locale))])) {
5643
+ } else if (_optionalChain([flags, 'access', _198 => _198.locale, 'optionalAccess', _199 => _199.some, 'call', _200 => _200((locale) => !i18nConfig.locale.targets.includes(locale))])) {
5371
5644
  throw new CLIError({
5372
5645
  message: `One or more specified locales do not exist in i18n.json locale.targets. Please add them to the list and try again.`,
5373
5646
  docUrl: "localeTargetNotFound"
5374
5647
  });
5375
- } else if (_optionalChain([flags, 'access', _194 => _194.bucket, 'optionalAccess', _195 => _195.some, 'call', _196 => _196(
5648
+ } else if (_optionalChain([flags, 'access', _201 => _201.bucket, 'optionalAccess', _202 => _202.some, 'call', _203 => _203(
5376
5649
  (bucket) => !i18nConfig.buckets[bucket]
5377
5650
  )])) {
5378
5651
  throw new CLIError({
@@ -5387,7 +5660,9 @@ async function reviewChanges(args) {
5387
5660
  if (currentStr === proposedStr && !args.force) {
5388
5661
  console.log(
5389
5662
  `
5390
- ${_chalk2.default.blue(args.pathPattern)} (${_chalk2.default.yellow(args.targetLocale)}): ${_chalk2.default.gray("No changes to review")}`
5663
+ ${_chalk2.default.blue(args.pathPattern)} (${_chalk2.default.yellow(
5664
+ args.targetLocale
5665
+ )}): ${_chalk2.default.gray("No changes to review")}`
5391
5666
  );
5392
5667
  return args.proposedData;
5393
5668
  }
@@ -5408,7 +5683,9 @@ ${_chalk2.default.blue(args.pathPattern)} (${_chalk2.default.yellow(args.targetL
5408
5683
  }).join("\n");
5409
5684
  console.log(
5410
5685
  `
5411
- Reviewing changes for ${_chalk2.default.blue(args.pathPattern)} (${_chalk2.default.yellow(args.targetLocale)}):`
5686
+ Reviewing changes for ${_chalk2.default.blue(args.pathPattern)} (${_chalk2.default.yellow(
5687
+ args.targetLocale
5688
+ )}):`
5412
5689
  );
5413
5690
  console.log(coloredDiff);
5414
5691
  const { action } = await _inquirer2.default.prompt([
@@ -5521,8 +5798,15 @@ function createLockfileHelper() {
5521
5798
  registerPartialSourceData: (pathPattern, partialSourceData) => {
5522
5799
  const lockfile = _loadLockfile();
5523
5800
  const sectionKey = _objecthash.MD5.call(void 0, pathPattern);
5524
- const sectionChecksums = _lodash2.default.mapValues(partialSourceData, (value) => _objecthash.MD5.call(void 0, value));
5525
- lockfile.checksums[sectionKey] = _lodash2.default.merge({}, _nullishCoalesce(lockfile.checksums[sectionKey], () => ( {})), sectionChecksums);
5801
+ const sectionChecksums = _lodash2.default.mapValues(
5802
+ partialSourceData,
5803
+ (value) => _objecthash.MD5.call(void 0, value)
5804
+ );
5805
+ lockfile.checksums[sectionKey] = _lodash2.default.merge(
5806
+ {},
5807
+ _nullishCoalesce(lockfile.checksums[sectionKey], () => ( {})),
5808
+ sectionChecksums
5809
+ );
5526
5810
  _saveLockfile(lockfile);
5527
5811
  },
5528
5812
  extractUpdatedData: (pathPattern, sourceData) => {
@@ -5530,7 +5814,10 @@ function createLockfileHelper() {
5530
5814
  const sectionKey = _objecthash.MD5.call(void 0, pathPattern);
5531
5815
  const currentChecksums = _lodash2.default.mapValues(sourceData, (value) => _objecthash.MD5.call(void 0, value));
5532
5816
  const savedChecksums = lockfile.checksums[sectionKey] || {};
5533
- const updatedData = _lodash2.default.pickBy(sourceData, (value, key) => savedChecksums[key] !== currentChecksums[key]);
5817
+ const updatedData = _lodash2.default.pickBy(
5818
+ sourceData,
5819
+ (value, key) => savedChecksums[key] !== currentChecksums[key]
5820
+ );
5534
5821
  return updatedData;
5535
5822
  }
5536
5823
  };
@@ -5574,20 +5861,31 @@ var lockfile_default = new (0, _interactivecommander.Command)().command("lockfil
5574
5861
  const ora = _ora2.default.call(void 0, );
5575
5862
  const lockfileHelper = createLockfileHelper();
5576
5863
  if (lockfileHelper.isLockfileExists() && !flags.force) {
5577
- ora.warn(`Lockfile won't be created because it already exists. Use --force to overwrite.`);
5864
+ ora.warn(
5865
+ `Lockfile won't be created because it already exists. Use --force to overwrite.`
5866
+ );
5578
5867
  } else {
5579
5868
  const i18nConfig = getConfig();
5580
5869
  const buckets = getBuckets(i18nConfig);
5581
5870
  for (const bucket of buckets) {
5582
5871
  for (const bucketConfig of bucket.paths) {
5583
- const sourceLocale = __spec.resolveOverriddenLocale.call(void 0, i18nConfig.locale.source, bucketConfig.delimiter);
5584
- const bucketLoader = createBucketLoader(bucket.type, bucketConfig.pathPattern, {
5585
- isCacheRestore: false,
5586
- defaultLocale: sourceLocale
5587
- });
5872
+ const sourceLocale = __spec.resolveOverriddenLocale.call(void 0,
5873
+ i18nConfig.locale.source,
5874
+ bucketConfig.delimiter
5875
+ );
5876
+ const bucketLoader = createBucketLoader(
5877
+ bucket.type,
5878
+ bucketConfig.pathPattern,
5879
+ {
5880
+ defaultLocale: sourceLocale
5881
+ }
5882
+ );
5588
5883
  bucketLoader.setDefaultLocale(sourceLocale);
5589
5884
  const sourceData = await bucketLoader.pull(sourceLocale);
5590
- lockfileHelper.registerSourceData(bucketConfig.pathPattern, sourceData);
5885
+ lockfileHelper.registerSourceData(
5886
+ bucketConfig.pathPattern,
5887
+ sourceData
5888
+ );
5591
5889
  }
5592
5890
  }
5593
5891
  ora.succeed("Lockfile created");
@@ -5602,7 +5900,9 @@ var flagsSchema = _zod2.default.object({
5602
5900
 
5603
5901
 
5604
5902
 
5605
- var cleanup_default = new (0, _interactivecommander.Command)().command("cleanup").description("Remove keys from target files that do not exist in the source file").helpOption("-h, --help", "Show help").option("--locale <locale>", "Specific locale to cleanup").option("--bucket <bucket>", "Specific bucket to cleanup").option("--dry-run", "Show what would be removed without making changes").option(
5903
+ var cleanup_default = new (0, _interactivecommander.Command)().command("cleanup").description(
5904
+ "Remove keys from target files that do not exist in the source file"
5905
+ ).helpOption("-h, --help", "Show help").option("--locale <locale>", "Specific locale to cleanup").option("--bucket <bucket>", "Specific bucket to cleanup").option("--dry-run", "Show what would be removed without making changes").option(
5606
5906
  "--verbose",
5607
5907
  "Show detailed output including:\n - List of keys that would be removed.\n - Processing steps."
5608
5908
  ).action(async function(options) {
@@ -5615,24 +5915,37 @@ var cleanup_default = new (0, _interactivecommander.Command)().command("cleanup"
5615
5915
  ora.succeed("Configuration loaded");
5616
5916
  let buckets = getBuckets(i18nConfig);
5617
5917
  if (options.bucket) {
5618
- buckets = buckets.filter((bucket) => bucket.type === options.bucket);
5918
+ buckets = buckets.filter(
5919
+ (bucket) => bucket.type === options.bucket
5920
+ );
5619
5921
  }
5620
5922
  const targetLocales = options.locale ? [options.locale] : i18nConfig.locale.targets;
5621
5923
  for (const bucket of buckets) {
5622
5924
  console.log();
5623
5925
  ora.info(`Processing bucket: ${bucket.type}`);
5624
5926
  for (const bucketConfig of bucket.paths) {
5625
- const sourceLocale = __spec.resolveOverriddenLocale.call(void 0, i18nConfig.locale.source, bucketConfig.delimiter);
5626
- const bucketOra = _ora2.default.call(void 0, { indent: 2 }).info(`Processing path: ${bucketConfig.pathPattern}`);
5627
- const bucketLoader = createBucketLoader(bucket.type, bucketConfig.pathPattern, {
5628
- isCacheRestore: false,
5629
- defaultLocale: sourceLocale
5630
- });
5927
+ const sourceLocale = __spec.resolveOverriddenLocale.call(void 0,
5928
+ i18nConfig.locale.source,
5929
+ bucketConfig.delimiter
5930
+ );
5931
+ const bucketOra = _ora2.default.call(void 0, { indent: 2 }).info(
5932
+ `Processing path: ${bucketConfig.pathPattern}`
5933
+ );
5934
+ const bucketLoader = createBucketLoader(
5935
+ bucket.type,
5936
+ bucketConfig.pathPattern,
5937
+ {
5938
+ defaultLocale: sourceLocale
5939
+ }
5940
+ );
5631
5941
  bucketLoader.setDefaultLocale(sourceLocale);
5632
5942
  const sourceData = await bucketLoader.pull(sourceLocale);
5633
5943
  const sourceKeys = Object.keys(sourceData);
5634
5944
  for (const _targetLocale of targetLocales) {
5635
- const targetLocale = __spec.resolveOverriddenLocale.call(void 0, _targetLocale, bucketConfig.delimiter);
5945
+ const targetLocale = __spec.resolveOverriddenLocale.call(void 0,
5946
+ _targetLocale,
5947
+ bucketConfig.delimiter
5948
+ );
5636
5949
  try {
5637
5950
  const targetData = await bucketLoader.pull(targetLocale);
5638
5951
  const targetKeys = Object.keys(targetData);
@@ -5642,17 +5955,29 @@ var cleanup_default = new (0, _interactivecommander.Command)().command("cleanup"
5642
5955
  continue;
5643
5956
  }
5644
5957
  if (options.verbose) {
5645
- bucketOra.info(`[${targetLocale}] Keys to remove: ${JSON.stringify(keysToRemove, null, 2)}`);
5958
+ bucketOra.info(
5959
+ `[${targetLocale}] Keys to remove: ${JSON.stringify(
5960
+ keysToRemove,
5961
+ null,
5962
+ 2
5963
+ )}`
5964
+ );
5646
5965
  }
5647
5966
  if (!options.dryRun) {
5648
5967
  const cleanedData = _lodash2.default.pick(targetData, sourceKeys);
5649
5968
  await bucketLoader.push(targetLocale, cleanedData);
5650
- bucketOra.succeed(`[${targetLocale}] Removed ${keysToRemove.length} keys`);
5969
+ bucketOra.succeed(
5970
+ `[${targetLocale}] Removed ${keysToRemove.length} keys`
5971
+ );
5651
5972
  } else {
5652
- bucketOra.succeed(`[${targetLocale}] Would remove ${keysToRemove.length} keys (dry run)`);
5973
+ bucketOra.succeed(
5974
+ `[${targetLocale}] Would remove ${keysToRemove.length} keys (dry run)`
5975
+ );
5653
5976
  }
5654
5977
  } catch (error) {
5655
- bucketOra.fail(`[${targetLocale}] Failed to cleanup: ${error.message}`);
5978
+ bucketOra.fail(
5979
+ `[${targetLocale}] Failed to cleanup: ${error.message}`
5980
+ );
5656
5981
  results.push({
5657
5982
  step: `Cleanup ${bucket.type}/${bucketConfig} for ${targetLocale}`,
5658
5983
  status: "Failed",
@@ -5700,7 +6025,7 @@ var _stdiojs = require('@modelcontextprotocol/sdk/server/stdio.js');
5700
6025
  var _mcpjs = require('@modelcontextprotocol/sdk/server/mcp.js');
5701
6026
 
5702
6027
 
5703
- var mcp_default = new (0, _interactivecommander.Command)().command("mcp").description("Use Lingo.dev model context provider with your AI agent").helpOption("-h, --help", "Show help").action(async (_33, program) => {
6028
+ var mcp_default = new (0, _interactivecommander.Command)().command("mcp").description("Use Lingo.dev model context provider with your AI agent").helpOption("-h, --help", "Show help").action(async (_34, program) => {
5704
6029
  const apiKey = program.args[0];
5705
6030
  const settings = getSettings(apiKey);
5706
6031
  if (!settings.auth.apiKey) {
@@ -5802,7 +6127,9 @@ function createLingoDotDevLocalizer(explicitApiKey) {
5802
6127
  if (!auth) {
5803
6128
  throw new Error(
5804
6129
  _dedent2.default`
5805
- You're trying to use ${_chalk2.default.hex(colors.green)("Lingo.dev")} provider, however, you are not authenticated.
6130
+ You're trying to use ${_chalk2.default.hex(colors.green)(
6131
+ "Lingo.dev"
6132
+ )} provider, however, you are not authenticated.
5806
6133
 
5807
6134
  To fix this issue:
5808
6135
  1. Run ${_chalk2.default.dim("lingo.dev login")} to authenticate, or
@@ -5822,7 +6149,7 @@ function createLingoDotDevLocalizer(explicitApiKey) {
5822
6149
  const response = await engine.whoami();
5823
6150
  return {
5824
6151
  authenticated: !!response,
5825
- username: _optionalChain([response, 'optionalAccess', _197 => _197.email])
6152
+ username: _optionalChain([response, 'optionalAccess', _204 => _204.email])
5826
6153
  };
5827
6154
  } catch (e2) {
5828
6155
  return { authenticated: false };
@@ -5859,6 +6186,7 @@ function createLingoDotDevLocalizer(explicitApiKey) {
5859
6186
 
5860
6187
 
5861
6188
 
6189
+
5862
6190
  function createExplicitLocalizer(provider) {
5863
6191
  switch (provider.id) {
5864
6192
  default:
@@ -5868,7 +6196,11 @@ function createExplicitLocalizer(provider) {
5868
6196
 
5869
6197
  To fix this issue:
5870
6198
  1. Switch to one of the supported providers, or
5871
- 2. Remove the ${_chalk2.default.italic("provider")} node from your i18n.json configuration to switch to ${_chalk2.default.hex(colors.green)("Lingo.dev")}
6199
+ 2. Remove the ${_chalk2.default.italic(
6200
+ "provider"
6201
+ )} node from your i18n.json configuration to switch to ${_chalk2.default.hex(
6202
+ colors.green
6203
+ )("Lingo.dev")}
5872
6204
 
5873
6205
  ${_chalk2.default.hex(colors.blue)("Docs: https://lingo.dev/go/docs")}
5874
6206
  `
@@ -5912,19 +6244,35 @@ function createExplicitLocalizer(provider) {
5912
6244
  prompt: provider.prompt,
5913
6245
  skipAuth: true
5914
6246
  });
6247
+ case "mistral":
6248
+ return createAiSdkLocalizer({
6249
+ factory: (params) => _mistral.createMistral.call(void 0, params).languageModel(provider.model),
6250
+ id: provider.id,
6251
+ prompt: provider.prompt,
6252
+ apiKeyName: "MISTRAL_API_KEY",
6253
+ baseUrl: provider.baseUrl
6254
+ });
5915
6255
  }
5916
6256
  }
5917
6257
  function createAiSdkLocalizer(params) {
5918
6258
  const skipAuth = params.skipAuth === true;
5919
- const apiKey = process.env[_nullishCoalesce(_optionalChain([params, 'optionalAccess', _198 => _198.apiKeyName]), () => ( ""))];
6259
+ const apiKey = process.env[_nullishCoalesce(_optionalChain([params, 'optionalAccess', _205 => _205.apiKeyName]), () => ( ""))];
5920
6260
  if (!skipAuth && !apiKey || !params.apiKeyName) {
5921
6261
  throw new Error(
5922
6262
  _dedent2.default`
5923
- You're trying to use raw ${_chalk2.default.dim(params.id)} API for translation. ${params.apiKeyName ? `However, ${_chalk2.default.dim(params.apiKeyName)} environment variable is not set.` : "However, that provider is unavailable."}
6263
+ You're trying to use raw ${_chalk2.default.dim(params.id)} API for translation. ${params.apiKeyName ? `However, ${_chalk2.default.dim(
6264
+ params.apiKeyName
6265
+ )} environment variable is not set.` : "However, that provider is unavailable."}
5924
6266
 
5925
6267
  To fix this issue:
5926
- 1. ${params.apiKeyName ? `Set ${_chalk2.default.dim(params.apiKeyName)} in your environment variables` : "Set the environment variable for your provider (if required)"}, or
5927
- 2. Remove the ${_chalk2.default.italic("provider")} node from your i18n.json configuration to switch to ${_chalk2.default.hex(colors.green)("Lingo.dev")}
6268
+ 1. ${params.apiKeyName ? `Set ${_chalk2.default.dim(
6269
+ params.apiKeyName
6270
+ )} in your environment variables` : "Set the environment variable for your provider (if required)"}, or
6271
+ 2. Remove the ${_chalk2.default.italic(
6272
+ "provider"
6273
+ )} node from your i18n.json configuration to switch to ${_chalk2.default.hex(
6274
+ colors.green
6275
+ )("Lingo.dev")}
5928
6276
 
5929
6277
  ${_chalk2.default.hex(colors.blue)("Docs: https://lingo.dev/go/docs")}
5930
6278
  `
@@ -6033,8 +6381,8 @@ async function setup(input2) {
6033
6381
  throw new Error(
6034
6382
  "No buckets found in i18n.json. Please add at least one bucket containing i18n content."
6035
6383
  );
6036
- } else if (_optionalChain([ctx, 'access', _199 => _199.flags, 'access', _200 => _200.bucket, 'optionalAccess', _201 => _201.some, 'call', _202 => _202(
6037
- (bucket) => !_optionalChain([ctx, 'access', _203 => _203.config, 'optionalAccess', _204 => _204.buckets, 'access', _205 => _205[bucket]])
6384
+ } else if (_optionalChain([ctx, 'access', _206 => _206.flags, 'access', _207 => _207.bucket, 'optionalAccess', _208 => _208.some, 'call', _209 => _209(
6385
+ (bucket) => !_optionalChain([ctx, 'access', _210 => _210.config, 'optionalAccess', _211 => _211.buckets, 'access', _212 => _212[bucket]])
6038
6386
  )])) {
6039
6387
  throw new Error(
6040
6388
  `One or more specified buckets do not exist in i18n.json. Please add them to the list first and try again.`
@@ -6047,7 +6395,7 @@ async function setup(input2) {
6047
6395
  title: "Selecting localization provider",
6048
6396
  task: async (ctx, task) => {
6049
6397
  ctx.localizer = createLocalizer(
6050
- _optionalChain([ctx, 'access', _206 => _206.config, 'optionalAccess', _207 => _207.provider]),
6398
+ _optionalChain([ctx, 'access', _213 => _213.config, 'optionalAccess', _214 => _214.provider]),
6051
6399
  ctx.flags.apiKey
6052
6400
  );
6053
6401
  if (!ctx.localizer) {
@@ -6064,10 +6412,14 @@ async function setup(input2) {
6064
6412
  const authStatus = await ctx.localizer.checkAuth();
6065
6413
  if (!authStatus.authenticated) {
6066
6414
  throw new Error(
6067
- `Failed to authenticate with ${_chalk2.default.hex(colors.yellow)(ctx.localizer.id)} provider. Please check your API key and try again.`
6415
+ `Failed to authenticate with ${_chalk2.default.hex(colors.yellow)(
6416
+ ctx.localizer.id
6417
+ )} provider. Please check your API key and try again.`
6068
6418
  );
6069
6419
  }
6070
- task.title = `Authenticated as ${_chalk2.default.hex(colors.yellow)(authStatus.username)}`;
6420
+ task.title = `Authenticated as ${_chalk2.default.hex(colors.yellow)(
6421
+ authStatus.username
6422
+ )}`;
6071
6423
  }
6072
6424
  },
6073
6425
  {
@@ -6128,14 +6480,22 @@ async function plan(input2) {
6128
6480
  title: "Locating content buckets",
6129
6481
  task: async (ctx, task) => {
6130
6482
  const bucketCount = buckets.length;
6131
- const bucketFilter = input2.flags.bucket ? ` ${_chalk2.default.dim(`(filtered by: ${_chalk2.default.hex(colors.yellow)(input2.flags.bucket.join(", "))})`)}` : "";
6132
- task.title = `Found ${_chalk2.default.hex(colors.yellow)(bucketCount.toString())} bucket(s)${bucketFilter}`;
6483
+ const bucketFilter = input2.flags.bucket ? ` ${_chalk2.default.dim(
6484
+ `(filtered by: ${_chalk2.default.hex(colors.yellow)(
6485
+ input2.flags.bucket.join(", ")
6486
+ )})`
6487
+ )}` : "";
6488
+ task.title = `Found ${_chalk2.default.hex(colors.yellow)(
6489
+ bucketCount.toString()
6490
+ )} bucket(s)${bucketFilter}`;
6133
6491
  }
6134
6492
  },
6135
6493
  {
6136
6494
  title: "Detecting locales",
6137
6495
  task: async (ctx, task) => {
6138
- task.title = `Found ${_chalk2.default.hex(colors.yellow)(_targetLocales.length.toString())} target locale(s)`;
6496
+ task.title = `Found ${_chalk2.default.hex(colors.yellow)(
6497
+ _targetLocales.length.toString()
6498
+ )} target locale(s)`;
6139
6499
  }
6140
6500
  },
6141
6501
  {
@@ -6154,8 +6514,14 @@ async function plan(input2) {
6154
6514
  patterns.push(bucketPath.pathPattern);
6155
6515
  }
6156
6516
  }
6157
- const fileFilter = input2.flags.file ? ` ${_chalk2.default.dim(`(filtered by: ${_chalk2.default.hex(colors.yellow)(input2.flags.file.join(", "))})`)}` : "";
6158
- task.title = `Found ${_chalk2.default.hex(colors.yellow)(patterns.length.toString())} path pattern(s)${fileFilter}`;
6517
+ const fileFilter = input2.flags.file ? ` ${_chalk2.default.dim(
6518
+ `(filtered by: ${_chalk2.default.hex(colors.yellow)(
6519
+ input2.flags.file.join(", ")
6520
+ )})`
6521
+ )}` : "";
6522
+ task.title = `Found ${_chalk2.default.hex(colors.yellow)(
6523
+ patterns.length.toString()
6524
+ )} path pattern(s)${fileFilter}`;
6159
6525
  }
6160
6526
  },
6161
6527
  {
@@ -6193,7 +6559,9 @@ async function plan(input2) {
6193
6559
  }
6194
6560
  }
6195
6561
  }
6196
- task.title = `Prepared ${_chalk2.default.hex(colors.green)(ctx.tasks.length.toString())} translation task(s)`;
6562
+ task.title = `Prepared ${_chalk2.default.hex(colors.green)(
6563
+ ctx.tasks.length.toString()
6564
+ )} translation task(s)`;
6197
6565
  }
6198
6566
  }
6199
6567
  ],
@@ -6647,7 +7015,7 @@ var AST = class _AST {
6647
7015
  const ret = this.type === null ? this.#parts.slice().map((p) => typeof p === "string" ? p : p.toJSON()) : [this.type, ...this.#parts.map((p) => p.toJSON())];
6648
7016
  if (this.isStart() && !this.type)
6649
7017
  ret.unshift([]);
6650
- if (this.isEnd() && (this === this.#root || this.#root.#filledNegs && _optionalChain([this, 'access', _208 => _208.#parent, 'optionalAccess', _209 => _209.type]) === "!")) {
7018
+ if (this.isEnd() && (this === this.#root || this.#root.#filledNegs && _optionalChain([this, 'access', _215 => _215.#parent, 'optionalAccess', _216 => _216.type]) === "!")) {
6651
7019
  ret.push({});
6652
7020
  }
6653
7021
  return ret;
@@ -6655,7 +7023,7 @@ var AST = class _AST {
6655
7023
  isStart() {
6656
7024
  if (this.#root === this)
6657
7025
  return true;
6658
- if (!_optionalChain([this, 'access', _210 => _210.#parent, 'optionalAccess', _211 => _211.isStart, 'call', _212 => _212()]))
7026
+ if (!_optionalChain([this, 'access', _217 => _217.#parent, 'optionalAccess', _218 => _218.isStart, 'call', _219 => _219()]))
6659
7027
  return false;
6660
7028
  if (this.#parentIndex === 0)
6661
7029
  return true;
@@ -6671,12 +7039,12 @@ var AST = class _AST {
6671
7039
  isEnd() {
6672
7040
  if (this.#root === this)
6673
7041
  return true;
6674
- if (_optionalChain([this, 'access', _213 => _213.#parent, 'optionalAccess', _214 => _214.type]) === "!")
7042
+ if (_optionalChain([this, 'access', _220 => _220.#parent, 'optionalAccess', _221 => _221.type]) === "!")
6675
7043
  return true;
6676
- if (!_optionalChain([this, 'access', _215 => _215.#parent, 'optionalAccess', _216 => _216.isEnd, 'call', _217 => _217()]))
7044
+ if (!_optionalChain([this, 'access', _222 => _222.#parent, 'optionalAccess', _223 => _223.isEnd, 'call', _224 => _224()]))
6677
7045
  return false;
6678
7046
  if (!this.type)
6679
- return _optionalChain([this, 'access', _218 => _218.#parent, 'optionalAccess', _219 => _219.isEnd, 'call', _220 => _220()]);
7047
+ return _optionalChain([this, 'access', _225 => _225.#parent, 'optionalAccess', _226 => _226.isEnd, 'call', _227 => _227()]);
6680
7048
  const pl = this.#parent ? this.#parent.#parts.length : 0;
6681
7049
  return this.#parentIndex === pl - 1;
6682
7050
  }
@@ -6898,7 +7266,7 @@ var AST = class _AST {
6898
7266
  if (!this.type) {
6899
7267
  const noEmpty = this.isStart() && this.isEnd();
6900
7268
  const src = this.#parts.map((p) => {
6901
- const [re, _33, hasMagic, uflag] = typeof p === "string" ? _AST.#parseGlob(p, this.#hasMagic, noEmpty) : p.toRegExpSource(allowDot);
7269
+ const [re, _34, hasMagic, uflag] = typeof p === "string" ? _AST.#parseGlob(p, this.#hasMagic, noEmpty) : p.toRegExpSource(allowDot);
6902
7270
  this.#hasMagic = this.#hasMagic || hasMagic;
6903
7271
  this.#uflag = this.#uflag || uflag;
6904
7272
  return re;
@@ -6921,7 +7289,7 @@ var AST = class _AST {
6921
7289
  }
6922
7290
  }
6923
7291
  let end = "";
6924
- if (this.isEnd() && this.#root.#filledNegs && _optionalChain([this, 'access', _221 => _221.#parent, 'optionalAccess', _222 => _222.type]) === "!") {
7292
+ if (this.isEnd() && this.#root.#filledNegs && _optionalChain([this, 'access', _228 => _228.#parent, 'optionalAccess', _229 => _229.type]) === "!") {
6925
7293
  end = "(?:$|\\/)";
6926
7294
  }
6927
7295
  const final2 = start2 + src + end;
@@ -6971,7 +7339,7 @@ var AST = class _AST {
6971
7339
  if (typeof p === "string") {
6972
7340
  throw new Error("string type in extglob ast??");
6973
7341
  }
6974
- const [re, _33, _hasMagic, uflag] = p.toRegExpSource(dot);
7342
+ const [re, _34, _hasMagic, uflag] = p.toRegExpSource(dot);
6975
7343
  this.#uflag = this.#uflag || uflag;
6976
7344
  return re;
6977
7345
  }).filter((p) => !(this.isStart() && this.isEnd()) || !!p).join("|");
@@ -7216,7 +7584,7 @@ var Minimatch = class {
7216
7584
  }
7217
7585
  return false;
7218
7586
  }
7219
- debug(..._33) {
7587
+ debug(..._34) {
7220
7588
  }
7221
7589
  make() {
7222
7590
  const pattern = this.pattern;
@@ -7238,7 +7606,7 @@ var Minimatch = class {
7238
7606
  const rawGlobParts = this.globSet.map((s) => this.slashSplit(s));
7239
7607
  this.globParts = this.preprocess(rawGlobParts);
7240
7608
  this.debug(this.pattern, this.globParts);
7241
- let set = this.globParts.map((s, _33, __) => {
7609
+ let set = this.globParts.map((s, _34, __) => {
7242
7610
  if (this.isWindows && this.windowsNoMagicRoot) {
7243
7611
  const isUNC = s[0] === "" && s[1] === "" && (s[2] === "?" || !globMagic.test(s[2])) && !globMagic.test(s[3]);
7244
7612
  const isDrive = /^[a-z]:/i.test(s[0]);
@@ -7761,11 +8129,15 @@ async function execute(input2) {
7761
8129
  {
7762
8130
  title: "Initializing localization engine",
7763
8131
  task: async (ctx, task) => {
7764
- task.title = `Localization engine ${_chalk2.default.hex(colors.green)("ready")} (${ctx.localizer.id})`;
8132
+ task.title = `Localization engine ${_chalk2.default.hex(colors.green)(
8133
+ "ready"
8134
+ )} (${ctx.localizer.id})`;
7765
8135
  }
7766
8136
  },
7767
8137
  {
7768
- title: `Processing localization tasks ${_chalk2.default.dim(`(tasks: ${input2.tasks.length}, concurrency: ${effectiveConcurrency})`)}`,
8138
+ title: `Processing localization tasks ${_chalk2.default.dim(
8139
+ `(tasks: ${input2.tasks.length}, concurrency: ${effectiveConcurrency})`
8140
+ )}`,
7769
8141
  task: (ctx, task) => {
7770
8142
  if (input2.tasks.length < 1) {
7771
8143
  task.title = `Skipping, nothing to localize.`;
@@ -7778,7 +8150,7 @@ async function execute(input2) {
7778
8150
  const workerTasks = [];
7779
8151
  for (let i = 0; i < workersCount; i++) {
7780
8152
  const assignedTasks = ctx.tasks.filter(
7781
- (_33, idx) => idx % workersCount === i
8153
+ (_34, idx) => idx % workersCount === i
7782
8154
  );
7783
8155
  workerTasks.push(
7784
8156
  createWorkerTask({
@@ -7814,11 +8186,11 @@ function createWorkerStatusMessage(args) {
7814
8186
  "[locale]",
7815
8187
  args.assignedTask.targetLocale
7816
8188
  );
7817
- return `[${_chalk2.default.hex(colors.yellow)(`${args.percentage}%`)}] Processing: ${_chalk2.default.dim(
7818
- displayPath
7819
- )} (${_chalk2.default.hex(colors.yellow)(args.assignedTask.sourceLocale)} -> ${_chalk2.default.hex(
7820
- colors.yellow
7821
- )(args.assignedTask.targetLocale)})`;
8189
+ return `[${_chalk2.default.hex(colors.yellow)(
8190
+ `${args.percentage}%`
8191
+ )}] Processing: ${_chalk2.default.dim(displayPath)} (${_chalk2.default.hex(colors.yellow)(
8192
+ args.assignedTask.sourceLocale
8193
+ )} -> ${_chalk2.default.hex(colors.yellow)(args.assignedTask.targetLocale)})`;
7822
8194
  }
7823
8195
  function createExecutionProgressMessage(ctx) {
7824
8196
  const succeededTasksCount = countTasks(
@@ -7833,7 +8205,9 @@ function createExecutionProgressMessage(ctx) {
7833
8205
  ctx,
7834
8206
  (_t, result) => result.status === "skipped"
7835
8207
  );
7836
- return `Processed ${_chalk2.default.green(succeededTasksCount)}/${ctx.tasks.length}, Failed ${_chalk2.default.red(failedTasksCount)}, Skipped ${_chalk2.default.dim(skippedTasksCount)}`;
8208
+ return `Processed ${_chalk2.default.green(succeededTasksCount)}/${ctx.tasks.length}, Failed ${_chalk2.default.red(failedTasksCount)}, Skipped ${_chalk2.default.dim(
8209
+ skippedTasksCount
8210
+ )}`;
7837
8211
  }
7838
8212
  function createLoaderForTask(assignedTask) {
7839
8213
  const bucketLoader = createBucketLoader(
@@ -7841,7 +8215,6 @@ function createLoaderForTask(assignedTask) {
7841
8215
  assignedTask.bucketPathPattern,
7842
8216
  {
7843
8217
  defaultLocale: assignedTask.sourceLocale,
7844
- isCacheRestore: false,
7845
8218
  injectLocale: assignedTask.injectLocale
7846
8219
  },
7847
8220
  assignedTask.lockedKeys,
@@ -7880,7 +8253,7 @@ function createWorkerTask(args) {
7880
8253
  const processableData = _lodash2.default.chain(sourceData).entries().filter(
7881
8254
  ([key, value]) => delta.added.includes(key) || delta.updated.includes(key) || !!args.ctx.flags.force
7882
8255
  ).filter(
7883
- ([key]) => !assignedTask.onlyKeys.length || _optionalChain([assignedTask, 'access', _223 => _223.onlyKeys, 'optionalAccess', _224 => _224.some, 'call', _225 => _225(
8256
+ ([key]) => !assignedTask.onlyKeys.length || _optionalChain([assignedTask, 'access', _230 => _230.onlyKeys, 'optionalAccess', _231 => _231.some, 'call', _232 => _232(
7884
8257
  (pattern) => minimatch(key, pattern)
7885
8258
  )])
7886
8259
  ).fromPairs().value();
@@ -7895,33 +8268,47 @@ function createWorkerTask(args) {
7895
8268
  targetData,
7896
8269
  processableData
7897
8270
  },
7898
- (progress) => {
8271
+ async (progress, _sourceChunk, processedChunk) => {
8272
+ await args.ioLimiter(async () => {
8273
+ await bucketLoader.pull(assignedTask.sourceLocale);
8274
+ const latestTargetData = await bucketLoader.pull(
8275
+ assignedTask.targetLocale
8276
+ );
8277
+ const _partialData = _lodash2.default.merge(
8278
+ {},
8279
+ latestTargetData,
8280
+ processedChunk
8281
+ );
8282
+ const finalChunkTargetData = processRenamedKeys(
8283
+ delta,
8284
+ _partialData
8285
+ );
8286
+ await bucketLoader.push(
8287
+ assignedTask.targetLocale,
8288
+ finalChunkTargetData
8289
+ );
8290
+ });
7899
8291
  subTask.title = createWorkerStatusMessage({
7900
8292
  assignedTask,
7901
8293
  percentage: progress
7902
8294
  });
7903
8295
  }
7904
8296
  );
7905
- let finalTargetData = _lodash2.default.merge(
8297
+ const finalTargetData = _lodash2.default.merge(
7906
8298
  {},
7907
8299
  sourceData,
7908
8300
  targetData,
7909
8301
  processedTargetData
7910
8302
  );
7911
- finalTargetData = _lodash2.default.chain(finalTargetData).entries().map(([key, value]) => {
7912
- const renaming = delta.renamed.find(
7913
- ([oldKey]) => oldKey === key
7914
- );
7915
- if (!renaming) {
7916
- return [key, value];
7917
- }
7918
- return [renaming[1], value];
7919
- }).fromPairs().value();
8303
+ const finalRenamedTargetData = processRenamedKeys(
8304
+ delta,
8305
+ finalTargetData
8306
+ );
7920
8307
  await args.ioLimiter(async () => {
7921
8308
  await bucketLoader.pull(assignedTask.sourceLocale);
7922
8309
  await bucketLoader.push(
7923
8310
  assignedTask.targetLocale,
7924
- finalTargetData
8311
+ finalRenamedTargetData
7925
8312
  );
7926
8313
  const checksums2 = await deltaProcessor.createChecksums(sourceData);
7927
8314
  await deltaProcessor.saveChecksums(checksums2);
@@ -7945,6 +8332,144 @@ function countTasks(ctx, predicate) {
7945
8332
  ([task, result]) => predicate(task, result)
7946
8333
  ).length;
7947
8334
  }
8335
+ function processRenamedKeys(delta, targetData) {
8336
+ return _lodash2.default.chain(targetData).entries().map(([key, value]) => {
8337
+ const renaming = delta.renamed.find(([oldKey]) => oldKey === key);
8338
+ if (!renaming) {
8339
+ return [key, value];
8340
+ }
8341
+ return [renaming[1], value];
8342
+ }).fromPairs().value();
8343
+ }
8344
+
8345
+ // src/cli/cmd/run/watch.ts
8346
+ var _chokidar = require('chokidar'); var chokidar = _interopRequireWildcard(_chokidar);
8347
+
8348
+ async function watch2(ctx) {
8349
+ const debounceDelay = ctx.flags.debounce || 5e3;
8350
+ console.log(_chalk2.default.hex(colors.orange)("[Watch Mode]"));
8351
+ console.log(
8352
+ `\u{1F440} Watching for changes... (Press ${_chalk2.default.yellow("Ctrl+C")} to stop)`
8353
+ );
8354
+ console.log(_chalk2.default.dim(` Debounce delay: ${debounceDelay}ms`));
8355
+ console.log("");
8356
+ const state = {
8357
+ isRunning: false,
8358
+ pendingChanges: /* @__PURE__ */ new Set()
8359
+ };
8360
+ const watchPatterns = await getWatchPatterns(ctx);
8361
+ if (watchPatterns.length === 0) {
8362
+ console.log(_chalk2.default.yellow("\u26A0\uFE0F No source files found to watch"));
8363
+ return;
8364
+ }
8365
+ console.log(_chalk2.default.dim(`Watching ${watchPatterns.length} file pattern(s):`));
8366
+ watchPatterns.forEach((pattern) => {
8367
+ console.log(_chalk2.default.dim(` \u2022 ${pattern}`));
8368
+ });
8369
+ console.log("");
8370
+ const watcher = chokidar.watch(watchPatterns, {
8371
+ ignoreInitial: true,
8372
+ persistent: true,
8373
+ awaitWriteFinish: {
8374
+ stabilityThreshold: 500,
8375
+ pollInterval: 100
8376
+ }
8377
+ });
8378
+ watcher.on("change", (path17) => {
8379
+ handleFileChange(path17, state, ctx);
8380
+ });
8381
+ watcher.on("add", (path17) => {
8382
+ handleFileChange(path17, state, ctx);
8383
+ });
8384
+ watcher.on("unlink", (path17) => {
8385
+ handleFileChange(path17, state, ctx);
8386
+ });
8387
+ watcher.on("error", (error) => {
8388
+ console.error(
8389
+ _chalk2.default.red(
8390
+ `Watch error: ${error instanceof Error ? error.message : String(error)}`
8391
+ )
8392
+ );
8393
+ });
8394
+ process.on("SIGINT", () => {
8395
+ console.log(_chalk2.default.yellow("\n\n\u{1F6D1} Stopping watch mode..."));
8396
+ watcher.close();
8397
+ process.exit(0);
8398
+ });
8399
+ await new Promise(() => {
8400
+ });
8401
+ }
8402
+ async function getWatchPatterns(ctx) {
8403
+ if (!ctx.config) return [];
8404
+ const buckets = getBuckets(ctx.config);
8405
+ const patterns = [];
8406
+ for (const bucket of buckets) {
8407
+ if (ctx.flags.bucket && !ctx.flags.bucket.includes(bucket.type)) {
8408
+ continue;
8409
+ }
8410
+ for (const bucketPath of bucket.paths) {
8411
+ if (ctx.flags.file) {
8412
+ if (!ctx.flags.file.some((f) => bucketPath.pathPattern.includes(f))) {
8413
+ continue;
8414
+ }
8415
+ }
8416
+ const sourceLocale = ctx.flags.sourceLocale || ctx.config.locale.source;
8417
+ const sourcePattern = bucketPath.pathPattern.replace(
8418
+ "[locale]",
8419
+ sourceLocale
8420
+ );
8421
+ patterns.push(sourcePattern);
8422
+ }
8423
+ }
8424
+ return patterns;
8425
+ }
8426
+ function handleFileChange(filePath, state, ctx) {
8427
+ const debounceDelay = ctx.flags.debounce || 5e3;
8428
+ state.pendingChanges.add(filePath);
8429
+ console.log(_chalk2.default.dim(`\u{1F4DD} File changed: ${filePath}`));
8430
+ if (state.debounceTimer) {
8431
+ clearTimeout(state.debounceTimer);
8432
+ }
8433
+ state.debounceTimer = setTimeout(async () => {
8434
+ if (state.isRunning) {
8435
+ console.log(
8436
+ _chalk2.default.yellow("\u23F3 Translation already in progress, skipping...")
8437
+ );
8438
+ return;
8439
+ }
8440
+ await triggerRetranslation(state, ctx);
8441
+ }, debounceDelay);
8442
+ }
8443
+ async function triggerRetranslation(state, ctx) {
8444
+ if (state.isRunning) return;
8445
+ state.isRunning = true;
8446
+ try {
8447
+ const changedFiles = Array.from(state.pendingChanges);
8448
+ state.pendingChanges.clear();
8449
+ console.log(_chalk2.default.hex(colors.green)("\n\u{1F504} Triggering retranslation..."));
8450
+ console.log(_chalk2.default.dim(`Changed files: ${changedFiles.join(", ")}`));
8451
+ console.log("");
8452
+ const runCtx = {
8453
+ ...ctx,
8454
+ tasks: [],
8455
+ results: /* @__PURE__ */ new Map()
8456
+ };
8457
+ await plan(runCtx);
8458
+ if (runCtx.tasks.length === 0) {
8459
+ console.log(_chalk2.default.dim("\u2728 No translation tasks needed"));
8460
+ } else {
8461
+ await execute(runCtx);
8462
+ await renderSummary(runCtx.results);
8463
+ }
8464
+ console.log(_chalk2.default.hex(colors.green)("\u2705 Retranslation completed"));
8465
+ console.log(_chalk2.default.dim("\u{1F440} Continuing to watch for changes...\n"));
8466
+ } catch (error) {
8467
+ console.error(_chalk2.default.red(`\u274C Retranslation failed: ${error.message}`));
8468
+ console.log(_chalk2.default.dim("\u{1F440} Continuing to watch for changes...\n"));
8469
+ } finally {
8470
+ state.isRunning = false;
8471
+ }
8472
+ }
7948
8473
 
7949
8474
  // src/cli/cmd/run/_types.ts
7950
8475
 
@@ -7964,18 +8489,21 @@ var flagsSchema2 = _zod.z.object({
7964
8489
  concurrency: _zod.z.number().positive().default(10),
7965
8490
  debug: _zod.z.boolean().default(false),
7966
8491
  sourceLocale: _zod.z.string().optional(),
7967
- targetLocale: _zod.z.array(_zod.z.string()).optional()
8492
+ targetLocale: _zod.z.array(_zod.z.string()).optional(),
8493
+ watch: _zod.z.boolean().default(false),
8494
+ debounce: _zod.z.number().positive().default(5e3)
8495
+ // 5 seconds default
7968
8496
  });
7969
8497
 
7970
8498
  // src/cli/cmd/run/_utils.ts
7971
8499
  async function determineAuthId(ctx) {
7972
- const isByokMode = !!_optionalChain([ctx, 'access', _226 => _226.config, 'optionalAccess', _227 => _227.provider]);
8500
+ const isByokMode = !!_optionalChain([ctx, 'access', _233 => _233.config, 'optionalAccess', _234 => _234.provider]);
7973
8501
  if (isByokMode) {
7974
8502
  return null;
7975
8503
  } else {
7976
8504
  try {
7977
- const authStatus = await _optionalChain([ctx, 'access', _228 => _228.localizer, 'optionalAccess', _229 => _229.checkAuth, 'call', _230 => _230()]);
7978
- return _optionalChain([authStatus, 'optionalAccess', _231 => _231.username]) || null;
8505
+ const authStatus = await _optionalChain([ctx, 'access', _235 => _235.localizer, 'optionalAccess', _236 => _236.checkAuth, 'call', _237 => _237()]);
8506
+ return _optionalChain([authStatus, 'optionalAccess', _238 => _238.username]) || null;
7979
8507
  } catch (e3) {
7980
8508
  return null;
7981
8509
  }
@@ -8015,6 +8543,13 @@ var run_default = new (0, _interactivecommander.Command)().command("run").descri
8015
8543
  "--concurrency <concurrency>",
8016
8544
  "Number of concurrent tasks to run",
8017
8545
  (val) => parseInt(val)
8546
+ ).option(
8547
+ "--watch",
8548
+ "Watch source files for changes and automatically retranslate"
8549
+ ).option(
8550
+ "--debounce <milliseconds>",
8551
+ "Debounce delay in milliseconds for watch mode (default: 5000ms)",
8552
+ (val) => parseInt(val)
8018
8553
  ).action(async (args) => {
8019
8554
  let authId = null;
8020
8555
  try {
@@ -8044,6 +8579,9 @@ var run_default = new (0, _interactivecommander.Command)().command("run").descri
8044
8579
  await renderSpacer();
8045
8580
  await renderSummary(ctx.results);
8046
8581
  await renderSpacer();
8582
+ if (ctx.flags.watch) {
8583
+ await watch2(ctx);
8584
+ }
8047
8585
  trackEvent(authId, "cmd.run.success", {
8048
8586
  config: ctx.config,
8049
8587
  flags: ctx.flags
@@ -8075,7 +8613,9 @@ var InBranchFlow = class extends IntegrationFlow {
8075
8613
  _child_process.execSync.call(void 0, `git add .`, { stdio: "inherit" });
8076
8614
  _child_process.execSync.call(void 0, `git status --porcelain`, { stdio: "inherit" });
8077
8615
  _child_process.execSync.call(void 0,
8078
- `git commit -m ${escapeShellArg(this.platformKit.config.commitMessage)} --no-verify`,
8616
+ `git commit -m ${escapeShellArg(
8617
+ this.platformKit.config.commitMessage
8618
+ )} --no-verify`,
8079
8619
  {
8080
8620
  stdio: "inherit"
8081
8621
  }
@@ -8123,7 +8663,7 @@ var InBranchFlow = class extends IntegrationFlow {
8123
8663
  _child_process.execSync.call(void 0, `git config --global safe.directory ${process.cwd()}`);
8124
8664
  _child_process.execSync.call(void 0, `git config user.name "${gitConfig.userName}"`);
8125
8665
  _child_process.execSync.call(void 0, `git config user.email "${gitConfig.userEmail}"`);
8126
- _optionalChain([this, 'access', _232 => _232.platformKit, 'optionalAccess', _233 => _233.gitConfig, 'call', _234 => _234()]);
8666
+ _optionalChain([this, 'access', _239 => _239.platformKit, 'optionalAccess', _240 => _240.gitConfig, 'call', _241 => _241()]);
8127
8667
  _child_process.execSync.call(void 0, `git fetch origin ${baseBranchName}`, { stdio: "inherit" });
8128
8668
  _child_process.execSync.call(void 0, `git checkout ${baseBranchName} --`, { stdio: "inherit" });
8129
8669
  if (!processOwnCommits) {
@@ -8155,7 +8695,7 @@ var InBranchFlow = class extends IntegrationFlow {
8155
8695
  // src/cli/cmd/ci/flows/pull-request.ts
8156
8696
  var PullRequestFlow = class extends InBranchFlow {
8157
8697
  async preRun() {
8158
- const canContinue = await _optionalChain([super.preRun.bind(this), 'optionalCall', _235 => _235()]);
8698
+ const canContinue = await _optionalChain([super.preRun.bind(this), 'optionalCall', _242 => _242()]);
8159
8699
  if (!canContinue) {
8160
8700
  return false;
8161
8701
  }
@@ -8198,7 +8738,9 @@ var PullRequestFlow = class extends InBranchFlow {
8198
8738
  this.ora.start("Checking if PR already exists");
8199
8739
  const pullRequestNumber = await this.ensureFreshPr(this.i18nBranchName);
8200
8740
  this.ora.succeed(
8201
- `Pull request ready: ${this.platformKit.buildPullRequestUrl(pullRequestNumber)}`
8741
+ `Pull request ready: ${this.platformKit.buildPullRequestUrl(
8742
+ pullRequestNumber
8743
+ )}`
8202
8744
  );
8203
8745
  }
8204
8746
  calculatePrBranchName() {
@@ -8368,11 +8910,17 @@ var PlatformKit = class {
8368
8910
  get config() {
8369
8911
  const env = _zod2.default.object({
8370
8912
  LINGODOTDEV_API_KEY: _zod2.default.string(),
8371
- LINGODOTDEV_PULL_REQUEST: _zod2.default.preprocess((val) => val === "true" || val === true, _zod2.default.boolean()),
8913
+ LINGODOTDEV_PULL_REQUEST: _zod2.default.preprocess(
8914
+ (val) => val === "true" || val === true,
8915
+ _zod2.default.boolean()
8916
+ ),
8372
8917
  LINGODOTDEV_COMMIT_MESSAGE: _zod2.default.string().optional(),
8373
8918
  LINGODOTDEV_PULL_REQUEST_TITLE: _zod2.default.string().optional(),
8374
8919
  LINGODOTDEV_WORKING_DIRECTORY: _zod2.default.string().optional(),
8375
- LINGODOTDEV_PROCESS_OWN_COMMITS: _zod2.default.preprocess((val) => val === "true" || val === true, _zod2.default.boolean()).optional()
8920
+ LINGODOTDEV_PROCESS_OWN_COMMITS: _zod2.default.preprocess(
8921
+ (val) => val === "true" || val === true,
8922
+ _zod2.default.boolean()
8923
+ ).optional()
8376
8924
  }).parse(process.env);
8377
8925
  return {
8378
8926
  replexicaApiKey: env.LINGODOTDEV_API_KEY,
@@ -8410,10 +8958,10 @@ var BitbucketPlatformKit = class extends PlatformKit {
8410
8958
  repo_slug: this.platformConfig.repositoryName,
8411
8959
  state: "OPEN"
8412
8960
  }).then(({ data: { values } }) => {
8413
- return _optionalChain([values, 'optionalAccess', _236 => _236.find, 'call', _237 => _237(
8414
- ({ source, destination }) => _optionalChain([source, 'optionalAccess', _238 => _238.branch, 'optionalAccess', _239 => _239.name]) === branch && _optionalChain([destination, 'optionalAccess', _240 => _240.branch, 'optionalAccess', _241 => _241.name]) === this.platformConfig.baseBranchName
8961
+ return _optionalChain([values, 'optionalAccess', _243 => _243.find, 'call', _244 => _244(
8962
+ ({ source, destination }) => _optionalChain([source, 'optionalAccess', _245 => _245.branch, 'optionalAccess', _246 => _246.name]) === branch && _optionalChain([destination, 'optionalAccess', _247 => _247.branch, 'optionalAccess', _248 => _248.name]) === this.platformConfig.baseBranchName
8415
8963
  )]);
8416
- }).then((pr) => _optionalChain([pr, 'optionalAccess', _242 => _242.id]));
8964
+ }).then((pr) => _optionalChain([pr, 'optionalAccess', _249 => _249.id]));
8417
8965
  }
8418
8966
  async closePullRequest({ pullRequestNumber }) {
8419
8967
  await this.bb.repositories.declinePullRequest({
@@ -8509,7 +9057,7 @@ var GitHubPlatformKit = class extends PlatformKit {
8509
9057
  repo: this.platformConfig.repositoryName,
8510
9058
  base: this.platformConfig.baseBranchName,
8511
9059
  state: "open"
8512
- }).then(({ data }) => data[0]).then((pr) => _optionalChain([pr, 'optionalAccess', _243 => _243.number]));
9060
+ }).then(({ data }) => data[0]).then((pr) => _optionalChain([pr, 'optionalAccess', _250 => _250.number]));
8513
9061
  }
8514
9062
  async closePullRequest({ pullRequestNumber }) {
8515
9063
  await this.octokit.rest.pulls.update({
@@ -8636,7 +9184,7 @@ var GitlabPlatformKit = class extends PlatformKit {
8636
9184
  sourceBranch: branch,
8637
9185
  state: "opened"
8638
9186
  });
8639
- return _optionalChain([mergeRequests, 'access', _244 => _244[0], 'optionalAccess', _245 => _245.iid]);
9187
+ return _optionalChain([mergeRequests, 'access', _251 => _251[0], 'optionalAccess', _252 => _252.iid]);
8640
9188
  }
8641
9189
  async closePullRequest({
8642
9190
  pullRequestNumber
@@ -8726,7 +9274,7 @@ var ci_default = new (0, _interactivecommander.Command)().command("ci").descript
8726
9274
  }
8727
9275
  const env = {
8728
9276
  LINGODOTDEV_API_KEY: settings.auth.apiKey,
8729
- LINGODOTDEV_PULL_REQUEST: _optionalChain([options, 'access', _246 => _246.pullRequest, 'optionalAccess', _247 => _247.toString, 'call', _248 => _248()]) || "false",
9277
+ LINGODOTDEV_PULL_REQUEST: _optionalChain([options, 'access', _253 => _253.pullRequest, 'optionalAccess', _254 => _254.toString, 'call', _255 => _255()]) || "false",
8730
9278
  ...options.commitMessage && {
8731
9279
  LINGODOTDEV_COMMIT_MESSAGE: options.commitMessage
8732
9280
  },
@@ -8746,7 +9294,7 @@ var ci_default = new (0, _interactivecommander.Command)().command("ci").descript
8746
9294
  const { isPullRequestMode } = platformKit.config;
8747
9295
  ora.info(`Pull request mode: ${isPullRequestMode ? "on" : "off"}`);
8748
9296
  const flow = isPullRequestMode ? new PullRequestFlow(ora, platformKit) : new InBranchFlow(ora, platformKit);
8749
- const canRun = await _optionalChain([flow, 'access', _249 => _249.preRun, 'optionalCall', _250 => _250()]);
9297
+ const canRun = await _optionalChain([flow, 'access', _256 => _256.preRun, 'optionalCall', _257 => _257()]);
8750
9298
  if (canRun === false) {
8751
9299
  return;
8752
9300
  }
@@ -8756,7 +9304,7 @@ var ci_default = new (0, _interactivecommander.Command)().command("ci").descript
8756
9304
  if (!hasChanges) {
8757
9305
  return;
8758
9306
  }
8759
- await _optionalChain([flow, 'access', _251 => _251.postRun, 'optionalCall', _252 => _252()]);
9307
+ await _optionalChain([flow, 'access', _258 => _258.postRun, 'optionalCall', _259 => _259()]);
8760
9308
  });
8761
9309
  function parseBooleanArg(val) {
8762
9310
  if (val === true) return true;
@@ -8772,11 +9320,29 @@ function parseBooleanArg(val) {
8772
9320
 
8773
9321
 
8774
9322
 
9323
+
9324
+
9325
+
9326
+
8775
9327
  var _clitable3 = require('cli-table3'); var _clitable32 = _interopRequireDefault(_clitable3);
8776
- var status_default = new (0, _interactivecommander.Command)().command("status").description("Show the status of the localization process").helpOption("-h, --help", "Show help").option("--locale <locale>", "Locale to process", (val, prev) => prev ? [...prev, val] : [val]).option("--bucket <bucket>", "Bucket to process", (val, prev) => prev ? [...prev, val] : [val]).option(
9328
+ var status_default = new (0, _interactivecommander.Command)().command("status").description("Show the status of the localization process").helpOption("-h, --help", "Show help").option(
9329
+ "--locale <locale>",
9330
+ "Locale to process",
9331
+ (val, prev) => prev ? [...prev, val] : [val]
9332
+ ).option(
9333
+ "--bucket <bucket>",
9334
+ "Bucket to process",
9335
+ (val, prev) => prev ? [...prev, val] : [val]
9336
+ ).option(
8777
9337
  "--file [files...]",
8778
9338
  "File to process. Process only a specific path, may contain asterisk * to match multiple files."
8779
- ).option("--force", "Ignore lockfile and process all keys, useful for estimating full re-translation").option("--verbose", "Show detailed output including key-level word counts").option("--api-key <api-key>", "Explicitly set the API key to use, override the default API key from settings").action(async function(options) {
9339
+ ).option(
9340
+ "--force",
9341
+ "Ignore lockfile and process all keys, useful for estimating full re-translation"
9342
+ ).option("--verbose", "Show detailed output including key-level word counts").option(
9343
+ "--api-key <api-key>",
9344
+ "Explicitly set the API key to use, override the default API key from settings"
9345
+ ).action(async function(options) {
8780
9346
  const ora = _ora2.default.call(void 0, );
8781
9347
  const flags = parseFlags2(options);
8782
9348
  let authId = null;
@@ -8807,17 +9373,23 @@ var status_default = new (0, _interactivecommander.Command)().command("status").
8807
9373
  flags
8808
9374
  });
8809
9375
  let buckets = getBuckets(i18nConfig);
8810
- if (_optionalChain([flags, 'access', _253 => _253.bucket, 'optionalAccess', _254 => _254.length])) {
8811
- buckets = buckets.filter((bucket) => flags.bucket.includes(bucket.type));
9376
+ if (_optionalChain([flags, 'access', _260 => _260.bucket, 'optionalAccess', _261 => _261.length])) {
9377
+ buckets = buckets.filter(
9378
+ (bucket) => flags.bucket.includes(bucket.type)
9379
+ );
8812
9380
  }
8813
9381
  ora.succeed("Buckets retrieved");
8814
- if (_optionalChain([flags, 'access', _255 => _255.file, 'optionalAccess', _256 => _256.length])) {
9382
+ if (_optionalChain([flags, 'access', _262 => _262.file, 'optionalAccess', _263 => _263.length])) {
8815
9383
  buckets = buckets.map((bucket) => {
8816
- const paths = bucket.paths.filter((path17) => flags.file.find((file) => _optionalChain([path17, 'access', _257 => _257.pathPattern, 'optionalAccess', _258 => _258.match, 'call', _259 => _259(file)])));
9384
+ const paths = bucket.paths.filter(
9385
+ (path17) => flags.file.find((file) => _optionalChain([path17, 'access', _264 => _264.pathPattern, 'optionalAccess', _265 => _265.match, 'call', _266 => _266(file)]))
9386
+ );
8817
9387
  return { ...bucket, paths };
8818
9388
  }).filter((bucket) => bucket.paths.length > 0);
8819
9389
  if (buckets.length === 0) {
8820
- ora.fail("No buckets found. All buckets were filtered out by --file option.");
9390
+ ora.fail(
9391
+ "No buckets found. All buckets were filtered out by --file option."
9392
+ );
8821
9393
  process.exit(1);
8822
9394
  } else {
8823
9395
  ora.info(`\x1B[36mProcessing only filtered buckets:\x1B[0m`);
@@ -8829,7 +9401,7 @@ var status_default = new (0, _interactivecommander.Command)().command("status").
8829
9401
  });
8830
9402
  }
8831
9403
  }
8832
- const targetLocales = _optionalChain([flags, 'access', _260 => _260.locale, 'optionalAccess', _261 => _261.length]) ? flags.locale : i18nConfig.locale.targets;
9404
+ const targetLocales = _optionalChain([flags, 'access', _267 => _267.locale, 'optionalAccess', _268 => _268.length]) ? flags.locale : i18nConfig.locale.targets;
8833
9405
  let totalSourceKeyCount = 0;
8834
9406
  let uniqueKeysToTranslate = 0;
8835
9407
  let totalExistingTranslations = 0;
@@ -8850,13 +9422,17 @@ var status_default = new (0, _interactivecommander.Command)().command("status").
8850
9422
  console.log();
8851
9423
  ora.info(`Analyzing bucket: ${bucket.type}`);
8852
9424
  for (const bucketPath of bucket.paths) {
8853
- const bucketOra = _ora2.default.call(void 0, { indent: 2 }).info(`Analyzing path: ${bucketPath.pathPattern}`);
8854
- const sourceLocale = __spec.resolveOverriddenLocale.call(void 0, i18nConfig.locale.source, bucketPath.delimiter);
9425
+ const bucketOra = _ora2.default.call(void 0, { indent: 2 }).info(
9426
+ `Analyzing path: ${bucketPath.pathPattern}`
9427
+ );
9428
+ const sourceLocale = __spec.resolveOverriddenLocale.call(void 0,
9429
+ i18nConfig.locale.source,
9430
+ bucketPath.delimiter
9431
+ );
8855
9432
  const bucketLoader = createBucketLoader(
8856
9433
  bucket.type,
8857
9434
  bucketPath.pathPattern,
8858
9435
  {
8859
- isCacheRestore: false,
8860
9436
  defaultLocale: sourceLocale,
8861
9437
  injectLocale: bucket.injectLocale
8862
9438
  },
@@ -8895,8 +9471,13 @@ var status_default = new (0, _interactivecommander.Command)().command("status").
8895
9471
  }
8896
9472
  fileStats[filePath].wordCount = sourceWordCount;
8897
9473
  for (const _targetLocale of targetLocales) {
8898
- const targetLocale = __spec.resolveOverriddenLocale.call(void 0, _targetLocale, bucketPath.delimiter);
8899
- bucketOra.start(`[${sourceLocale} -> ${targetLocale}] Analyzing translation status...`);
9474
+ const targetLocale = __spec.resolveOverriddenLocale.call(void 0,
9475
+ _targetLocale,
9476
+ bucketPath.delimiter
9477
+ );
9478
+ bucketOra.start(
9479
+ `[${sourceLocale} -> ${targetLocale}] Analyzing translation status...`
9480
+ );
8900
9481
  let targetData = {};
8901
9482
  let fileExists = true;
8902
9483
  try {
@@ -8912,13 +9493,20 @@ var status_default = new (0, _interactivecommander.Command)().command("status").
8912
9493
  fileStats[filePath].languageStats[_targetLocale].words = sourceWordCount;
8913
9494
  languageStats[_targetLocale].missing += sourceKeys.length;
8914
9495
  languageStats[_targetLocale].words += sourceWordCount;
8915
- totalWordCount.set(_targetLocale, (totalWordCount.get(_targetLocale) || 0) + sourceWordCount);
9496
+ totalWordCount.set(
9497
+ _targetLocale,
9498
+ (totalWordCount.get(_targetLocale) || 0) + sourceWordCount
9499
+ );
8916
9500
  bucketOra.succeed(
8917
- `[${sourceLocale} -> ${targetLocale}] ${_chalk2.default.red(`0% complete`)} (0/${sourceKeys.length} keys) - file not found`
9501
+ `[${sourceLocale} -> ${targetLocale}] ${_chalk2.default.red(
9502
+ `0% complete`
9503
+ )} (0/${sourceKeys.length} keys) - file not found`
8918
9504
  );
8919
9505
  continue;
8920
9506
  }
8921
- const deltaProcessor = createDeltaProcessor(bucketPath.pathPattern);
9507
+ const deltaProcessor = createDeltaProcessor(
9508
+ bucketPath.pathPattern
9509
+ );
8922
9510
  const checksums = await deltaProcessor.loadChecksums();
8923
9511
  const delta = await deltaProcessor.calculateDelta({
8924
9512
  sourceData,
@@ -8927,7 +9515,9 @@ var status_default = new (0, _interactivecommander.Command)().command("status").
8927
9515
  });
8928
9516
  const missingKeys = delta.added;
8929
9517
  const updatedKeys = delta.updated;
8930
- const completeKeys = sourceKeys.filter((key) => !missingKeys.includes(key) && !updatedKeys.includes(key));
9518
+ const completeKeys = sourceKeys.filter(
9519
+ (key) => !missingKeys.includes(key) && !updatedKeys.includes(key)
9520
+ );
8931
9521
  let wordsToTranslate = 0;
8932
9522
  const keysToProcess = flags.force ? sourceKeys : [...missingKeys, ...updatedKeys];
8933
9523
  for (const key of keysToProcess) {
@@ -8945,25 +9535,39 @@ var status_default = new (0, _interactivecommander.Command)().command("status").
8945
9535
  languageStats[_targetLocale].updated += updatedKeys.length;
8946
9536
  languageStats[_targetLocale].complete += completeKeys.length;
8947
9537
  languageStats[_targetLocale].words += wordsToTranslate;
8948
- totalWordCount.set(_targetLocale, (totalWordCount.get(_targetLocale) || 0) + wordsToTranslate);
9538
+ totalWordCount.set(
9539
+ _targetLocale,
9540
+ (totalWordCount.get(_targetLocale) || 0) + wordsToTranslate
9541
+ );
8949
9542
  const totalKeysInFile = sourceKeys.length;
8950
9543
  const completionPercent = (completeKeys.length / totalKeysInFile * 100).toFixed(1);
8951
9544
  if (missingKeys.length === 0 && updatedKeys.length === 0) {
8952
9545
  bucketOra.succeed(
8953
- `[${sourceLocale} -> ${targetLocale}] ${_chalk2.default.green(`100% complete`)} (${completeKeys.length}/${totalKeysInFile} keys)`
9546
+ `[${sourceLocale} -> ${targetLocale}] ${_chalk2.default.green(
9547
+ `100% complete`
9548
+ )} (${completeKeys.length}/${totalKeysInFile} keys)`
8954
9549
  );
8955
9550
  } else {
8956
9551
  const message = `[${sourceLocale} -> ${targetLocale}] ${parseFloat(completionPercent) > 50 ? _chalk2.default.yellow(`${completionPercent}% complete`) : _chalk2.default.red(`${completionPercent}% complete`)} (${completeKeys.length}/${totalKeysInFile} keys)`;
8957
9552
  bucketOra.succeed(message);
8958
9553
  if (flags.verbose) {
8959
9554
  if (missingKeys.length > 0) {
8960
- console.log(` ${_chalk2.default.red(`Missing:`)} ${missingKeys.length} keys, ~${wordsToTranslate} words`);
8961
9555
  console.log(
8962
- ` ${_chalk2.default.dim(`Example missing: ${missingKeys.slice(0, 2).join(", ")}${missingKeys.length > 2 ? "..." : ""}`)}`
9556
+ ` ${_chalk2.default.red(`Missing:`)} ${missingKeys.length} keys, ~${wordsToTranslate} words`
9557
+ );
9558
+ console.log(
9559
+ ` ${_chalk2.default.red(`Missing:`)} ${missingKeys.length} keys, ~${wordsToTranslate} words`
9560
+ );
9561
+ console.log(
9562
+ ` ${_chalk2.default.dim(
9563
+ `Example missing: ${missingKeys.slice(0, 2).join(", ")}${missingKeys.length > 2 ? "..." : ""}`
9564
+ )}`
8963
9565
  );
8964
9566
  }
8965
9567
  if (updatedKeys.length > 0) {
8966
- console.log(` ${_chalk2.default.yellow(`Updated:`)} ${updatedKeys.length} keys that changed in source`);
9568
+ console.log(
9569
+ ` ${_chalk2.default.yellow(`Updated:`)} ${updatedKeys.length} keys that changed in source`
9570
+ );
8967
9571
  }
8968
9572
  }
8969
9573
  }
@@ -8973,9 +9577,12 @@ var status_default = new (0, _interactivecommander.Command)().command("status").
8973
9577
  ora.fail(`Failed to analyze bucket ${bucket.type}: ${error.message}`);
8974
9578
  }
8975
9579
  }
8976
- const totalKeysNeedingTranslation = Object.values(languageStats).reduce((sum, stats) => {
8977
- return sum + stats.missing + stats.updated;
8978
- }, 0);
9580
+ const totalKeysNeedingTranslation = Object.values(languageStats).reduce(
9581
+ (sum, stats) => {
9582
+ return sum + stats.missing + stats.updated;
9583
+ },
9584
+ 0
9585
+ );
8979
9586
  const totalCompletedKeys = totalSourceKeyCount - totalKeysNeedingTranslation / targetLocales.length;
8980
9587
  console.log();
8981
9588
  ora.succeed(_chalk2.default.green(`Localization status completed.`));
@@ -8985,12 +9592,26 @@ var status_default = new (0, _interactivecommander.Command)().command("status").
8985
9592
  console.log(_chalk2.default.bold.cyan(`\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D`));
8986
9593
  console.log(_chalk2.default.bold(`
8987
9594
  \u{1F4DD} SOURCE CONTENT:`));
8988
- console.log(`\u2022 Source language: ${_chalk2.default.green(i18nConfig.locale.source)}`);
8989
- console.log(`\u2022 Source keys: ${_chalk2.default.yellow(totalSourceKeyCount.toString())} keys across all files`);
9595
+ console.log(
9596
+ `\u2022 Source language: ${_chalk2.default.green(i18nConfig.locale.source)}`
9597
+ );
9598
+ console.log(
9599
+ `\u2022 Source keys: ${_chalk2.default.yellow(
9600
+ totalSourceKeyCount.toString()
9601
+ )} keys across all files`
9602
+ );
8990
9603
  console.log(_chalk2.default.bold(`
8991
9604
  \u{1F310} LANGUAGE BY LANGUAGE BREAKDOWN:`));
8992
9605
  const table = new (0, _clitable32.default)({
8993
- head: ["Language", "Status", "Complete", "Missing", "Updated", "Total Keys", "Words to Translate"],
9606
+ head: [
9607
+ "Language",
9608
+ "Status",
9609
+ "Complete",
9610
+ "Missing",
9611
+ "Updated",
9612
+ "Total Keys",
9613
+ "Words to Translate"
9614
+ ],
8994
9615
  style: {
8995
9616
  head: ["white"],
8996
9617
  // White color for headers
@@ -9039,15 +9660,21 @@ var status_default = new (0, _interactivecommander.Command)().command("status").
9039
9660
  console.log(_chalk2.default.bold(`
9040
9661
  \u{1F4CA} USAGE ESTIMATE:`));
9041
9662
  console.log(
9042
- `\u2022 WORDS TO BE CONSUMED: ~${_chalk2.default.yellow.bold(totalWordsToTranslate.toLocaleString())} words across all languages`
9663
+ `\u2022 WORDS TO BE CONSUMED: ~${_chalk2.default.yellow.bold(
9664
+ totalWordsToTranslate.toLocaleString()
9665
+ )} words across all languages`
9666
+ );
9667
+ console.log(
9668
+ ` (Words are counted from source language for keys that need translation in target languages)`
9043
9669
  );
9044
- console.log(` (Words are counted from source language for keys that need translation in target languages)`);
9045
9670
  if (targetLocales.length > 1) {
9046
9671
  console.log(`\u2022 Per-language breakdown:`);
9047
9672
  for (const locale of targetLocales) {
9048
9673
  const words = totalWordCount.get(locale) || 0;
9049
9674
  const percent = (words / totalWordsToTranslate * 100).toFixed(1);
9050
- console.log(` - ${locale}: ~${words.toLocaleString()} words (${percent}% of total)`);
9675
+ console.log(
9676
+ ` - ${locale}: ~${words.toLocaleString()} words (${percent}% of total)`
9677
+ );
9051
9678
  }
9052
9679
  }
9053
9680
  if (flags.confirm && Object.keys(fileStats).length > 0) {
@@ -9057,7 +9684,9 @@ var status_default = new (0, _interactivecommander.Command)().command("status").
9057
9684
  if (stats.sourceKeys === 0) return;
9058
9685
  console.log(_chalk2.default.bold(`
9059
9686
  \u2022 ${path17}:`));
9060
- console.log(` ${stats.sourceKeys} source keys, ~${stats.wordCount.toLocaleString()} source words`);
9687
+ console.log(
9688
+ ` ${stats.sourceKeys} source keys, ~${stats.wordCount.toLocaleString()} source words`
9689
+ );
9061
9690
  const fileTable = new (0, _clitable32.default)({
9062
9691
  head: ["Language", "Status", "Details"],
9063
9692
  style: {
@@ -9084,8 +9713,10 @@ var status_default = new (0, _interactivecommander.Command)().command("status").
9084
9713
  let details = "";
9085
9714
  if (langStats.missing > 0 || langStats.updated > 0) {
9086
9715
  const parts = [];
9087
- if (langStats.missing > 0) parts.push(`${langStats.missing} missing`);
9088
- if (langStats.updated > 0) parts.push(`${langStats.updated} changed`);
9716
+ if (langStats.missing > 0)
9717
+ parts.push(`${langStats.missing} missing`);
9718
+ if (langStats.updated > 0)
9719
+ parts.push(`${langStats.updated} changed`);
9089
9720
  details = `${parts.join(", ")}, ~${langStats.words} words`;
9090
9721
  } else {
9091
9722
  details = "All keys translated";
@@ -9098,7 +9729,9 @@ var status_default = new (0, _interactivecommander.Command)().command("status").
9098
9729
  const completeLanguages = targetLocales.filter(
9099
9730
  (locale) => languageStats[locale].missing === 0 && languageStats[locale].updated === 0
9100
9731
  );
9101
- const missingLanguages = targetLocales.filter((locale) => languageStats[locale].complete === 0);
9732
+ const missingLanguages = targetLocales.filter(
9733
+ (locale) => languageStats[locale].complete === 0
9734
+ );
9102
9735
  console.log(_chalk2.default.bold.green(`
9103
9736
  \u{1F4A1} OPTIMIZATION TIPS:`));
9104
9737
  if (missingLanguages.length > 0) {
@@ -9113,7 +9746,9 @@ var status_default = new (0, _interactivecommander.Command)().command("status").
9113
9746
  }
9114
9747
  if (targetLocales.length > 1) {
9115
9748
  console.log(`\u2022 Translating one language at a time reduces complexity`);
9116
- console.log(`\u2022 Try 'lingo.dev@latest i18n --locale ${targetLocales[0]}' to process just one language`);
9749
+ console.log(
9750
+ `\u2022 Try 'lingo.dev@latest i18n --locale ${targetLocales[0]}' to process just one language`
9751
+ );
9117
9752
  }
9118
9753
  trackEvent(authId || "status", "cmd.status.success", {
9119
9754
  i18nConfig,
@@ -9170,12 +9805,14 @@ function validateParams2(i18nConfig, flags) {
9170
9805
  message: "No buckets found in i18n.json. Please add at least one bucket containing i18n content.",
9171
9806
  docUrl: "bucketNotFound"
9172
9807
  });
9173
- } else if (_optionalChain([flags, 'access', _262 => _262.locale, 'optionalAccess', _263 => _263.some, 'call', _264 => _264((locale) => !i18nConfig.locale.targets.includes(locale))])) {
9808
+ } else if (_optionalChain([flags, 'access', _269 => _269.locale, 'optionalAccess', _270 => _270.some, 'call', _271 => _271((locale) => !i18nConfig.locale.targets.includes(locale))])) {
9174
9809
  throw new CLIError({
9175
9810
  message: `One or more specified locales do not exist in i18n.json locale.targets. Please add them to the list and try again.`,
9176
9811
  docUrl: "localeTargetNotFound"
9177
9812
  });
9178
- } else if (_optionalChain([flags, 'access', _265 => _265.bucket, 'optionalAccess', _266 => _266.some, 'call', _267 => _267((bucket) => !i18nConfig.buckets[bucket])])) {
9813
+ } else if (_optionalChain([flags, 'access', _272 => _272.bucket, 'optionalAccess', _273 => _273.some, 'call', _274 => _274(
9814
+ (bucket) => !i18nConfig.buckets[bucket]
9815
+ )])) {
9179
9816
  throw new CLIError({
9180
9817
  message: `One or more specified buckets do not exist in i18n.json. Please add them to the list and try again.`,
9181
9818
  docUrl: "bucketNotFound"
@@ -9220,7 +9857,9 @@ var may_the_fourth_default = new (0, _interactivecommander.Command)().command("m
9220
9857
  });
9221
9858
  await renderSpacer2();
9222
9859
  console.log(
9223
- `${_chalk2.default.hex(colors2.green)("We hope you enjoyed it! :)")} ${_chalk2.default.hex(colors2.blue)("May the Fourth be with you! \u{1F680}")}`
9860
+ `${_chalk2.default.hex(colors2.green)("We hope you enjoyed it! :)")} ${_chalk2.default.hex(
9861
+ colors2.blue
9862
+ )("May the Fourth be with you! \u{1F680}")}`
9224
9863
  );
9225
9864
  await renderSpacer2();
9226
9865
  console.log(_chalk2.default.dim(`---`));
@@ -9246,7 +9885,9 @@ async function renderBanner2() {
9246
9885
  }
9247
9886
  async function renderHero2() {
9248
9887
  console.log(
9249
- `\u26A1\uFE0F ${_chalk2.default.hex(colors2.green)("Lingo.dev")} - open-source, AI-powered i18n CLI for web & mobile localization.`
9888
+ `\u26A1\uFE0F ${_chalk2.default.hex(colors2.green)(
9889
+ "Lingo.dev"
9890
+ )} - open-source, AI-powered i18n CLI for web & mobile localization.`
9250
9891
  );
9251
9892
  console.log(" ");
9252
9893
  console.log(
@@ -9258,7 +9899,7 @@ async function renderHero2() {
9258
9899
  // package.json
9259
9900
  var package_default = {
9260
9901
  name: "lingo.dev",
9261
- version: "0.100.1",
9902
+ version: "0.102.0",
9262
9903
  description: "Lingo.dev CLI",
9263
9904
  private: false,
9264
9905
  publishConfig: {
@@ -9372,6 +10013,7 @@ var package_default = {
9372
10013
  dependencies: {
9373
10014
  "@ai-sdk/anthropic": "^1.2.11",
9374
10015
  "@ai-sdk/google": "^1.2.19",
10016
+ "@ai-sdk/mistral": "^1.2.8",
9375
10017
  "@ai-sdk/openai": "^1.3.22",
9376
10018
  "@babel/generator": "^7.27.1",
9377
10019
  "@babel/parser": "^7.27.1",
@@ -9392,6 +10034,7 @@ var package_default = {
9392
10034
  ai: "^4.3.15",
9393
10035
  bitbucket: "^2.12.0",
9394
10036
  chalk: "^5.4.1",
10037
+ chokidar: "^4.0.3",
9395
10038
  "cli-progress": "^3.12.0",
9396
10039
  "cli-table3": "^0.6.5",
9397
10040
  cors: "^2.8.5",
@@ -9460,6 +10103,7 @@ var package_default = {
9460
10103
  },
9461
10104
  devDependencies: {
9462
10105
  "@types/babel__generator": "^7.27.0",
10106
+ "@types/chokidar": "^2.1.7",
9463
10107
  "@types/cli-progress": "^3.11.6",
9464
10108
  "@types/cors": "^2.8.17",
9465
10109
  "@types/diff": "^7.0.0",
@@ -9488,6 +10132,167 @@ var package_default = {
9488
10132
  packageManager: "pnpm@9.12.3"
9489
10133
  };
9490
10134
 
10135
+ // src/cli/cmd/purge.ts
10136
+
10137
+
10138
+
10139
+
10140
+ var purge_default = new (0, _interactivecommander.Command)().command("purge").description(
10141
+ "Remove translations for given --bucket, --file, --key, --locale"
10142
+ ).helpOption("-h, --help", "Show help").option(
10143
+ "--bucket <bucket>",
10144
+ "Bucket to process",
10145
+ (val, prev) => prev ? [...prev, val] : [val]
10146
+ ).option(
10147
+ "--file [files...]",
10148
+ "File(s) to process. Only process files that match the given glob pattern(s)."
10149
+ ).option(
10150
+ "--key <key>",
10151
+ "Key to remove. Remove all translation keys matching the given glob pattern."
10152
+ ).option(
10153
+ "--locale <locale>",
10154
+ "Locale to process",
10155
+ (val, prev) => prev ? [...prev, val] : [val]
10156
+ ).option(
10157
+ "--yes-really",
10158
+ "Skip interactive confirmation and delete without asking."
10159
+ ).action(async function(options) {
10160
+ const ora = _ora2.default.call(void 0, );
10161
+ try {
10162
+ ora.start("Loading configuration...");
10163
+ const i18nConfig = getConfig();
10164
+ if (!i18nConfig) {
10165
+ throw new Error("i18n.json not found. Please run `lingo.dev init`.");
10166
+ }
10167
+ ora.succeed("Configuration loaded");
10168
+ let buckets = getBuckets(i18nConfig);
10169
+ if (options.bucket && options.bucket.length) {
10170
+ buckets = buckets.filter(
10171
+ (bucket) => options.bucket.includes(bucket.type)
10172
+ );
10173
+ }
10174
+ if (options.file && options.file.length) {
10175
+ buckets = buckets.map((bucket) => {
10176
+ const paths = bucket.paths.filter(
10177
+ (bucketPath) => _optionalChain([options, 'access', _275 => _275.file, 'optionalAccess', _276 => _276.some, 'call', _277 => _277((f) => bucketPath.pathPattern.includes(f))])
10178
+ );
10179
+ return { ...bucket, paths };
10180
+ }).filter((bucket) => bucket.paths.length > 0);
10181
+ if (buckets.length === 0) {
10182
+ ora.fail("All files were filtered out by --file option.");
10183
+ process.exit(1);
10184
+ }
10185
+ }
10186
+ const sourceLocale = i18nConfig.locale.source;
10187
+ const targetLocales = options.locale && options.locale.length ? options.locale : i18nConfig.locale.targets;
10188
+ let removedAny = false;
10189
+ for (const bucket of buckets) {
10190
+ console.log();
10191
+ ora.info(`Processing bucket: ${bucket.type}`);
10192
+ for (const bucketPath of bucket.paths) {
10193
+ for (const _targetLocale of targetLocales) {
10194
+ const targetLocale = __spec.resolveOverriddenLocale.call(void 0,
10195
+ _targetLocale,
10196
+ bucketPath.delimiter
10197
+ );
10198
+ const bucketOra = _ora2.default.call(void 0, { indent: 2 }).start(
10199
+ `Processing path: ${bucketPath.pathPattern} [${targetLocale}]`
10200
+ );
10201
+ try {
10202
+ const bucketLoader = createBucketLoader(
10203
+ bucket.type,
10204
+ bucketPath.pathPattern,
10205
+ {
10206
+ defaultLocale: sourceLocale,
10207
+ injectLocale: bucket.injectLocale
10208
+ },
10209
+ bucket.lockedKeys,
10210
+ bucket.lockedPatterns,
10211
+ bucket.ignoredKeys
10212
+ );
10213
+ await bucketLoader.init();
10214
+ bucketLoader.setDefaultLocale(sourceLocale);
10215
+ await bucketLoader.pull(sourceLocale);
10216
+ let targetData = await bucketLoader.pull(targetLocale);
10217
+ if (!targetData || Object.keys(targetData).length === 0) {
10218
+ bucketOra.info(
10219
+ `No translations found for ${bucketPath.pathPattern} [${targetLocale}]`
10220
+ );
10221
+ continue;
10222
+ }
10223
+ let newData = { ...targetData };
10224
+ let keysToRemove = [];
10225
+ if (options.key) {
10226
+ keysToRemove = Object.keys(newData).filter(
10227
+ (k) => minimatch(k, options.key)
10228
+ );
10229
+ } else {
10230
+ keysToRemove = Object.keys(newData);
10231
+ }
10232
+ if (keysToRemove.length > 0) {
10233
+ if (options.key) {
10234
+ bucketOra.info(
10235
+ `About to delete ${keysToRemove.length} key(s) matching '${options.key}' from ${bucketPath.pathPattern} [${targetLocale}]:
10236
+ ${keysToRemove.slice(0, 10).join(", ")}${keysToRemove.length > 10 ? ", ..." : ""}`
10237
+ );
10238
+ } else {
10239
+ bucketOra.info(
10240
+ `About to delete all (${keysToRemove.length}) keys from ${bucketPath.pathPattern} [${targetLocale}]`
10241
+ );
10242
+ }
10243
+ if (!options.yesReally) {
10244
+ bucketOra.warn(
10245
+ "This is a destructive operation. If you are sure, type 'y' to continue. (Use --yes-really to skip this check.)"
10246
+ );
10247
+ const confirmed = await _prompts.confirm.call(void 0, {
10248
+ message: `Delete these keys from ${bucketPath.pathPattern} [${targetLocale}]?`,
10249
+ default: false
10250
+ });
10251
+ if (!confirmed) {
10252
+ bucketOra.info("Skipped by user.");
10253
+ continue;
10254
+ }
10255
+ }
10256
+ for (const key of keysToRemove) {
10257
+ delete newData[key];
10258
+ }
10259
+ removedAny = true;
10260
+ await bucketLoader.push(targetLocale, newData);
10261
+ if (options.key) {
10262
+ bucketOra.succeed(
10263
+ `Removed ${keysToRemove.length} key(s) matching '${options.key}' from ${bucketPath.pathPattern} [${targetLocale}]`
10264
+ );
10265
+ } else {
10266
+ bucketOra.succeed(
10267
+ `Removed all keys (${keysToRemove.length}) from ${bucketPath.pathPattern} [${targetLocale}]`
10268
+ );
10269
+ }
10270
+ } else if (options.key) {
10271
+ bucketOra.info(
10272
+ `No keys matching '${options.key}' found in ${bucketPath.pathPattern} [${targetLocale}]`
10273
+ );
10274
+ } else {
10275
+ bucketOra.info("No keys to remove.");
10276
+ }
10277
+ } catch (error) {
10278
+ const err = error;
10279
+ bucketOra.fail(`Failed: ${err.message}`);
10280
+ }
10281
+ }
10282
+ }
10283
+ }
10284
+ if (!removedAny) {
10285
+ ora.info("No keys were removed.");
10286
+ } else {
10287
+ ora.succeed("Purge completed.");
10288
+ }
10289
+ } catch (error) {
10290
+ const err = error;
10291
+ ora.fail(err.message);
10292
+ process.exit(1);
10293
+ }
10294
+ });
10295
+
9491
10296
  // src/cli/index.ts
9492
10297
  _dotenv2.default.config();
9493
10298
  var cli_default = new (0, _interactivecommander.InteractiveCommand)().name("lingo.dev").description("Lingo.dev CLI").helpOption("-h, --help", "Show help").addHelpText(
@@ -9505,7 +10310,7 @@ ${_gradientstring.vice.call(void 0,
9505
10310
 
9506
10311
  Star the the repo :) https://github.com/LingoDotDev/lingo.dev
9507
10312
  `
9508
- ).version(`v${package_default.version}`, "-v, --version", "Show version").addCommand(init_default).interactive("-y, --no-interactive", "Disable interactive mode").addCommand(i18n_default).addCommand(auth_default).addCommand(login_default).addCommand(logout_default).addCommand(show_default).addCommand(config_default2).addCommand(lockfile_default).addCommand(cleanup_default).addCommand(mcp_default).addCommand(ci_default).addCommand(status_default).addCommand(may_the_fourth_default, { hidden: true }).addCommand(run_default, { hidden: true }).exitOverride((err) => {
10313
+ ).version(`v${package_default.version}`, "-v, --version", "Show version").addCommand(init_default).interactive("-y, --no-interactive", "Disable interactive mode").addCommand(i18n_default).addCommand(auth_default).addCommand(login_default).addCommand(logout_default).addCommand(show_default).addCommand(config_default2).addCommand(lockfile_default).addCommand(cleanup_default).addCommand(mcp_default).addCommand(ci_default).addCommand(status_default).addCommand(may_the_fourth_default, { hidden: true }).addCommand(run_default).addCommand(purge_default).exitOverride((err) => {
9509
10314
  if (err.code === "commander.helpDisplayed" || err.code === "commander.version" || err.code === "commander.help") {
9510
10315
  process.exit(0);
9511
10316
  }