lingo.dev 0.74.15 → 0.74.17

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.mjs CHANGED
@@ -263,15 +263,173 @@ function _getConfigFilePath() {
263
263
  }
264
264
 
265
265
  // src/cli/cmd/init.ts
266
- import { defaultConfig, resolveLocaleCode, bucketTypes } from "@lingo.dev/_spec";
267
- import fs3 from "fs";
268
- import path3 from "path";
266
+ import { defaultConfig, resolveLocaleCode as resolveLocaleCode2, bucketTypes } from "@lingo.dev/_spec";
267
+ import fs4 from "fs";
268
+ import path5 from "path";
269
269
  import { spawn } from "child_process";
270
+ import _3 from "lodash";
271
+ import { checkbox, confirm, input } from "@inquirer/prompts";
272
+
273
+ // src/cli/utils/find-locale-paths.ts
274
+ import path3 from "path";
275
+ import { glob } from "glob";
270
276
  import _2 from "lodash";
271
- import { confirm } from "@inquirer/prompts";
272
- var openUrl = (path9) => {
277
+ import { resolveLocaleCode } from "@lingo.dev/_spec";
278
+ function findLocaleFiles(bucket) {
279
+ switch (bucket) {
280
+ case "json":
281
+ return findLocaleFilesWithExtension(".json");
282
+ case "yaml":
283
+ return findLocaleFilesWithExtension(".yml");
284
+ case "flutter":
285
+ return findLocaleFilesWithExtension(".arb");
286
+ case "android":
287
+ return findLocaleFilesWithExtension(".xml");
288
+ case "markdown":
289
+ return findLocaleFilesWithExtension(".md");
290
+ case "xcode-xcstrings":
291
+ return findLocaleFilesForFilename("Localizable.xcstrings");
292
+ case "xcode-strings":
293
+ return findLocaleFilesForFilename("Localizable.strings");
294
+ case "xcode-stringsdict":
295
+ return findLocaleFilesForFilename("Localizable.stringsdict");
296
+ default:
297
+ throw new Error(`Unsupported bucket type: ${bucket}`);
298
+ }
299
+ }
300
+ function findLocaleFilesWithExtension(ext) {
301
+ const files = glob.sync(`**/*${ext}`, {
302
+ ignore: ["node_modules/**", "package*.json", "i18n.json", "lingo.json"]
303
+ });
304
+ const localeFilePattern = new RegExp(`[/\\\\]([a-z]{2}(-[A-Z]{2})?)${ext}$`);
305
+ const localeDirectoryPattern = new RegExp(`[/\\\\]([a-z]{2}(-[A-Z]{2})?)[/\\\\][^/\\\\]+${ext}$`);
306
+ const potentialLocaleFiles = files.filter(
307
+ (file) => localeFilePattern.test(file) || localeDirectoryPattern.test(file)
308
+ );
309
+ const localeFilesAndPatterns = potentialLocaleFiles.map((file) => {
310
+ const match = file.match(new RegExp(`[/|\\\\]([a-z]{2}(-[A-Z]{2})?)(/|\\\\|${ext})`));
311
+ const locale = match?.[1];
312
+ const localeInDir = match?.[3] !== ext;
313
+ const filePattern = localeInDir ? file.replace(`/${locale}/`, `/[locale]/`) : path3.join(path3.dirname(file), `[locale]${ext}`);
314
+ return { file, locale, pattern: filePattern };
315
+ }).filter(({ locale }) => {
316
+ try {
317
+ resolveLocaleCode(locale);
318
+ return true;
319
+ } catch (e) {
320
+ }
321
+ return false;
322
+ });
323
+ const grouppedFilesAndPatterns = _2.groupBy(localeFilesAndPatterns, "pattern");
324
+ const patterns = Object.keys(grouppedFilesAndPatterns);
325
+ if (patterns.length > 0) {
326
+ return { found: true, patterns };
327
+ }
328
+ return { found: false, patterns: [`i18n/[locale]${ext}`] };
329
+ }
330
+ function findLocaleFilesForFilename(fileName) {
331
+ const pattern = fileName;
332
+ const localeFiles = glob.sync(`**/${fileName}`, {
333
+ ignore: ["node_modules/**", "package*.json", "i18n.json", "lingo.json"]
334
+ });
335
+ const localeFilesAndPatterns = localeFiles.map((file) => ({
336
+ file,
337
+ pattern: path3.join(path3.dirname(file), pattern)
338
+ }));
339
+ const grouppedFilesAndPatterns = _2.groupBy(localeFilesAndPatterns, "pattern");
340
+ const patterns = Object.keys(grouppedFilesAndPatterns);
341
+ if (patterns.length > 0) {
342
+ return { found: true, patterns };
343
+ }
344
+ return { found: false, patterns: [fileName] };
345
+ }
346
+
347
+ // src/cli/utils/ensure-patterns.ts
348
+ import fs3 from "fs";
349
+ import path4 from "path";
350
+ function ensurePatterns(patterns, source) {
351
+ if (patterns.length === 0) {
352
+ throw new Error("No patterns found");
353
+ }
354
+ patterns.forEach((pattern) => {
355
+ const filePath = pattern.replace("[locale]", source);
356
+ if (!fs3.existsSync(filePath)) {
357
+ const defaultContent = getDefaultContent(path4.extname(filePath), source);
358
+ fs3.mkdirSync(path4.dirname(filePath), { recursive: true });
359
+ fs3.writeFileSync(filePath, defaultContent);
360
+ }
361
+ });
362
+ }
363
+ function getDefaultContent(ext, source) {
364
+ const defaultGreeting = "Hello from Lingo.dev";
365
+ switch (ext) {
366
+ case ".json":
367
+ case ".arb":
368
+ return `{
369
+ "greeting": "${defaultGreeting}"
370
+ }`;
371
+ case ".yml":
372
+ return `${source}:
373
+ greeting: "${defaultGreeting}"`;
374
+ case ".xml":
375
+ return `<resources>
376
+ <string name="greeting">${defaultGreeting}</string>
377
+ </resources>`;
378
+ case ".md":
379
+ return `# ${defaultGreeting}`;
380
+ case ".xcstrings":
381
+ return `{
382
+ "sourceLanguage" : "${source}",
383
+ "strings" : {
384
+ "${defaultGreeting}" : {
385
+ "extractionState" : "manual",
386
+ "localizations" : {
387
+ "${source}" : {
388
+ "stringUnit" : {
389
+ "state" : "translated",
390
+ "value" : "${defaultGreeting}"
391
+ }
392
+ }
393
+ }
394
+ }
395
+ }
396
+ }`;
397
+ case ".strings":
398
+ return `"greeting" = "${defaultGreeting}";`;
399
+ case ".stringsdict":
400
+ return `<?xml version="1.0" encoding="UTF-8"?>
401
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
402
+ <plist version="1.0">
403
+ <dict>
404
+ <key>key</key>
405
+ <dict>
406
+ <key>NSStringLocalizedFormatKey</key>
407
+ <string>%#@count@</string>
408
+ <key>count</key>
409
+ <dict>
410
+ <key>NSStringFormatSpecTypeKey</key>
411
+ <string>NSStringPluralRuleType</string>
412
+ <key>NSStringFormatValueTypeKey</key>
413
+ <string>d</string>
414
+ <key>zero</key>
415
+ <string>No items</string>
416
+ <key>one</key>
417
+ <string>One item</string>
418
+ <key>other</key>
419
+ <string>%d items</string>
420
+ </dict>
421
+ </dict>
422
+ </dict>
423
+ </plist>`;
424
+ default:
425
+ throw new Error(`Unsupported file extension: ${ext}`);
426
+ }
427
+ }
428
+
429
+ // src/cli/cmd/init.ts
430
+ var openUrl = (path11) => {
273
431
  const settings = getSettings(void 0);
274
- spawn("open", [`${settings.auth.webUrl}${path9}`]);
432
+ spawn("open", [`${settings.auth.webUrl}${path11}`]);
275
433
  };
276
434
  var throwHelpError = (option, value) => {
277
435
  if (value === "help") {
@@ -286,7 +444,7 @@ Do you need support for ${value} ${option}? Type "help" and we will.`
286
444
  var init_default = new InteractiveCommand().command("init").description("Initialize Lingo.dev project").helpOption("-h, --help", "Show help").addOption(new InteractiveOption("-f --force", "Overwrite existing config").prompt(void 0).default(false)).addOption(
287
445
  new InteractiveOption("-s --source <locale>", "Source locale").argParser((value) => {
288
446
  try {
289
- resolveLocaleCode(value);
447
+ resolveLocaleCode2(value);
290
448
  } catch (e) {
291
449
  throwHelpError("locale", value);
292
450
  }
@@ -297,7 +455,7 @@ var init_default = new InteractiveCommand().command("init").description("Initial
297
455
  const values = value.includes(",") ? value.split(",") : value.split(" ");
298
456
  values.forEach((value2) => {
299
457
  try {
300
- resolveLocaleCode(value2);
458
+ resolveLocaleCode2(value2);
301
459
  } catch (e) {
302
460
  throwHelpError("locale", value2);
303
461
  }
@@ -317,8 +475,8 @@ var init_default = new InteractiveCommand().command("init").description("Initial
317
475
  const values = value.includes(",") ? value.split(",") : value.split(" ");
318
476
  for (const p of values) {
319
477
  try {
320
- const dirPath = path3.dirname(p);
321
- const stats = fs3.statSync(dirPath);
478
+ const dirPath = path5.dirname(p);
479
+ const stats = fs4.statSync(dirPath);
322
480
  if (!stats.isDirectory()) {
323
481
  throw new Error(`${dirPath} is not a directory`);
324
482
  }
@@ -327,26 +485,60 @@ var init_default = new InteractiveCommand().command("init").description("Initial
327
485
  }
328
486
  }
329
487
  return values;
330
- }).default([])
488
+ }).prompt(void 0).default([])
331
489
  ).action(async (options) => {
332
490
  const settings = getSettings(void 0);
491
+ const isInteractive = options.interactive;
333
492
  const spinner = Ora2().start("Initializing Lingo.dev project");
334
493
  let existingConfig = await getConfig(false);
335
494
  if (existingConfig && !options.force) {
336
495
  spinner.fail("Lingo.dev project already initialized");
337
496
  return process.exit(1);
338
497
  }
339
- const newConfig = _2.cloneDeep(defaultConfig);
498
+ const newConfig = _3.cloneDeep(defaultConfig);
340
499
  newConfig.locale.source = options.source;
341
500
  newConfig.locale.targets = options.targets;
342
- newConfig.buckets = {
343
- [options.bucket]: {
344
- include: options.paths || []
501
+ if (!isInteractive) {
502
+ newConfig.buckets = {
503
+ [options.bucket]: {
504
+ include: options.paths || []
505
+ }
506
+ };
507
+ } else {
508
+ let selectedPatterns = [];
509
+ const { found, patterns } = findLocaleFiles(options.bucket);
510
+ if (found) {
511
+ spinner.succeed("Found existing locale files:");
512
+ selectedPatterns = await checkbox({
513
+ message: "Select the paths to use",
514
+ choices: patterns.map((value) => ({
515
+ value
516
+ }))
517
+ });
518
+ } else {
519
+ spinner.succeed("No existing locale files found.");
520
+ const useDefault = await confirm({
521
+ message: `Use (and create) default path ${patterns.join(", ")}?`
522
+ });
523
+ ensurePatterns(patterns, options.source);
524
+ if (useDefault) {
525
+ selectedPatterns = patterns;
526
+ }
345
527
  }
346
- };
528
+ if (selectedPatterns.length === 0) {
529
+ const customPaths = await input({
530
+ message: "Enter paths to use"
531
+ });
532
+ selectedPatterns = customPaths.includes(",") ? customPaths.split(",") : customPaths.split(" ");
533
+ }
534
+ newConfig.buckets = {
535
+ [options.bucket]: {
536
+ include: selectedPatterns || []
537
+ }
538
+ };
539
+ }
347
540
  await saveConfig(newConfig);
348
541
  spinner.succeed("Lingo.dev project initialized");
349
- const isInteractive = !process.argv.includes("-y") && !process.argv.includes("--no-interactive");
350
542
  if (isInteractive) {
351
543
  const openDocs = await confirm({ message: "Would you like to see our docs?" });
352
544
  if (openDocs) {
@@ -394,22 +586,22 @@ import { Command as Command5 } from "interactive-commander";
394
586
 
395
587
  // src/cli/cmd/show/config.ts
396
588
  import { Command as Command2 } from "interactive-commander";
397
- import _3 from "lodash";
398
- import fs4 from "fs";
399
- import path4 from "path";
589
+ import _4 from "lodash";
590
+ import fs5 from "fs";
591
+ import path6 from "path";
400
592
  import { defaultConfig as defaultConfig2 } from "@lingo.dev/_spec";
401
593
  var config_default = new Command2().command("config").description("Print out the current configuration").helpOption("-h, --help", "Show help").action(async (options) => {
402
594
  const fileConfig = loadReplexicaFileConfig();
403
- const config = _3.merge({}, defaultConfig2, fileConfig);
595
+ const config = _4.merge({}, defaultConfig2, fileConfig);
404
596
  console.log(JSON.stringify(config, null, 2));
405
597
  });
406
598
  function loadReplexicaFileConfig() {
407
- const replexicaConfigPath = path4.resolve(process.cwd(), "i18n.json");
408
- const fileExists = fs4.existsSync(replexicaConfigPath);
599
+ const replexicaConfigPath = path6.resolve(process.cwd(), "i18n.json");
600
+ const fileExists = fs5.existsSync(replexicaConfigPath);
409
601
  if (!fileExists) {
410
602
  return void 0;
411
603
  }
412
- const fileContent = fs4.readFileSync(replexicaConfigPath, "utf-8");
604
+ const fileContent = fs5.readFileSync(replexicaConfigPath, "utf-8");
413
605
  const replexicaFileConfig = JSON.parse(fileContent);
414
606
  return replexicaFileConfig;
415
607
  }
@@ -445,9 +637,9 @@ import { Command as Command4 } from "interactive-commander";
445
637
  import Ora4 from "ora";
446
638
 
447
639
  // src/cli/utils/buckets.ts
448
- import _4 from "lodash";
449
- import path5 from "path";
450
- import * as glob from "glob";
640
+ import _5 from "lodash";
641
+ import path7 from "path";
642
+ import * as glob2 from "glob";
451
643
  import { resolveOverridenLocale } from "@lingo.dev/_spec";
452
644
  function getBuckets(i18nConfig) {
453
645
  const result = Object.entries(i18nConfig.buckets).map(([bucketType, bucketEntry]) => {
@@ -477,13 +669,13 @@ function extractPathPatterns(sourceLocale, include, exclude) {
477
669
  })
478
670
  )
479
671
  );
480
- const result = _4.differenceBy(includedPatterns, excludedPatterns ?? [], (item) => item.pathPattern);
672
+ const result = _5.differenceBy(includedPatterns, excludedPatterns ?? [], (item) => item.pathPattern);
481
673
  return result;
482
674
  }
483
675
  function expandPlaceholderedGlob(_pathPattern, sourceLocale) {
484
- const absolutePathPattern = path5.resolve(_pathPattern);
485
- const pathPattern = path5.relative(process.cwd(), absolutePathPattern);
486
- if (path5.relative(process.cwd(), pathPattern).startsWith("..")) {
676
+ const absolutePathPattern = path7.resolve(_pathPattern);
677
+ const pathPattern = path7.relative(process.cwd(), absolutePathPattern);
678
+ if (path7.relative(process.cwd(), pathPattern).startsWith("..")) {
487
679
  throw new CLIError({
488
680
  message: `Invalid path pattern: ${pathPattern}. Path pattern must be within the current working directory.`,
489
681
  docUrl: "invalidPathPattern"
@@ -501,19 +693,19 @@ function expandPlaceholderedGlob(_pathPattern, sourceLocale) {
501
693
  docUrl: "invalidPathPattern"
502
694
  });
503
695
  }
504
- const pathPatternChunks = pathPattern.split(path5.sep);
696
+ const pathPatternChunks = pathPattern.split(path7.sep);
505
697
  const localeSegmentIndex = pathPatternChunks.findIndex((segment) => segment.includes("[locale]"));
506
698
  const localePlaceholderIndex = pathPatternChunks[localeSegmentIndex]?.indexOf("[locale]") ?? -1;
507
699
  const sourcePathPattern = pathPattern.replace(/\[locale\]/g, sourceLocale);
508
- const sourcePaths = glob.sync(sourcePathPattern, { follow: true, withFileTypes: true }).filter((file) => file.isFile() || file.isSymbolicLink()).map((file) => file.fullpath()).map((fullpath) => path5.relative(process.cwd(), fullpath));
700
+ const sourcePaths = glob2.sync(sourcePathPattern, { follow: true, withFileTypes: true }).filter((file) => file.isFile() || file.isSymbolicLink()).map((file) => file.fullpath()).map((fullpath) => path7.relative(process.cwd(), fullpath));
509
701
  const placeholderedPaths = sourcePaths.map((sourcePath) => {
510
- const sourcePathChunks = sourcePath.split(path5.sep);
702
+ const sourcePathChunks = sourcePath.split(path7.sep);
511
703
  if (localeSegmentIndex >= 0 && localePlaceholderIndex >= 0) {
512
704
  const placeholderedPathChunk = sourcePathChunks[localeSegmentIndex];
513
705
  const placeholderedSegment = placeholderedPathChunk.substring(0, localePlaceholderIndex) + "[locale]" + placeholderedPathChunk.substring(localePlaceholderIndex + sourceLocale.length);
514
706
  sourcePathChunks[localeSegmentIndex] = placeholderedSegment;
515
707
  }
516
- const placeholderedPath = sourcePathChunks.join(path5.sep);
708
+ const placeholderedPath = sourcePathChunks.join(path7.sep);
517
709
  return placeholderedPath;
518
710
  });
519
711
  return placeholderedPaths;
@@ -555,8 +747,8 @@ var files_default = new Command4().command("files").description("Print out the l
555
747
  } else if (type.target) {
556
748
  result.push(...targetPaths);
557
749
  }
558
- result.forEach((path9) => {
559
- console.log(path9);
750
+ result.forEach((path11) => {
751
+ console.log(path11);
560
752
  });
561
753
  }
562
754
  }
@@ -580,7 +772,7 @@ import { bucketTypeSchema, localeCodeSchema, resolveOverridenLocale as resolveOv
580
772
  import { ReplexicaEngine } from "@lingo.dev/_sdk";
581
773
  import { Command as Command6 } from "interactive-commander";
582
774
  import Z4 from "zod";
583
- import _18 from "lodash";
775
+ import _19 from "lodash";
584
776
  import Ora5 from "ora";
585
777
 
586
778
  // src/cli/loaders/_utils.ts
@@ -597,8 +789,8 @@ function composeLoaders(...loaders) {
597
789
  }
598
790
  return this;
599
791
  },
600
- pull: async (locale, input) => {
601
- let result = input;
792
+ pull: async (locale, input2) => {
793
+ let result = input2;
602
794
  for (let i = 0; i < loaders.length; i++) {
603
795
  result = await loaders[i].pull(locale, result);
604
796
  }
@@ -634,7 +826,7 @@ function createLoader(lDefinition) {
634
826
  state.defaultLocale = locale;
635
827
  return this;
636
828
  },
637
- async pull(locale, input) {
829
+ async pull(locale, input2) {
638
830
  if (!state.defaultLocale) {
639
831
  throw new Error("Default locale not set");
640
832
  }
@@ -642,9 +834,9 @@ function createLoader(lDefinition) {
642
834
  throw new Error("The first pull must be for the default locale");
643
835
  }
644
836
  if (locale === state.defaultLocale) {
645
- state.originalInput = input || null;
837
+ state.originalInput = input2 || null;
646
838
  }
647
- return lDefinition.pull(locale, input, state.initCtx);
839
+ return lDefinition.pull(locale, input2, state.initCtx);
648
840
  },
649
841
  async push(locale, data) {
650
842
  if (!state.defaultLocale) {
@@ -663,8 +855,8 @@ function createLoader(lDefinition) {
663
855
  import { jsonrepair } from "jsonrepair";
664
856
  function createJsonLoader() {
665
857
  return createLoader({
666
- pull: async (locale, input) => {
667
- const jsonString = input || "{}";
858
+ pull: async (locale, input2) => {
859
+ const jsonString = input2 || "{}";
668
860
  let result;
669
861
  try {
670
862
  result = JSON.parse(jsonString);
@@ -682,33 +874,46 @@ function createJsonLoader() {
682
874
 
683
875
  // src/cli/loaders/flat.ts
684
876
  import { flatten, unflatten } from "flat";
685
- import _5 from "lodash";
877
+ import _6 from "lodash";
686
878
  var OBJECT_NUMERIC_KEY_PREFIX = "__lingodotdev__obj__";
687
879
  function createFlatLoader() {
688
- let denormalizedKeysMap = {};
880
+ return composeLoaders(createDenormalizeLoader(), createNormalizeLoader());
881
+ }
882
+ function createDenormalizeLoader() {
689
883
  return createLoader({
690
- pull: async (locale, input) => {
691
- const denormalized = denormalizeObjectKeys(input || {});
692
- const flattened = flatten(denormalized, {
884
+ pull: async (locale, input2) => {
885
+ const inputDenormalized = denormalizeObjectKeys(input2 || {});
886
+ const denormalized = flatten(inputDenormalized, {
693
887
  delimiter: "/",
694
888
  transformKey(key) {
695
889
  return encodeURIComponent(String(key));
696
890
  }
697
891
  });
698
- denormalizedKeysMap = { ...denormalizedKeysMap, ...buildDenormalizedKeysMap(flattened) };
699
- const normalized = normalizeObjectKeys(flattened);
892
+ const keysMap = buildDenormalizedKeysMap(denormalized);
893
+ return { denormalized, keysMap };
894
+ },
895
+ push: async (locale, { denormalized }) => {
896
+ const normalized = normalizeObjectKeys(denormalized);
897
+ return normalized;
898
+ }
899
+ });
900
+ }
901
+ function createNormalizeLoader() {
902
+ return createLoader({
903
+ pull: async (locale, input2) => {
904
+ const normalized = normalizeObjectKeys(input2.denormalized);
700
905
  return normalized;
701
906
  },
702
- push: async (locale, data) => {
703
- const denormalized = mapDenormalizedKeys(data, denormalizedKeysMap);
704
- const unflattened = unflatten(denormalized || {}, {
907
+ push: async (locale, data, originalInput) => {
908
+ const keysMap = originalInput?.keysMap ?? {};
909
+ const input2 = mapDenormalizedKeys(data, keysMap);
910
+ const denormalized = unflatten(input2, {
705
911
  delimiter: "/",
706
912
  transformKey(key) {
707
913
  return decodeURIComponent(String(key));
708
914
  }
709
915
  });
710
- const normalized = normalizeObjectKeys(unflattened);
711
- return normalized;
916
+ return { denormalized, keysMap: keysMap || {} };
712
917
  }
713
918
  });
714
919
  }
@@ -728,7 +933,7 @@ function buildDenormalizedKeysMap(obj) {
728
933
  function mapDenormalizedKeys(obj, denormalizedKeysMap) {
729
934
  return Object.keys(obj).reduce(
730
935
  (acc, key) => {
731
- const denormalizedKey = denormalizedKeysMap[key];
936
+ const denormalizedKey = denormalizedKeysMap[key] ?? key;
732
937
  acc[denormalizedKey] = obj[key];
733
938
  return acc;
734
939
  },
@@ -736,12 +941,12 @@ function mapDenormalizedKeys(obj, denormalizedKeysMap) {
736
941
  );
737
942
  }
738
943
  function denormalizeObjectKeys(obj) {
739
- if (_5.isObject(obj) && !_5.isArray(obj)) {
740
- return _5.transform(
944
+ if (_6.isObject(obj) && !_6.isArray(obj)) {
945
+ return _6.transform(
741
946
  obj,
742
947
  (result, value, key) => {
743
948
  const newKey = !isNaN(Number(key)) ? `${OBJECT_NUMERIC_KEY_PREFIX}${key}` : key;
744
- result[newKey] = _5.isObject(value) ? denormalizeObjectKeys(value) : value;
949
+ result[newKey] = _6.isObject(value) ? denormalizeObjectKeys(value) : value;
745
950
  },
746
951
  {}
747
952
  );
@@ -750,12 +955,12 @@ function denormalizeObjectKeys(obj) {
750
955
  }
751
956
  }
752
957
  function normalizeObjectKeys(obj) {
753
- if (_5.isObject(obj) && !_5.isArray(obj)) {
754
- return _5.transform(
958
+ if (_6.isObject(obj) && !_6.isArray(obj)) {
959
+ return _6.transform(
755
960
  obj,
756
961
  (result, value, key) => {
757
962
  const newKey = `${key}`.replace(OBJECT_NUMERIC_KEY_PREFIX, "");
758
- result[newKey] = _5.isObject(value) ? normalizeObjectKeys(value) : value;
963
+ result[newKey] = _6.isObject(value) ? normalizeObjectKeys(value) : value;
759
964
  },
760
965
  {}
761
966
  );
@@ -765,8 +970,8 @@ function normalizeObjectKeys(obj) {
765
970
  }
766
971
 
767
972
  // src/cli/loaders/text-file.ts
768
- import fs5 from "fs/promises";
769
- import path6 from "path";
973
+ import fs6 from "fs/promises";
974
+ import path8 from "path";
770
975
  function createTextFileLoader(pathPattern) {
771
976
  return createLoader({
772
977
  async pull(locale) {
@@ -774,15 +979,15 @@ function createTextFileLoader(pathPattern) {
774
979
  const trimmedResult = result.trim();
775
980
  return trimmedResult;
776
981
  },
777
- async push(locale, data, _20, originalLocale) {
982
+ async push(locale, data, _21, originalLocale) {
778
983
  const draftPath = pathPattern.replace("[locale]", locale);
779
- const finalPath = path6.resolve(draftPath);
780
- const dirPath = path6.dirname(finalPath);
781
- await fs5.mkdir(dirPath, { recursive: true });
984
+ const finalPath = path8.resolve(draftPath);
985
+ const dirPath = path8.dirname(finalPath);
986
+ await fs6.mkdir(dirPath, { recursive: true });
782
987
  const trimmedPayload = data.trim();
783
988
  const trailingNewLine = await getTrailingNewLine(pathPattern, locale, originalLocale);
784
989
  let finalPayload = trimmedPayload + trailingNewLine;
785
- await fs5.writeFile(finalPath, finalPayload, {
990
+ await fs6.writeFile(finalPath, finalPayload, {
786
991
  encoding: "utf-8",
787
992
  flag: "w"
788
993
  });
@@ -791,12 +996,12 @@ function createTextFileLoader(pathPattern) {
791
996
  }
792
997
  async function readFileForLocale(pathPattern, locale) {
793
998
  const draftPath = pathPattern.replace("[locale]", locale);
794
- const finalPath = path6.resolve(draftPath);
795
- const exists = await fs5.access(finalPath).then(() => true).catch(() => false);
999
+ const finalPath = path8.resolve(draftPath);
1000
+ const exists = await fs6.access(finalPath).then(() => true).catch(() => false);
796
1001
  if (!exists) {
797
1002
  return "";
798
1003
  }
799
- return fs5.readFile(finalPath, "utf-8");
1004
+ return fs6.readFile(finalPath, "utf-8");
800
1005
  }
801
1006
  async function getTrailingNewLine(pathPattern, locale, originalLocale) {
802
1007
  let templateData = await readFileForLocale(pathPattern, locale);
@@ -814,8 +1019,8 @@ async function getTrailingNewLine(pathPattern, locale, originalLocale) {
814
1019
  import YAML from "yaml";
815
1020
  function createYamlLoader() {
816
1021
  return createLoader({
817
- async pull(locale, input) {
818
- return YAML.parse(input) || {};
1022
+ async pull(locale, input2) {
1023
+ return YAML.parse(input2) || {};
819
1024
  },
820
1025
  async push(locale, payload) {
821
1026
  return YAML.stringify(payload, {
@@ -828,8 +1033,8 @@ function createYamlLoader() {
828
1033
  // src/cli/loaders/root-key.ts
829
1034
  function createRootKeyLoader(replaceAll = false) {
830
1035
  return createLoader({
831
- async pull(locale, input) {
832
- const result = input[locale];
1036
+ async pull(locale, input2) {
1037
+ const result = input2[locale];
833
1038
  return result;
834
1039
  },
835
1040
  async push(locale, data, originalInput) {
@@ -843,15 +1048,15 @@ function createRootKeyLoader(replaceAll = false) {
843
1048
  }
844
1049
 
845
1050
  // src/cli/loaders/flutter.ts
846
- import _6 from "lodash";
1051
+ import _7 from "lodash";
847
1052
  function createFlutterLoader() {
848
1053
  return createLoader({
849
- async pull(locale, input) {
850
- const result = _6.pickBy(input, (value, key) => !key.startsWith("@"));
1054
+ async pull(locale, input2) {
1055
+ const result = _7.pickBy(input2, (value, key) => !key.startsWith("@"));
851
1056
  return result;
852
1057
  },
853
1058
  async push(locale, data, originalInput) {
854
- const result = _6.merge({}, originalInput, { "@@locale": locale }, data);
1059
+ const result = _7.merge({}, originalInput, { "@@locale": locale }, data);
855
1060
  return result;
856
1061
  }
857
1062
  });
@@ -861,10 +1066,10 @@ function createFlutterLoader() {
861
1066
  import { parseStringPromise, Builder } from "xml2js";
862
1067
  function createAndroidLoader() {
863
1068
  return createLoader({
864
- async pull(locale, input) {
1069
+ async pull(locale, input2) {
865
1070
  try {
866
1071
  const result = {};
867
- const parsed = !input ? { resources: {} } : await parseStringPromise(input, { explicitArray: true });
1072
+ const parsed = !input2 ? { resources: {} } : await parseStringPromise(input2, { explicitArray: true });
868
1073
  if (!parsed || !parsed.resources) {
869
1074
  console.warn("No resources found in the Android resource file");
870
1075
  return result;
@@ -953,16 +1158,16 @@ function createAndroidLoader() {
953
1158
  // src/cli/loaders/csv.ts
954
1159
  import { parse } from "csv-parse/sync";
955
1160
  import { stringify } from "csv-stringify/sync";
956
- import _7 from "lodash";
1161
+ import _8 from "lodash";
957
1162
  function createCsvLoader() {
958
1163
  return createLoader({
959
1164
  async pull(locale, _input) {
960
- const input = parse(_input, {
1165
+ const input2 = parse(_input, {
961
1166
  columns: true,
962
1167
  skip_empty_lines: true
963
1168
  });
964
1169
  const result = {};
965
- _7.forEach(input, (row) => {
1170
+ _8.forEach(input2, (row) => {
966
1171
  const key = row.id;
967
1172
  if (key && row[locale] && row[locale].trim() !== "") {
968
1173
  result[key] = row[locale];
@@ -971,16 +1176,16 @@ function createCsvLoader() {
971
1176
  return result;
972
1177
  },
973
1178
  async push(locale, data, originalInput) {
974
- const input = parse(originalInput || "", {
1179
+ const input2 = parse(originalInput || "", {
975
1180
  columns: true,
976
1181
  skip_empty_lines: true
977
1182
  });
978
- const columns = input.length > 0 ? Object.keys(input[0]) : ["id", locale];
979
- const updatedRows = input.map((row) => ({
1183
+ const columns = input2.length > 0 ? Object.keys(input2[0]) : ["id", locale];
1184
+ const updatedRows = input2.map((row) => ({
980
1185
  ...row,
981
1186
  [locale]: data[row.id] || row[locale] || ""
982
1187
  }));
983
- const existingKeys = new Set(input.map((row) => row.id));
1188
+ const existingKeys = new Set(input2.map((row) => row.id));
984
1189
  Object.entries(data).forEach(([key, value]) => {
985
1190
  if (!existingKeys.has(key)) {
986
1191
  const newRow = {
@@ -1015,9 +1220,9 @@ function createHtmlLoader() {
1015
1220
  };
1016
1221
  const UNLOCALIZABLE_TAGS = ["script", "style"];
1017
1222
  return createLoader({
1018
- async pull(locale, input) {
1223
+ async pull(locale, input2) {
1019
1224
  const result = {};
1020
- const dom = new JSDOM(input);
1225
+ const dom = new JSDOM(input2);
1021
1226
  const document = dom.window.document;
1022
1227
  const getPath = (node, attribute) => {
1023
1228
  const indices = [];
@@ -1083,9 +1288,9 @@ function createHtmlLoader() {
1083
1288
  const bDepth = b.split("/").length;
1084
1289
  return aDepth - bDepth;
1085
1290
  });
1086
- paths.forEach((path9) => {
1087
- const value = data[path9];
1088
- const [nodePath, attribute] = path9.split("#");
1291
+ paths.forEach((path11) => {
1292
+ const value = data[path11];
1293
+ const [nodePath, attribute] = path11.split("#");
1089
1294
  const [rootTag, ...indices] = nodePath.split("/");
1090
1295
  let parent = rootTag === "head" ? document.head : document.body;
1091
1296
  let current = parent;
@@ -1137,8 +1342,8 @@ var yamlEngine = {
1137
1342
  };
1138
1343
  function createMarkdownLoader() {
1139
1344
  return createLoader({
1140
- async pull(locale, input) {
1141
- const { data: frontmatter, content } = matter(input, {
1345
+ async pull(locale, input2) {
1346
+ const { data: frontmatter, content } = matter(input2, {
1142
1347
  engines: {
1143
1348
  yaml: yamlEngine
1144
1349
  }
@@ -1188,7 +1393,7 @@ function createPropertiesLoader() {
1188
1393
  return result;
1189
1394
  },
1190
1395
  async push(locale, payload) {
1191
- const result = Object.entries(payload).filter(([_20, value]) => value != null).map(([key, value]) => `${key}=${value}`).join("\n");
1396
+ const result = Object.entries(payload).filter(([_21, value]) => value != null).map(([key, value]) => `${key}=${value}`).join("\n");
1192
1397
  return result;
1193
1398
  }
1194
1399
  });
@@ -1207,8 +1412,8 @@ function parsePropertyLine(line) {
1207
1412
  // src/cli/loaders/xcode-strings.ts
1208
1413
  function createXcodeStringsLoader() {
1209
1414
  return createLoader({
1210
- async pull(locale, input) {
1211
- const lines = input.split("\n");
1415
+ async pull(locale, input2) {
1416
+ const lines = input2.split("\n");
1212
1417
  const result = {};
1213
1418
  for (const line of lines) {
1214
1419
  const trimmedLine = line.trim();
@@ -1249,9 +1454,9 @@ var emptyData = [
1249
1454
  ].join("\n");
1250
1455
  function createXcodeStringsdictLoader() {
1251
1456
  return createLoader({
1252
- async pull(locale, input) {
1457
+ async pull(locale, input2) {
1253
1458
  try {
1254
- const parsed = plist.parse(input || emptyData);
1459
+ const parsed = plist.parse(input2 || emptyData);
1255
1460
  if (typeof parsed !== "object" || parsed === null) {
1256
1461
  throw new CLIError({
1257
1462
  message: "Invalid .stringsdict format",
@@ -1274,12 +1479,12 @@ function createXcodeStringsdictLoader() {
1274
1479
  }
1275
1480
 
1276
1481
  // src/cli/loaders/xcode-xcstrings.ts
1277
- import _8 from "lodash";
1482
+ import _9 from "lodash";
1278
1483
  function createXcodeXcstringsLoader() {
1279
1484
  return createLoader({
1280
- async pull(locale, input) {
1485
+ async pull(locale, input2) {
1281
1486
  const resultData = {};
1282
- for (const [translationKey, _translationEntity] of Object.entries(input.strings)) {
1487
+ for (const [translationKey, _translationEntity] of Object.entries(input2.strings)) {
1283
1488
  const rootTranslationEntity = _translationEntity;
1284
1489
  const langTranslationEntity = rootTranslationEntity?.localizations?.[locale];
1285
1490
  if (langTranslationEntity) {
@@ -1338,7 +1543,7 @@ function createXcodeXcstringsLoader() {
1338
1543
  };
1339
1544
  }
1340
1545
  }
1341
- const result = _8.merge({}, originalInput, langDataToMerge);
1546
+ const result = _9.merge({}, originalInput, langDataToMerge);
1342
1547
  return result;
1343
1548
  }
1344
1549
  });
@@ -1380,33 +1585,36 @@ async function loadPrettierConfig() {
1380
1585
  }
1381
1586
 
1382
1587
  // src/cli/loaders/unlocalizable.ts
1383
- import _9 from "lodash";
1588
+ import _10 from "lodash";
1384
1589
  import _isUrl from "is-url";
1385
1590
  import { isValid, parseISO } from "date-fns";
1386
- function createUnlocalizableLoader() {
1591
+ function createUnlocalizableLoader(isCacheRestore = false) {
1387
1592
  const rules = {
1388
- isEmpty: (v) => _9.isEmpty(v),
1389
- isNumber: (v) => !_9.isNaN(_9.toNumber(v)),
1390
- isBoolean: (v) => _9.isBoolean(v),
1391
- isIsoDate: (v) => _9.isString(v) && _isIsoDate(v),
1392
- isSystemId: (v) => _9.isString(v) && _isSystemId(v),
1393
- isUrl: (v) => _9.isString(v) && _isUrl(v)
1593
+ isEmpty: (v) => _10.isEmpty(v),
1594
+ isNumber: (v) => !_10.isNaN(_10.toNumber(v)),
1595
+ isBoolean: (v) => _10.isBoolean(v),
1596
+ isIsoDate: (v) => _10.isString(v) && _isIsoDate(v),
1597
+ isSystemId: (v) => _10.isString(v) && _isSystemId(v),
1598
+ isUrl: (v) => _10.isString(v) && _isUrl(v)
1394
1599
  };
1395
1600
  return createLoader({
1396
- async pull(locale, input) {
1397
- const passthroughKeys = Object.entries(input).filter(([key, value]) => {
1601
+ async pull(locale, input2) {
1602
+ const passthroughKeys = Object.entries(input2).filter(([key, value]) => {
1398
1603
  for (const [ruleName, rule] of Object.entries(rules)) {
1399
1604
  if (rule(value)) {
1400
1605
  return true;
1401
1606
  }
1402
1607
  }
1403
1608
  return false;
1404
- }).map(([key, _20]) => key);
1405
- const result = _9.omitBy(input, (_20, key) => passthroughKeys.includes(key));
1609
+ }).map(([key, _21]) => key);
1610
+ const result = _10.omitBy(input2, (_21, key) => passthroughKeys.includes(key));
1406
1611
  return result;
1407
1612
  },
1408
1613
  async push(locale, data, originalInput) {
1409
- const result = _9.merge({}, originalInput, data);
1614
+ if (isCacheRestore) {
1615
+ return _10.merge({}, data);
1616
+ }
1617
+ const result = _10.merge({}, originalInput, data);
1410
1618
  return result;
1411
1619
  }
1412
1620
  });
@@ -1419,20 +1627,20 @@ function _isIsoDate(v) {
1419
1627
  }
1420
1628
 
1421
1629
  // src/cli/loaders/po/index.ts
1422
- import _10 from "lodash";
1630
+ import _11 from "lodash";
1423
1631
  import gettextParser from "gettext-parser";
1424
1632
  function createPoLoader(params = { multiline: false }) {
1425
1633
  return composeLoaders(createPoDataLoader(params), createPoContentLoader());
1426
1634
  }
1427
1635
  function createPoDataLoader(params) {
1428
1636
  return createLoader({
1429
- async pull(locale, input) {
1430
- const parsedPo = gettextParser.po.parse(input);
1637
+ async pull(locale, input2) {
1638
+ const parsedPo = gettextParser.po.parse(input2);
1431
1639
  const result = {};
1432
- const sections = input.split("\n\n").filter(Boolean);
1640
+ const sections = input2.split("\n\n").filter(Boolean);
1433
1641
  for (const section of sections) {
1434
1642
  const sectionPo = gettextParser.po.parse(section);
1435
- const contextKey = _10.keys(sectionPo.translations)[0];
1643
+ const contextKey = _11.keys(sectionPo.translations)[0];
1436
1644
  const entries = sectionPo.translations[contextKey];
1437
1645
  Object.entries(entries).forEach(([msgid, entry]) => {
1438
1646
  if (msgid && entry.msgid) {
@@ -1450,12 +1658,12 @@ function createPoDataLoader(params) {
1450
1658
  const sections = originalInput?.split("\n\n").filter(Boolean) || [];
1451
1659
  const result = sections.map((section) => {
1452
1660
  const sectionPo = gettextParser.po.parse(section);
1453
- const contextKey = _10.keys(sectionPo.translations)[0];
1661
+ const contextKey = _11.keys(sectionPo.translations)[0];
1454
1662
  const entries = sectionPo.translations[contextKey];
1455
1663
  const msgid = Object.keys(entries).find((key) => entries[key].msgid);
1456
1664
  if (!msgid) return section;
1457
1665
  if (data[msgid]) {
1458
- const updatedPo = _10.merge({}, sectionPo, {
1666
+ const updatedPo = _11.merge({}, sectionPo, {
1459
1667
  translations: {
1460
1668
  [contextKey]: {
1461
1669
  [msgid]: {
@@ -1474,8 +1682,8 @@ function createPoDataLoader(params) {
1474
1682
  }
1475
1683
  function createPoContentLoader() {
1476
1684
  return createLoader({
1477
- async pull(locale, input) {
1478
- const result = _10.chain(input).entries().filter(([, entry]) => !!entry.msgid).map(([, entry]) => [
1685
+ async pull(locale, input2) {
1686
+ const result = _11.chain(input2).entries().filter(([, entry]) => !!entry.msgid).map(([, entry]) => [
1479
1687
  entry.msgid,
1480
1688
  {
1481
1689
  singular: entry.msgstr[0] || entry.msgid,
@@ -1485,7 +1693,7 @@ function createPoContentLoader() {
1485
1693
  return result;
1486
1694
  },
1487
1695
  async push(locale, data, originalInput) {
1488
- const result = _10.chain(originalInput).entries().map(([, entry]) => [
1696
+ const result = _11.chain(originalInput).entries().map(([, entry]) => [
1489
1697
  entry.msgid,
1490
1698
  {
1491
1699
  ...entry,
@@ -1501,8 +1709,8 @@ function createPoContentLoader() {
1501
1709
  import xliff from "xliff";
1502
1710
  function createXliffLoader() {
1503
1711
  return createLoader({
1504
- async pull(locale, input) {
1505
- const js = await xliff.xliff2js(input);
1712
+ async pull(locale, input2) {
1713
+ const js = await xliff.xliff2js(input2);
1506
1714
  return js || {};
1507
1715
  },
1508
1716
  async push(locale, payload) {
@@ -1519,10 +1727,10 @@ function normalizeXMLString(xmlString) {
1519
1727
  }
1520
1728
  function createXmlLoader() {
1521
1729
  return createLoader({
1522
- async pull(locale, input) {
1730
+ async pull(locale, input2) {
1523
1731
  let result = {};
1524
1732
  try {
1525
- const parsed = await parseStringPromise2(input, {
1733
+ const parsed = await parseStringPromise2(input2, {
1526
1734
  explicitArray: false,
1527
1735
  mergeAttrs: false,
1528
1736
  normalize: true,
@@ -1557,8 +1765,8 @@ import srtParser from "srt-parser-2";
1557
1765
  function createSrtLoader() {
1558
1766
  const parser = new srtParser();
1559
1767
  return createLoader({
1560
- async pull(locale, input) {
1561
- const parsed = parser.fromSrt(input) || [];
1768
+ async pull(locale, input2) {
1769
+ const parsed = parser.fromSrt(input2) || [];
1562
1770
  const result = {};
1563
1771
  parsed.forEach((entry) => {
1564
1772
  const key = `${entry.id}#${entry.startTime}-${entry.endTime}`;
@@ -1586,7 +1794,7 @@ function createSrtLoader() {
1586
1794
  }
1587
1795
 
1588
1796
  // src/cli/loaders/dato/index.ts
1589
- import fs6 from "fs";
1797
+ import fs7 from "fs";
1590
1798
  import JSON5 from "json5";
1591
1799
 
1592
1800
  // src/cli/loaders/dato/_base.ts
@@ -1608,34 +1816,34 @@ var datoSettingsSchema = Z2.object({
1608
1816
  });
1609
1817
 
1610
1818
  // src/cli/loaders/dato/filter.ts
1611
- import _11 from "lodash";
1819
+ import _12 from "lodash";
1612
1820
  function createDatoFilterLoader() {
1613
1821
  return createLoader({
1614
- async pull(locale, input) {
1822
+ async pull(locale, input2) {
1615
1823
  const result = {};
1616
- for (const [modelId, modelInfo] of _11.entries(input)) {
1824
+ for (const [modelId, modelInfo] of _12.entries(input2)) {
1617
1825
  result[modelId] = {};
1618
1826
  for (const record of modelInfo.records) {
1619
- result[modelId][record.id] = _11.chain(modelInfo.fields).mapKeys((field) => field.api_key).mapValues((field) => _11.get(record, [field.api_key, locale])).value();
1827
+ result[modelId][record.id] = _12.chain(modelInfo.fields).mapKeys((field) => field.api_key).mapValues((field) => _12.get(record, [field.api_key, locale])).value();
1620
1828
  }
1621
1829
  }
1622
1830
  return result;
1623
1831
  },
1624
1832
  async push(locale, data, originalInput, originalLocale) {
1625
- const result = _11.cloneDeep(originalInput || {});
1626
- for (const [modelId, modelInfo] of _11.entries(result)) {
1833
+ const result = _12.cloneDeep(originalInput || {});
1834
+ for (const [modelId, modelInfo] of _12.entries(result)) {
1627
1835
  for (const record of modelInfo.records) {
1628
- for (const [fieldId, fieldValue] of _11.entries(record)) {
1836
+ for (const [fieldId, fieldValue] of _12.entries(record)) {
1629
1837
  const fieldInfo = modelInfo.fields.find((field) => field.api_key === fieldId);
1630
1838
  if (fieldInfo) {
1631
- const sourceFieldValue = _11.get(fieldValue, [originalLocale]);
1632
- const targetFieldValue = _11.get(data, [modelId, record.id, fieldId]);
1839
+ const sourceFieldValue = _12.get(fieldValue, [originalLocale]);
1840
+ const targetFieldValue = _12.get(data, [modelId, record.id, fieldId]);
1633
1841
  if (targetFieldValue) {
1634
- _11.set(record, [fieldId, locale], targetFieldValue);
1842
+ _12.set(record, [fieldId, locale], targetFieldValue);
1635
1843
  } else {
1636
- _11.set(record, [fieldId, locale], sourceFieldValue);
1844
+ _12.set(record, [fieldId, locale], sourceFieldValue);
1637
1845
  }
1638
- _11.chain(fieldValue).keys().reject((loc) => loc === locale || loc === originalLocale).filter((loc) => _11.isEmpty(_11.get(fieldValue, [loc]))).forEach((loc) => _11.set(record, [fieldId, loc], sourceFieldValue)).value();
1846
+ _12.chain(fieldValue).keys().reject((loc) => loc === locale || loc === originalLocale).filter((loc) => _12.isEmpty(_12.get(fieldValue, [loc]))).forEach((loc) => _12.set(record, [fieldId, loc], sourceFieldValue)).value();
1639
1847
  }
1640
1848
  }
1641
1849
  }
@@ -1646,10 +1854,10 @@ function createDatoFilterLoader() {
1646
1854
  }
1647
1855
 
1648
1856
  // src/cli/loaders/dato/api.ts
1649
- import _13 from "lodash";
1857
+ import _14 from "lodash";
1650
1858
 
1651
1859
  // src/cli/loaders/dato/_utils.ts
1652
- import _12 from "lodash";
1860
+ import _13 from "lodash";
1653
1861
  import { buildClient } from "@datocms/cma-client-node";
1654
1862
  function createDatoClient(params) {
1655
1863
  if (!params.apiKey) {
@@ -1824,7 +2032,7 @@ function createDatoApiLoader(config, onConfigUpdate) {
1824
2032
  const result = {
1825
2033
  models: {}
1826
2034
  };
1827
- const updatedConfig = _13.cloneDeep(config);
2035
+ const updatedConfig = _14.cloneDeep(config);
1828
2036
  console.log(`Initializing DatoCMS loader...`);
1829
2037
  const project = await dato.findProject();
1830
2038
  const modelChoices = await getModelChoices(dato, config);
@@ -1842,7 +2050,7 @@ function createDatoApiLoader(config, onConfigUpdate) {
1842
2050
  delete updatedConfig.models[modelId];
1843
2051
  }
1844
2052
  }
1845
- for (const modelId of _13.keys(updatedConfig.models)) {
2053
+ for (const modelId of _14.keys(updatedConfig.models)) {
1846
2054
  const { modelName, fields } = await getModelFields(dato, modelId);
1847
2055
  if (fields.length > 0) {
1848
2056
  result.models[modelId] = { fields: [], records: [] };
@@ -1853,7 +2061,7 @@ function createDatoApiLoader(config, onConfigUpdate) {
1853
2061
  const isLocalized = await updateFieldLocalization(dato, fieldInfo, selectedFields.includes(fieldInfo.id));
1854
2062
  if (isLocalized) {
1855
2063
  result.models[modelId].fields.push(fieldInfo);
1856
- updatedConfig.models[modelId].fields = _13.uniq([
2064
+ updatedConfig.models[modelId].fields = _14.uniq([
1857
2065
  ...updatedConfig.models[modelId].fields || [],
1858
2066
  fieldInfo.api_key
1859
2067
  ]);
@@ -1870,9 +2078,9 @@ function createDatoApiLoader(config, onConfigUpdate) {
1870
2078
  onConfigUpdate(updatedConfig);
1871
2079
  return result;
1872
2080
  },
1873
- async pull(locale, input, initCtx) {
2081
+ async pull(locale, input2, initCtx) {
1874
2082
  const result = {};
1875
- for (const modelId of _13.keys(initCtx?.models || {})) {
2083
+ for (const modelId of _14.keys(initCtx?.models || {})) {
1876
2084
  let records = initCtx?.models[modelId].records || [];
1877
2085
  const recordIds = records.map((record) => record.id);
1878
2086
  records = await dato.findRecords(recordIds);
@@ -1887,7 +2095,7 @@ function createDatoApiLoader(config, onConfigUpdate) {
1887
2095
  return result;
1888
2096
  },
1889
2097
  async push(locale, data, originalInput) {
1890
- for (const modelId of _13.keys(data)) {
2098
+ for (const modelId of _14.keys(data)) {
1891
2099
  for (let i = 0; i < data[modelId].records.length; i++) {
1892
2100
  const record = data[modelId].records[i];
1893
2101
  console.log(`Updating record ${i + 1}/${data[modelId].records.length} for model ${modelId}...`);
@@ -1901,7 +2109,7 @@ async function getModelFields(dato, modelId) {
1901
2109
  const modelInfo = await dato.findModel(modelId);
1902
2110
  return {
1903
2111
  modelName: modelInfo.name,
1904
- fields: _13.filter(modelInfo.fields, (field) => field.type === "field")
2112
+ fields: _14.filter(modelInfo.fields, (field) => field.type === "field")
1905
2113
  };
1906
2114
  }
1907
2115
  async function getFieldDetails(dato, fields) {
@@ -1979,17 +2187,17 @@ async function promptModelSelection(choices) {
1979
2187
  }
1980
2188
 
1981
2189
  // src/cli/loaders/dato/extract.ts
1982
- import _14 from "lodash";
2190
+ import _15 from "lodash";
1983
2191
  function createDatoExtractLoader() {
1984
2192
  return createLoader({
1985
- async pull(locale, input) {
2193
+ async pull(locale, input2) {
1986
2194
  const result = {};
1987
- for (const [modelId, modelInfo] of _14.entries(input)) {
1988
- for (const [recordId, record] of _14.entries(modelInfo)) {
1989
- for (const [fieldName, fieldValue] of _14.entries(record)) {
2195
+ for (const [modelId, modelInfo] of _15.entries(input2)) {
2196
+ for (const [recordId, record] of _15.entries(modelInfo)) {
2197
+ for (const [fieldName, fieldValue] of _15.entries(record)) {
1990
2198
  const parsedValue = createParsedDatoValue(fieldValue);
1991
2199
  if (parsedValue) {
1992
- _14.set(result, [modelId, `_${recordId}`, fieldName], parsedValue);
2200
+ _15.set(result, [modelId, `_${recordId}`, fieldName], parsedValue);
1993
2201
  }
1994
2202
  }
1995
2203
  }
@@ -1997,14 +2205,14 @@ function createDatoExtractLoader() {
1997
2205
  return result;
1998
2206
  },
1999
2207
  async push(locale, data, originalInput) {
2000
- const result = _14.cloneDeep(originalInput || {});
2001
- for (const [modelId, modelInfo] of _14.entries(data)) {
2002
- for (const [virtualRecordId, record] of _14.entries(modelInfo)) {
2003
- for (const [fieldName, fieldValue] of _14.entries(record)) {
2208
+ const result = _15.cloneDeep(originalInput || {});
2209
+ for (const [modelId, modelInfo] of _15.entries(data)) {
2210
+ for (const [virtualRecordId, record] of _15.entries(modelInfo)) {
2211
+ for (const [fieldName, fieldValue] of _15.entries(record)) {
2004
2212
  const [, recordId] = virtualRecordId.split("_");
2005
- const originalFieldValue = _14.get(originalInput, [modelId, recordId, fieldName]);
2213
+ const originalFieldValue = _15.get(originalInput, [modelId, recordId, fieldName]);
2006
2214
  const rawValue = createRawDatoValue(fieldValue, originalFieldValue, true);
2007
- _14.set(result, [modelId, recordId, fieldName], rawValue || originalFieldValue);
2215
+ _15.set(result, [modelId, recordId, fieldName], rawValue || originalFieldValue);
2008
2216
  }
2009
2217
  }
2010
2218
  }
@@ -2013,25 +2221,25 @@ function createDatoExtractLoader() {
2013
2221
  });
2014
2222
  }
2015
2223
  function detectDatoFieldType(rawDatoValue) {
2016
- if (_14.has(rawDatoValue, "document") && _14.get(rawDatoValue, "schema") === "dast") {
2224
+ if (_15.has(rawDatoValue, "document") && _15.get(rawDatoValue, "schema") === "dast") {
2017
2225
  return "structured_text";
2018
- } else if (_14.has(rawDatoValue, "no_index") || _14.has(rawDatoValue, "twitter_card")) {
2226
+ } else if (_15.has(rawDatoValue, "no_index") || _15.has(rawDatoValue, "twitter_card")) {
2019
2227
  return "seo";
2020
- } else if (_14.get(rawDatoValue, "type") === "item") {
2228
+ } else if (_15.get(rawDatoValue, "type") === "item") {
2021
2229
  return "single_block";
2022
- } else if (_14.isArray(rawDatoValue) && _14.every(rawDatoValue, (item) => _14.get(item, "type") === "item")) {
2230
+ } else if (_15.isArray(rawDatoValue) && _15.every(rawDatoValue, (item) => _15.get(item, "type") === "item")) {
2023
2231
  return "rich_text";
2024
2232
  } else if (_isFile(rawDatoValue)) {
2025
2233
  return "file";
2026
- } else if (_14.isArray(rawDatoValue) && _14.every(rawDatoValue, (item) => _isFile(item))) {
2234
+ } else if (_15.isArray(rawDatoValue) && _15.every(rawDatoValue, (item) => _isFile(item))) {
2027
2235
  return "gallery";
2028
2236
  } else if (_isJson(rawDatoValue)) {
2029
2237
  return "json";
2030
- } else if (_14.isString(rawDatoValue)) {
2238
+ } else if (_15.isString(rawDatoValue)) {
2031
2239
  return "string";
2032
2240
  } else if (_isVideo(rawDatoValue)) {
2033
2241
  return "video";
2034
- } else if (_14.isArray(rawDatoValue) && _14.every(rawDatoValue, (item) => _14.isString(item))) {
2242
+ } else if (_15.isArray(rawDatoValue) && _15.every(rawDatoValue, (item) => _15.isString(item))) {
2035
2243
  return "ref_list";
2036
2244
  } else {
2037
2245
  return null;
@@ -2089,62 +2297,62 @@ function createRawDatoValue(parsedDatoValue, originalRawDatoValue, isClean = fal
2089
2297
  }
2090
2298
  function serializeStructuredText(rawStructuredText) {
2091
2299
  return serializeStructuredTextNode(rawStructuredText);
2092
- function serializeStructuredTextNode(node, path9 = [], acc = {}) {
2300
+ function serializeStructuredTextNode(node, path11 = [], acc = {}) {
2093
2301
  if ("document" in node) {
2094
- return serializeStructuredTextNode(node.document, [...path9, "document"], acc);
2302
+ return serializeStructuredTextNode(node.document, [...path11, "document"], acc);
2095
2303
  }
2096
- if (!_14.isNil(node.value)) {
2097
- acc[[...path9, "value"].join(".")] = node.value;
2098
- } else if (_14.get(node, "type") === "block") {
2099
- acc[[...path9, "item"].join(".")] = serializeBlock(node.item);
2304
+ if (!_15.isNil(node.value)) {
2305
+ acc[[...path11, "value"].join(".")] = node.value;
2306
+ } else if (_15.get(node, "type") === "block") {
2307
+ acc[[...path11, "item"].join(".")] = serializeBlock(node.item);
2100
2308
  }
2101
2309
  if (node.children) {
2102
2310
  for (let i = 0; i < node.children.length; i++) {
2103
- serializeStructuredTextNode(node.children[i], [...path9, i.toString()], acc);
2311
+ serializeStructuredTextNode(node.children[i], [...path11, i.toString()], acc);
2104
2312
  }
2105
2313
  }
2106
2314
  return acc;
2107
2315
  }
2108
2316
  }
2109
2317
  function serializeSeo(rawSeo) {
2110
- return _14.chain(rawSeo).pick(["title", "description"]).value();
2318
+ return _15.chain(rawSeo).pick(["title", "description"]).value();
2111
2319
  }
2112
2320
  function serializeBlock(rawBlock) {
2113
- if (_14.get(rawBlock, "type") === "item" && _14.has(rawBlock, "id")) {
2321
+ if (_15.get(rawBlock, "type") === "item" && _15.has(rawBlock, "id")) {
2114
2322
  return serializeBlock(rawBlock.attributes);
2115
2323
  }
2116
2324
  const result = {};
2117
- for (const [attributeName, attributeValue] of _14.entries(rawBlock)) {
2325
+ for (const [attributeName, attributeValue] of _15.entries(rawBlock)) {
2118
2326
  result[attributeName] = createParsedDatoValue(attributeValue);
2119
2327
  }
2120
2328
  return result;
2121
2329
  }
2122
2330
  function serializeBlockList(rawBlockList) {
2123
- return _14.chain(rawBlockList).map((block) => serializeBlock(block)).value();
2331
+ return _15.chain(rawBlockList).map((block) => serializeBlock(block)).value();
2124
2332
  }
2125
2333
  function serializeVideo(rawVideo) {
2126
- return _14.chain(rawVideo).pick(["title"]).value();
2334
+ return _15.chain(rawVideo).pick(["title"]).value();
2127
2335
  }
2128
2336
  function serializeFile(rawFile) {
2129
- return _14.chain(rawFile).pick(["alt", "title"]).value();
2337
+ return _15.chain(rawFile).pick(["alt", "title"]).value();
2130
2338
  }
2131
2339
  function serializeGallery(rawGallery) {
2132
- return _14.chain(rawGallery).map((item) => serializeFile(item)).value();
2340
+ return _15.chain(rawGallery).map((item) => serializeFile(item)).value();
2133
2341
  }
2134
2342
  function deserializeFile(parsedFile, originalRawFile) {
2135
- return _14.chain(parsedFile).defaults(originalRawFile).value();
2343
+ return _15.chain(parsedFile).defaults(originalRawFile).value();
2136
2344
  }
2137
2345
  function deserializeGallery(parsedGallery, originalRawGallery) {
2138
- return _14.chain(parsedGallery).map((item, i) => deserializeFile(item, originalRawGallery[i])).value();
2346
+ return _15.chain(parsedGallery).map((item, i) => deserializeFile(item, originalRawGallery[i])).value();
2139
2347
  }
2140
2348
  function deserializeVideo(parsedVideo, originalRawVideo) {
2141
- return _14.chain(parsedVideo).defaults(originalRawVideo).value();
2349
+ return _15.chain(parsedVideo).defaults(originalRawVideo).value();
2142
2350
  }
2143
2351
  function deserializeBlock(payload, rawNode, isClean = false) {
2144
- const result = _14.cloneDeep(rawNode);
2145
- for (const [attributeName, attributeValue] of _14.entries(rawNode.attributes)) {
2352
+ const result = _15.cloneDeep(rawNode);
2353
+ for (const [attributeName, attributeValue] of _15.entries(rawNode.attributes)) {
2146
2354
  const rawValue = createRawDatoValue(payload[attributeName], attributeValue, isClean);
2147
- _14.set(result, ["attributes", attributeName], rawValue);
2355
+ _15.set(result, ["attributes", attributeName], rawValue);
2148
2356
  }
2149
2357
  if (isClean) {
2150
2358
  delete result["id"];
@@ -2152,45 +2360,45 @@ function deserializeBlock(payload, rawNode, isClean = false) {
2152
2360
  return result;
2153
2361
  }
2154
2362
  function deserializeSeo(parsedSeo, originalRawSeo) {
2155
- return _14.chain(parsedSeo).pick(["title", "description"]).defaults(originalRawSeo).value();
2363
+ return _15.chain(parsedSeo).pick(["title", "description"]).defaults(originalRawSeo).value();
2156
2364
  }
2157
2365
  function deserializeBlockList(parsedBlockList, originalRawBlockList, isClean = false) {
2158
- return _14.chain(parsedBlockList).map((block, i) => deserializeBlock(block, originalRawBlockList[i], isClean)).value();
2366
+ return _15.chain(parsedBlockList).map((block, i) => deserializeBlock(block, originalRawBlockList[i], isClean)).value();
2159
2367
  }
2160
2368
  function deserializeStructuredText(parsedStructuredText, originalRawStructuredText) {
2161
- const result = _14.cloneDeep(originalRawStructuredText);
2162
- for (const [path9, value] of _14.entries(parsedStructuredText)) {
2163
- const realPath = _14.chain(path9.split(".")).flatMap((s) => !_14.isNaN(_14.toNumber(s)) ? ["children", s] : s).value();
2164
- const deserializedValue = createRawDatoValue(value, _14.get(originalRawStructuredText, realPath), true);
2165
- _14.set(result, realPath, deserializedValue);
2369
+ const result = _15.cloneDeep(originalRawStructuredText);
2370
+ for (const [path11, value] of _15.entries(parsedStructuredText)) {
2371
+ const realPath = _15.chain(path11.split(".")).flatMap((s) => !_15.isNaN(_15.toNumber(s)) ? ["children", s] : s).value();
2372
+ const deserializedValue = createRawDatoValue(value, _15.get(originalRawStructuredText, realPath), true);
2373
+ _15.set(result, realPath, deserializedValue);
2166
2374
  }
2167
2375
  return result;
2168
2376
  }
2169
2377
  function _isJson(rawDatoValue) {
2170
2378
  try {
2171
- return _14.isString(rawDatoValue) && rawDatoValue.startsWith("{") && rawDatoValue.endsWith("}") && !!JSON.parse(rawDatoValue);
2379
+ return _15.isString(rawDatoValue) && rawDatoValue.startsWith("{") && rawDatoValue.endsWith("}") && !!JSON.parse(rawDatoValue);
2172
2380
  } catch (e) {
2173
2381
  return false;
2174
2382
  }
2175
2383
  }
2176
2384
  function _isFile(rawDatoValue) {
2177
- return _14.isObject(rawDatoValue) && ["alt", "title", "custom_data", "focal_point", "upload_id"].every((key) => _14.has(rawDatoValue, key));
2385
+ return _15.isObject(rawDatoValue) && ["alt", "title", "custom_data", "focal_point", "upload_id"].every((key) => _15.has(rawDatoValue, key));
2178
2386
  }
2179
2387
  function _isVideo(rawDatoValue) {
2180
- return _14.isObject(rawDatoValue) && ["url", "title", "width", "height", "provider", "provider_uid", "thumbnail_url"].every(
2181
- (key) => _14.has(rawDatoValue, key)
2388
+ return _15.isObject(rawDatoValue) && ["url", "title", "width", "height", "provider", "provider_uid", "thumbnail_url"].every(
2389
+ (key) => _15.has(rawDatoValue, key)
2182
2390
  );
2183
2391
  }
2184
2392
 
2185
2393
  // src/cli/loaders/dato/index.ts
2186
2394
  function createDatoLoader(configFilePath) {
2187
2395
  try {
2188
- const configContent = fs6.readFileSync(configFilePath, "utf-8");
2396
+ const configContent = fs7.readFileSync(configFilePath, "utf-8");
2189
2397
  const datoConfig = datoConfigSchema.parse(JSON5.parse(configContent));
2190
2398
  return composeLoaders(
2191
2399
  createDatoApiLoader(
2192
2400
  datoConfig,
2193
- (updatedConfig) => fs6.writeFileSync(configFilePath, JSON5.stringify(updatedConfig, null, 2))
2401
+ (updatedConfig) => fs7.writeFileSync(configFilePath, JSON5.stringify(updatedConfig, null, 2))
2194
2402
  ),
2195
2403
  createDatoFilterLoader(),
2196
2404
  createDatoExtractLoader()
@@ -2204,8 +2412,8 @@ function createDatoLoader(configFilePath) {
2204
2412
  import webvtt from "node-webvtt";
2205
2413
  function createVttLoader() {
2206
2414
  return createLoader({
2207
- async pull(locale, input) {
2208
- const vtt = webvtt.parse(input)?.cues;
2415
+ async pull(locale, input2) {
2416
+ const vtt = webvtt.parse(input2)?.cues;
2209
2417
  if (Object.keys(vtt).length === 0) {
2210
2418
  return {};
2211
2419
  } else {
@@ -2228,27 +2436,27 @@ function createVttLoader() {
2228
2436
  text
2229
2437
  };
2230
2438
  });
2231
- const input = {
2439
+ const input2 = {
2232
2440
  valid: true,
2233
2441
  strict: true,
2234
2442
  cues: output
2235
2443
  };
2236
- return webvtt.compile(input);
2444
+ return webvtt.compile(input2);
2237
2445
  }
2238
2446
  });
2239
2447
  }
2240
2448
 
2241
2449
  // src/cli/loaders/variable/index.ts
2242
- import _15 from "lodash";
2450
+ import _16 from "lodash";
2243
2451
  function createVariableLoader(params) {
2244
2452
  return composeLoaders(variableExtractLoader(params), variableContentLoader());
2245
2453
  }
2246
2454
  function variableExtractLoader(params) {
2247
2455
  const specifierPattern = getFormatSpecifierPattern(params.type);
2248
2456
  return createLoader({
2249
- pull: async (locale, input) => {
2457
+ pull: async (locale, input2) => {
2250
2458
  const result = {};
2251
- for (const [key, value] of Object.entries(input)) {
2459
+ for (const [key, value] of Object.entries(input2)) {
2252
2460
  const matches = value.match(specifierPattern) || [];
2253
2461
  result[key] = result[key] || {
2254
2462
  value,
@@ -2281,12 +2489,12 @@ function variableExtractLoader(params) {
2281
2489
  }
2282
2490
  function variableContentLoader() {
2283
2491
  return createLoader({
2284
- pull: async (locale, input) => {
2285
- const result = _15.mapValues(input, (payload) => payload.value);
2492
+ pull: async (locale, input2) => {
2493
+ const result = _16.mapValues(input2, (payload) => payload.value);
2286
2494
  return result;
2287
2495
  },
2288
2496
  push: async (locale, data, originalInput) => {
2289
- const result = _15.cloneDeep(originalInput || {});
2497
+ const result = _16.cloneDeep(originalInput || {});
2290
2498
  for (const [key, originalValueObj] of Object.entries(result)) {
2291
2499
  result[key] = {
2292
2500
  ...originalValueObj,
@@ -2309,20 +2517,20 @@ function getFormatSpecifierPattern(type) {
2309
2517
  }
2310
2518
 
2311
2519
  // src/cli/loaders/sync.ts
2312
- import _16 from "lodash";
2520
+ import _17 from "lodash";
2313
2521
  function createSyncLoader() {
2314
2522
  return createLoader({
2315
- async pull(locale, input, originalInput) {
2523
+ async pull(locale, input2, originalInput) {
2316
2524
  if (!originalInput) {
2317
- return input;
2525
+ return input2;
2318
2526
  }
2319
- return _16.chain(originalInput).mapValues((value, key) => input[key]).value();
2527
+ return _17.chain(originalInput).mapValues((value, key) => input2[key]).value();
2320
2528
  },
2321
2529
  async push(locale, data, originalInput) {
2322
2530
  if (!originalInput) {
2323
2531
  return data;
2324
2532
  }
2325
- return _16.chain(originalInput || {}).mapValues((value, key) => data[key]).value();
2533
+ return _17.chain(originalInput || {}).mapValues((value, key) => data[key]).value();
2326
2534
  }
2327
2535
  });
2328
2536
  }
@@ -2387,7 +2595,7 @@ function createPlutilJsonTextLoader() {
2387
2595
  }
2388
2596
 
2389
2597
  // src/cli/loaders/index.ts
2390
- function createBucketLoader(bucketType, bucketPathPattern) {
2598
+ function createBucketLoader(bucketType, bucketPathPattern, { isCacheRestore = false } = {}) {
2391
2599
  switch (bucketType) {
2392
2600
  default:
2393
2601
  throw new Error(`Unsupported bucket type: ${bucketType}`);
@@ -2397,7 +2605,7 @@ function createBucketLoader(bucketType, bucketPathPattern) {
2397
2605
  createAndroidLoader(),
2398
2606
  createFlatLoader(),
2399
2607
  createSyncLoader(),
2400
- createUnlocalizableLoader()
2608
+ createUnlocalizableLoader(isCacheRestore)
2401
2609
  );
2402
2610
  case "csv":
2403
2611
  return composeLoaders(
@@ -2405,7 +2613,7 @@ function createBucketLoader(bucketType, bucketPathPattern) {
2405
2613
  createCsvLoader(),
2406
2614
  createFlatLoader(),
2407
2615
  createSyncLoader(),
2408
- createUnlocalizableLoader()
2616
+ createUnlocalizableLoader(isCacheRestore)
2409
2617
  );
2410
2618
  case "html":
2411
2619
  return composeLoaders(
@@ -2413,7 +2621,7 @@ function createBucketLoader(bucketType, bucketPathPattern) {
2413
2621
  createPrettierLoader({ parser: "html", alwaysFormat: true }),
2414
2622
  createHtmlLoader(),
2415
2623
  createSyncLoader(),
2416
- createUnlocalizableLoader()
2624
+ createUnlocalizableLoader(isCacheRestore)
2417
2625
  );
2418
2626
  case "json":
2419
2627
  return composeLoaders(
@@ -2422,7 +2630,7 @@ function createBucketLoader(bucketType, bucketPathPattern) {
2422
2630
  createJsonLoader(),
2423
2631
  createFlatLoader(),
2424
2632
  createSyncLoader(),
2425
- createUnlocalizableLoader()
2633
+ createUnlocalizableLoader(isCacheRestore)
2426
2634
  );
2427
2635
  case "markdown":
2428
2636
  return composeLoaders(
@@ -2430,7 +2638,7 @@ function createBucketLoader(bucketType, bucketPathPattern) {
2430
2638
  createPrettierLoader({ parser: "markdown" }),
2431
2639
  createMarkdownLoader(),
2432
2640
  createSyncLoader(),
2433
- createUnlocalizableLoader()
2641
+ createUnlocalizableLoader(isCacheRestore)
2434
2642
  );
2435
2643
  case "po":
2436
2644
  return composeLoaders(
@@ -2438,7 +2646,7 @@ function createBucketLoader(bucketType, bucketPathPattern) {
2438
2646
  createPoLoader(),
2439
2647
  createFlatLoader(),
2440
2648
  createSyncLoader(),
2441
- createUnlocalizableLoader(),
2649
+ createUnlocalizableLoader(isCacheRestore),
2442
2650
  createVariableLoader({ type: "python" })
2443
2651
  );
2444
2652
  case "properties":
@@ -2446,14 +2654,14 @@ function createBucketLoader(bucketType, bucketPathPattern) {
2446
2654
  createTextFileLoader(bucketPathPattern),
2447
2655
  createPropertiesLoader(),
2448
2656
  createSyncLoader(),
2449
- createUnlocalizableLoader()
2657
+ createUnlocalizableLoader(isCacheRestore)
2450
2658
  );
2451
2659
  case "xcode-strings":
2452
2660
  return composeLoaders(
2453
2661
  createTextFileLoader(bucketPathPattern),
2454
2662
  createXcodeStringsLoader(),
2455
2663
  createSyncLoader(),
2456
- createUnlocalizableLoader()
2664
+ createUnlocalizableLoader(isCacheRestore)
2457
2665
  );
2458
2666
  case "xcode-stringsdict":
2459
2667
  return composeLoaders(
@@ -2461,7 +2669,7 @@ function createBucketLoader(bucketType, bucketPathPattern) {
2461
2669
  createXcodeStringsdictLoader(),
2462
2670
  createFlatLoader(),
2463
2671
  createSyncLoader(),
2464
- createUnlocalizableLoader()
2672
+ createUnlocalizableLoader(isCacheRestore)
2465
2673
  );
2466
2674
  case "xcode-xcstrings":
2467
2675
  return composeLoaders(
@@ -2471,7 +2679,7 @@ function createBucketLoader(bucketType, bucketPathPattern) {
2471
2679
  createXcodeXcstringsLoader(),
2472
2680
  createFlatLoader(),
2473
2681
  createSyncLoader(),
2474
- createUnlocalizableLoader(),
2682
+ createUnlocalizableLoader(isCacheRestore),
2475
2683
  createVariableLoader({ type: "ieee" })
2476
2684
  );
2477
2685
  case "yaml":
@@ -2481,7 +2689,7 @@ function createBucketLoader(bucketType, bucketPathPattern) {
2481
2689
  createYamlLoader(),
2482
2690
  createFlatLoader(),
2483
2691
  createSyncLoader(),
2484
- createUnlocalizableLoader()
2692
+ createUnlocalizableLoader(isCacheRestore)
2485
2693
  );
2486
2694
  case "yaml-root-key":
2487
2695
  return composeLoaders(
@@ -2491,7 +2699,7 @@ function createBucketLoader(bucketType, bucketPathPattern) {
2491
2699
  createRootKeyLoader(true),
2492
2700
  createFlatLoader(),
2493
2701
  createSyncLoader(),
2494
- createUnlocalizableLoader()
2702
+ createUnlocalizableLoader(isCacheRestore)
2495
2703
  );
2496
2704
  case "flutter":
2497
2705
  return composeLoaders(
@@ -2501,7 +2709,7 @@ function createBucketLoader(bucketType, bucketPathPattern) {
2501
2709
  createFlutterLoader(),
2502
2710
  createFlatLoader(),
2503
2711
  createSyncLoader(),
2504
- createUnlocalizableLoader()
2712
+ createUnlocalizableLoader(isCacheRestore)
2505
2713
  );
2506
2714
  case "xliff":
2507
2715
  return composeLoaders(
@@ -2509,7 +2717,7 @@ function createBucketLoader(bucketType, bucketPathPattern) {
2509
2717
  createXliffLoader(),
2510
2718
  createFlatLoader(),
2511
2719
  createSyncLoader(),
2512
- createUnlocalizableLoader()
2720
+ createUnlocalizableLoader(isCacheRestore)
2513
2721
  );
2514
2722
  case "xml":
2515
2723
  return composeLoaders(
@@ -2517,84 +2725,84 @@ function createBucketLoader(bucketType, bucketPathPattern) {
2517
2725
  createXmlLoader(),
2518
2726
  createFlatLoader(),
2519
2727
  createSyncLoader(),
2520
- createUnlocalizableLoader()
2728
+ createUnlocalizableLoader(isCacheRestore)
2521
2729
  );
2522
2730
  case "srt":
2523
2731
  return composeLoaders(
2524
2732
  createTextFileLoader(bucketPathPattern),
2525
2733
  createSrtLoader(),
2526
2734
  createSyncLoader(),
2527
- createUnlocalizableLoader()
2735
+ createUnlocalizableLoader(isCacheRestore)
2528
2736
  );
2529
2737
  case "dato":
2530
2738
  return composeLoaders(
2531
2739
  createDatoLoader(bucketPathPattern),
2532
2740
  createSyncLoader(),
2533
2741
  createFlatLoader(),
2534
- createUnlocalizableLoader()
2742
+ createUnlocalizableLoader(isCacheRestore)
2535
2743
  );
2536
2744
  case "vtt":
2537
2745
  return composeLoaders(
2538
2746
  createTextFileLoader(bucketPathPattern),
2539
2747
  createVttLoader(),
2540
2748
  createSyncLoader(),
2541
- createUnlocalizableLoader()
2749
+ createUnlocalizableLoader(isCacheRestore)
2542
2750
  );
2543
2751
  }
2544
2752
  }
2545
2753
 
2546
2754
  // src/cli/utils/lockfile.ts
2547
- import fs7 from "fs";
2548
- import path7 from "path";
2755
+ import fs8 from "fs";
2756
+ import path9 from "path";
2549
2757
  import Z3 from "zod";
2550
2758
  import YAML3 from "yaml";
2551
2759
  import { MD5 } from "object-hash";
2552
- import _17 from "lodash";
2760
+ import _18 from "lodash";
2553
2761
  function createLockfileHelper() {
2554
2762
  return {
2555
2763
  isLockfileExists: () => {
2556
2764
  const lockfilePath = _getLockfilePath();
2557
- return fs7.existsSync(lockfilePath);
2765
+ return fs8.existsSync(lockfilePath);
2558
2766
  },
2559
2767
  registerSourceData: (pathPattern, sourceData) => {
2560
2768
  const lockfile = _loadLockfile();
2561
2769
  const sectionKey = MD5(pathPattern);
2562
- const sectionChecksums = _17.mapValues(sourceData, (value) => MD5(value));
2770
+ const sectionChecksums = _18.mapValues(sourceData, (value) => MD5(value));
2563
2771
  lockfile.checksums[sectionKey] = sectionChecksums;
2564
2772
  _saveLockfile(lockfile);
2565
2773
  },
2566
2774
  registerPartialSourceData: (pathPattern, partialSourceData) => {
2567
2775
  const lockfile = _loadLockfile();
2568
2776
  const sectionKey = MD5(pathPattern);
2569
- const sectionChecksums = _17.mapValues(partialSourceData, (value) => MD5(value));
2570
- lockfile.checksums[sectionKey] = _17.merge({}, lockfile.checksums[sectionKey] ?? {}, sectionChecksums);
2777
+ const sectionChecksums = _18.mapValues(partialSourceData, (value) => MD5(value));
2778
+ lockfile.checksums[sectionKey] = _18.merge({}, lockfile.checksums[sectionKey] ?? {}, sectionChecksums);
2571
2779
  _saveLockfile(lockfile);
2572
2780
  },
2573
2781
  extractUpdatedData: (pathPattern, sourceData) => {
2574
2782
  const lockfile = _loadLockfile();
2575
2783
  const sectionKey = MD5(pathPattern);
2576
- const currentChecksums = _17.mapValues(sourceData, (value) => MD5(value));
2784
+ const currentChecksums = _18.mapValues(sourceData, (value) => MD5(value));
2577
2785
  const savedChecksums = lockfile.checksums[sectionKey] || {};
2578
- const updatedData = _17.pickBy(sourceData, (value, key) => savedChecksums[key] !== currentChecksums[key]);
2786
+ const updatedData = _18.pickBy(sourceData, (value, key) => savedChecksums[key] !== currentChecksums[key]);
2579
2787
  return updatedData;
2580
2788
  }
2581
2789
  };
2582
2790
  function _loadLockfile() {
2583
2791
  const lockfilePath = _getLockfilePath();
2584
- if (!fs7.existsSync(lockfilePath)) {
2792
+ if (!fs8.existsSync(lockfilePath)) {
2585
2793
  return LockfileSchema.parse({});
2586
2794
  }
2587
- const content = fs7.readFileSync(lockfilePath, "utf-8");
2795
+ const content = fs8.readFileSync(lockfilePath, "utf-8");
2588
2796
  const result = LockfileSchema.parse(YAML3.parse(content));
2589
2797
  return result;
2590
2798
  }
2591
2799
  function _saveLockfile(lockfile) {
2592
2800
  const lockfilePath = _getLockfilePath();
2593
2801
  const content = YAML3.stringify(lockfile);
2594
- fs7.writeFileSync(lockfilePath, content);
2802
+ fs8.writeFileSync(lockfilePath, content);
2595
2803
  }
2596
2804
  function _getLockfilePath() {
2597
- return path7.join(process.cwd(), "i18n.lock");
2805
+ return path9.join(process.cwd(), "i18n.lock");
2598
2806
  }
2599
2807
  }
2600
2808
  var LockfileSchema = Z3.object({
@@ -2619,8 +2827,8 @@ import inquirer2 from "inquirer";
2619
2827
  import externalEditor from "external-editor";
2620
2828
 
2621
2829
  // src/cli/utils/cache.ts
2622
- import path8 from "path";
2623
- import fs8 from "fs";
2830
+ import path10 from "path";
2831
+ import fs9 from "fs";
2624
2832
  var cacheChunk = (targetLocale, sourceChunk, processedChunk) => {
2625
2833
  const rows = Object.entries(sourceChunk).map(([key, source]) => ({
2626
2834
  targetLocale,
@@ -2650,26 +2858,26 @@ function getNormalizedCache() {
2650
2858
  function deleteCache() {
2651
2859
  const cacheFilePath = _getCacheFilePath();
2652
2860
  try {
2653
- fs8.unlinkSync(cacheFilePath);
2861
+ fs9.unlinkSync(cacheFilePath);
2654
2862
  } catch (e) {
2655
2863
  }
2656
2864
  }
2657
2865
  function _loadCache() {
2658
2866
  const cacheFilePath = _getCacheFilePath();
2659
- if (!fs8.existsSync(cacheFilePath)) {
2867
+ if (!fs9.existsSync(cacheFilePath)) {
2660
2868
  return [];
2661
2869
  }
2662
- const content = fs8.readFileSync(cacheFilePath, "utf-8");
2870
+ const content = fs9.readFileSync(cacheFilePath, "utf-8");
2663
2871
  const result = _parseJSONLines(content);
2664
2872
  return result;
2665
2873
  }
2666
2874
  function _appendToCache(rows) {
2667
2875
  const cacheFilePath = _getCacheFilePath();
2668
2876
  const lines = _buildJSONLines(rows);
2669
- fs8.appendFileSync(cacheFilePath, lines);
2877
+ fs9.appendFileSync(cacheFilePath, lines);
2670
2878
  }
2671
2879
  function _getCacheFilePath() {
2672
- return path8.join(process.cwd(), "i18n.cache");
2880
+ return path10.join(process.cwd(), "i18n.cache");
2673
2881
  }
2674
2882
  function _buildJSONLines(rows) {
2675
2883
  return rows.map((row) => JSON.stringify(row)).join("\n") + "\n";
@@ -2745,7 +2953,7 @@ var i18n_default = new Command6().command("i18n").description("Run Localization
2745
2953
  const bucketOra = Ora5({ indent: 4 });
2746
2954
  bucketOra.info(`Processing path: ${bucketConfig.pathPattern}`);
2747
2955
  const sourceLocale = resolveOverridenLocale3(i18nConfig.locale.source, bucketConfig.delimiter);
2748
- const bucketLoader = createBucketLoader(bucket.type, bucketConfig.pathPattern);
2956
+ const bucketLoader = createBucketLoader(bucket.type, bucketConfig.pathPattern, { isCacheRestore: true });
2749
2957
  bucketLoader.setDefaultLocale(sourceLocale);
2750
2958
  await bucketLoader.init();
2751
2959
  const sourceData = await bucketLoader.pull(sourceLocale);
@@ -2823,7 +3031,7 @@ var i18n_default = new Command6().command("i18n").description("Run Localization
2823
3031
  targetData
2824
3032
  });
2825
3033
  if (flags.key) {
2826
- processableData = _18.pickBy(processableData, (_20, key) => key === flags.key);
3034
+ processableData = _19.pickBy(processableData, (_21, key) => key === flags.key);
2827
3035
  }
2828
3036
  if (flags.verbose) {
2829
3037
  bucketOra.info(JSON.stringify(processableData, null, 2));
@@ -2859,7 +3067,7 @@ var i18n_default = new Command6().command("i18n").description("Run Localization
2859
3067
  if (flags.verbose) {
2860
3068
  bucketOra.info(JSON.stringify(processedTargetData, null, 2));
2861
3069
  }
2862
- let finalTargetData = _18.merge({}, sourceData, targetData, processedTargetData);
3070
+ let finalTargetData = _19.merge({}, sourceData, targetData, processedTargetData);
2863
3071
  if (flags.interactive) {
2864
3072
  bucketOra.stop();
2865
3073
  const reviewedData = await reviewChanges({
@@ -2873,7 +3081,7 @@ var i18n_default = new Command6().command("i18n").description("Run Localization
2873
3081
  finalTargetData = reviewedData;
2874
3082
  bucketOra.start(`Applying changes to ${bucketConfig} (${targetLocale})`);
2875
3083
  }
2876
- const finalDiffSize = _18.chain(finalTargetData).omitBy((value, key) => value === targetData[key]).size().value();
3084
+ const finalDiffSize = _19.chain(finalTargetData).omitBy((value, key) => value === targetData[key]).size().value();
2877
3085
  if (finalDiffSize > 0 || flags.force) {
2878
3086
  await bucketLoader.push(targetLocale, finalTargetData);
2879
3087
  bucketOra.succeed(`[${sourceLocale} -> ${targetLocale}] Localization completed`);
@@ -2918,9 +3126,9 @@ var i18n_default = new Command6().command("i18n").description("Run Localization
2918
3126
  }
2919
3127
  });
2920
3128
  function calculateDataDelta(args) {
2921
- const newKeys = _18.difference(Object.keys(args.sourceData), Object.keys(args.targetData));
3129
+ const newKeys = _19.difference(Object.keys(args.sourceData), Object.keys(args.targetData));
2922
3130
  const updatedKeys = Object.keys(args.updatedSourceData);
2923
- const result = _18.chain(args.sourceData).pickBy((value, key) => newKeys.includes(key) || updatedKeys.includes(key)).value();
3131
+ const result = _19.chain(args.sourceData).pickBy((value, key) => newKeys.includes(key) || updatedKeys.includes(key)).value();
2924
3132
  return result;
2925
3133
  }
2926
3134
  async function retryWithExponentialBackoff(operation, maxAttempts, baseDelay = 1e3) {
@@ -3061,7 +3269,7 @@ Reviewing changes for ${chalk.blue(args.pathPattern)} (${chalk.yellow(args.targe
3061
3269
  return args.currentData;
3062
3270
  }
3063
3271
  const customData = { ...args.currentData };
3064
- const changes = _18.reduce(
3272
+ const changes = _19.reduce(
3065
3273
  args.proposedData,
3066
3274
  (result, value, key) => {
3067
3275
  if (args.currentData[key] !== value) {
@@ -3142,7 +3350,7 @@ var flagsSchema = Z5.object({
3142
3350
  // src/cli/cmd/cleanup.ts
3143
3351
  import { resolveOverridenLocale as resolveOverridenLocale5 } from "@lingo.dev/_spec";
3144
3352
  import { Command as Command8 } from "interactive-commander";
3145
- import _19 from "lodash";
3353
+ import _20 from "lodash";
3146
3354
  import Ora7 from "ora";
3147
3355
  var cleanup_default = new Command8().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("--verbose", "Show verbose output").action(async function(options) {
3148
3356
  const ora = Ora7();
@@ -3172,7 +3380,7 @@ var cleanup_default = new Command8().command("cleanup").description("Remove keys
3172
3380
  try {
3173
3381
  const targetData = await bucketLoader.pull(targetLocale);
3174
3382
  const targetKeys = Object.keys(targetData);
3175
- const keysToRemove = _19.difference(targetKeys, sourceKeys);
3383
+ const keysToRemove = _20.difference(targetKeys, sourceKeys);
3176
3384
  if (keysToRemove.length === 0) {
3177
3385
  bucketOra.succeed(`[${targetLocale}] No keys to remove`);
3178
3386
  continue;
@@ -3181,7 +3389,7 @@ var cleanup_default = new Command8().command("cleanup").description("Remove keys
3181
3389
  bucketOra.info(`[${targetLocale}] Keys to remove: ${JSON.stringify(keysToRemove, null, 2)}`);
3182
3390
  }
3183
3391
  if (!options.dryRun) {
3184
- const cleanedData = _19.pick(targetData, sourceKeys);
3392
+ const cleanedData = _20.pick(targetData, sourceKeys);
3185
3393
  await bucketLoader.push(targetLocale, cleanedData);
3186
3394
  bucketOra.succeed(`[${targetLocale}] Removed ${keysToRemove.length} keys`);
3187
3395
  } else {
@@ -3233,7 +3441,7 @@ function displaySummary(results) {
3233
3441
  // package.json
3234
3442
  var package_default = {
3235
3443
  name: "lingo.dev",
3236
- version: "0.74.15",
3444
+ version: "0.74.17",
3237
3445
  description: "Lingo.dev CLI",
3238
3446
  private: false,
3239
3447
  publishConfig: {