lingo.dev 0.77.4 → 0.77.6

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
@@ -264,11 +264,11 @@ function _getConfigFilePath() {
264
264
 
265
265
  // src/cli/cmd/init.ts
266
266
  import { defaultConfig, resolveLocaleCode as resolveLocaleCode2, bucketTypes } from "@lingo.dev/_spec";
267
- import fs5 from "fs";
268
- import path6 from "path";
267
+ import fs6 from "fs";
268
+ import path7 from "path";
269
269
  import { spawn } from "child_process";
270
270
  import _3 from "lodash";
271
- import { checkbox, confirm, input } from "@inquirer/prompts";
271
+ import { checkbox as checkbox2, confirm as confirm2, input } from "@inquirer/prompts";
272
272
 
273
273
  // src/cli/utils/find-locale-paths.ts
274
274
  import path3 from "path";
@@ -332,10 +332,11 @@ function findLocaleFilesWithExtension(ext) {
332
332
  });
333
333
  const grouppedFilesAndPatterns = _2.groupBy(localeFilesAndPatterns, "pattern");
334
334
  const patterns = Object.keys(grouppedFilesAndPatterns);
335
+ const defaultPatterns = [`i18n/[locale]${ext}`];
335
336
  if (patterns.length > 0) {
336
- return { found: true, patterns };
337
+ return { patterns, defaultPatterns };
337
338
  }
338
- return { found: false, patterns: [`i18n/[locale]${ext}`] };
339
+ return { patterns: [], defaultPatterns };
339
340
  }
340
341
  function findLocaleFilesForFilename(fileName) {
341
342
  const pattern = fileName;
@@ -348,10 +349,11 @@ function findLocaleFilesForFilename(fileName) {
348
349
  }));
349
350
  const grouppedFilesAndPatterns = _2.groupBy(localeFilesAndPatterns, "pattern");
350
351
  const patterns = Object.keys(grouppedFilesAndPatterns);
352
+ const defaultPatterns = [fileName];
351
353
  if (patterns.length > 0) {
352
- return { found: true, patterns };
354
+ return { patterns, defaultPatterns };
353
355
  }
354
- return { found: false, patterns: [fileName] };
356
+ return { patterns: [], defaultPatterns };
355
357
  }
356
358
 
357
359
  // src/cli/utils/ensure-patterns.ts
@@ -473,10 +475,136 @@ function findCurrentProjectRoot() {
473
475
  return null;
474
476
  }
475
477
 
478
+ // src/cli/utils/init-ci-cd.ts
479
+ import { checkbox, confirm } from "@inquirer/prompts";
480
+ import fs5 from "fs";
481
+ import path6 from "path";
482
+ var platforms = ["github", "bitbucket", "gitlab"];
483
+ async function initCICD(spinner) {
484
+ const initializers = getPlatformInitializers(spinner);
485
+ const init = await confirm({
486
+ message: "Would you like to use Lingo.dev in your CI/CD?"
487
+ });
488
+ if (!init) {
489
+ spinner.warn("CI/CD not initialized. To set it up later, see docs: https://docs.lingo.dev/ci-action/overview");
490
+ return;
491
+ }
492
+ const selectedPlatforms = await checkbox({
493
+ message: "Please select CI/CD platform(s) you want to use:",
494
+ choices: platforms.map((platform) => ({
495
+ name: initializers[platform].name,
496
+ value: platform,
497
+ checked: initializers[platform].isEnabled()
498
+ }))
499
+ });
500
+ for (const platform of selectedPlatforms) {
501
+ await initializers[platform].init();
502
+ }
503
+ }
504
+ function getPlatformInitializers(spinner) {
505
+ return {
506
+ github: makeGithubInitializer(spinner),
507
+ bitbucket: makeBitbucketInitializer(spinner),
508
+ gitlab: makeGitlabInitializer(spinner)
509
+ };
510
+ }
511
+ function makePlatformInitializer(config, spinner) {
512
+ return {
513
+ name: config.name,
514
+ isEnabled: () => {
515
+ const filePath = path6.join(process.cwd(), config.checkPath);
516
+ return fs5.existsSync(filePath);
517
+ },
518
+ init: async () => {
519
+ const filePath = path6.join(process.cwd(), config.ciConfigPath);
520
+ const dirPath = path6.dirname(filePath);
521
+ if (!fs5.existsSync(dirPath)) {
522
+ fs5.mkdirSync(dirPath, { recursive: true });
523
+ }
524
+ let canWrite = true;
525
+ if (fs5.existsSync(filePath)) {
526
+ canWrite = await confirm({
527
+ message: `File ${filePath} already exists. Do you want to overwrite it?`,
528
+ default: false
529
+ });
530
+ }
531
+ if (canWrite) {
532
+ fs5.writeFileSync(filePath, config.ciConfigContent);
533
+ spinner.succeed(`CI/CD initialized for ${config.name}`);
534
+ } else {
535
+ spinner.warn(`CI/CD not initialized for ${config.name}`);
536
+ }
537
+ }
538
+ };
539
+ }
540
+ function makeGithubInitializer(spinner) {
541
+ return makePlatformInitializer(
542
+ {
543
+ name: "GitHub Action",
544
+ checkPath: ".github",
545
+ ciConfigPath: ".github/workflows/i18n.yml",
546
+ ciConfigContent: `name: Lingo.dev i18n
547
+
548
+ on:
549
+ push:
550
+ branches:
551
+ - main
552
+
553
+ permissions:
554
+ contents: write
555
+ pull-requests: write
556
+
557
+ jobs:
558
+ i18n:
559
+ name: Run i18n
560
+ runs-on: ubuntu-latest
561
+ steps:
562
+ - uses: actions/checkout@v4
563
+ - uses: lingodotdev/lingo.dev@main
564
+ with:
565
+ api-key: \${{ secrets.LINGODOTDEV_API_KEY }}
566
+ `
567
+ },
568
+ spinner
569
+ );
570
+ }
571
+ function makeBitbucketInitializer(spinner) {
572
+ return makePlatformInitializer(
573
+ {
574
+ name: "Bitbucket Pipeline",
575
+ checkPath: "bitbucket-pipelines.yml",
576
+ ciConfigPath: "bitbucket-pipelines.yml",
577
+ ciConfigContent: `pipelines:
578
+ branches:
579
+ main:
580
+ - step:
581
+ name: Run i18n
582
+ script:
583
+ - pipe: lingodotdev/lingo.dev:main`
584
+ },
585
+ spinner
586
+ );
587
+ }
588
+ function makeGitlabInitializer(spinner) {
589
+ return makePlatformInitializer(
590
+ {
591
+ name: "Gitlab CI",
592
+ checkPath: ".gitlab-ci.yml",
593
+ ciConfigPath: ".gitlab-ci.yml",
594
+ ciConfigContent: `lingodotdev:
595
+ image: lingodotdev/ci-action:latest
596
+ script:
597
+ - echo "Done"
598
+ `
599
+ },
600
+ spinner
601
+ );
602
+ }
603
+
476
604
  // src/cli/cmd/init.ts
477
- var openUrl = (path12) => {
605
+ var openUrl = (path13) => {
478
606
  const settings = getSettings(void 0);
479
- spawn("open", [`${settings.auth.webUrl}${path12}`]);
607
+ spawn("open", [`${settings.auth.webUrl}${path13}`]);
480
608
  };
481
609
  var throwHelpError = (option, value) => {
482
610
  if (value === "help") {
@@ -522,8 +650,8 @@ var init_default = new InteractiveCommand().command("init").description("Initial
522
650
  const values = value.includes(",") ? value.split(",") : value.split(" ");
523
651
  for (const p of values) {
524
652
  try {
525
- const dirPath = path6.dirname(p);
526
- const stats = fs5.statSync(dirPath);
653
+ const dirPath = path7.dirname(p);
654
+ const stats = fs6.statSync(dirPath);
527
655
  if (!stats.isDirectory()) {
528
656
  throw new Error(`${dirPath} is not a directory`);
529
657
  }
@@ -553,10 +681,10 @@ var init_default = new InteractiveCommand().command("init").description("Initial
553
681
  };
554
682
  } else {
555
683
  let selectedPatterns = [];
556
- const { found, patterns } = findLocaleFiles(options.bucket);
557
- if (found) {
684
+ const { patterns, defaultPatterns } = findLocaleFiles(options.bucket);
685
+ if (patterns.length > 0) {
558
686
  spinner.succeed("Found existing locale files:");
559
- selectedPatterns = await checkbox({
687
+ selectedPatterns = await checkbox2({
560
688
  message: "Select the paths to use",
561
689
  choices: patterns.map((value) => ({
562
690
  value
@@ -566,12 +694,12 @@ var init_default = new InteractiveCommand().command("init").description("Initial
566
694
  spinner.succeed("No existing locale files found.");
567
695
  }
568
696
  if (selectedPatterns.length === 0) {
569
- const useDefault = await confirm({
570
- message: `Use (and create) default path ${patterns.join(", ")}?`
697
+ const useDefault = await confirm2({
698
+ message: `Use (and create) default path ${defaultPatterns.join(", ")}?`
571
699
  });
572
- ensurePatterns(patterns, options.source);
573
700
  if (useDefault) {
574
- selectedPatterns = patterns;
701
+ ensurePatterns(defaultPatterns, options.source);
702
+ selectedPatterns = defaultPatterns;
575
703
  }
576
704
  }
577
705
  if (selectedPatterns.length === 0) {
@@ -589,7 +717,8 @@ var init_default = new InteractiveCommand().command("init").description("Initial
589
717
  await saveConfig(newConfig);
590
718
  spinner.succeed("Lingo.dev project initialized");
591
719
  if (isInteractive) {
592
- const openDocs = await confirm({ message: "Would you like to see our docs?" });
720
+ await initCICD(spinner);
721
+ const openDocs = await confirm2({ message: "Would you like to see our docs?" });
593
722
  if (openDocs) {
594
723
  openUrl("/go/docs");
595
724
  }
@@ -601,7 +730,7 @@ var init_default = new InteractiveCommand().command("init").description("Initial
601
730
  const auth = await authenticator.whoami();
602
731
  if (!auth) {
603
732
  if (isInteractive) {
604
- const doAuth = await confirm({
733
+ const doAuth = await confirm2({
605
734
  message: "It looks like you are not logged into the CLI. Login now?"
606
735
  });
607
736
  if (doAuth) {
@@ -637,8 +766,8 @@ import { Command as Command5 } from "interactive-commander";
637
766
  // src/cli/cmd/show/config.ts
638
767
  import { Command as Command2 } from "interactive-commander";
639
768
  import _4 from "lodash";
640
- import fs6 from "fs";
641
- import path7 from "path";
769
+ import fs7 from "fs";
770
+ import path8 from "path";
642
771
  import { defaultConfig as defaultConfig2 } from "@lingo.dev/_spec";
643
772
  var config_default = new Command2().command("config").description("Print out the current configuration").helpOption("-h, --help", "Show help").action(async (options) => {
644
773
  const fileConfig = loadReplexicaFileConfig();
@@ -646,12 +775,12 @@ var config_default = new Command2().command("config").description("Print out the
646
775
  console.log(JSON.stringify(config, null, 2));
647
776
  });
648
777
  function loadReplexicaFileConfig() {
649
- const replexicaConfigPath = path7.resolve(process.cwd(), "i18n.json");
650
- const fileExists = fs6.existsSync(replexicaConfigPath);
778
+ const replexicaConfigPath = path8.resolve(process.cwd(), "i18n.json");
779
+ const fileExists = fs7.existsSync(replexicaConfigPath);
651
780
  if (!fileExists) {
652
781
  return void 0;
653
782
  }
654
- const fileContent = fs6.readFileSync(replexicaConfigPath, "utf-8");
783
+ const fileContent = fs7.readFileSync(replexicaConfigPath, "utf-8");
655
784
  const replexicaFileConfig = JSON.parse(fileContent);
656
785
  return replexicaFileConfig;
657
786
  }
@@ -688,7 +817,7 @@ import Ora4 from "ora";
688
817
 
689
818
  // src/cli/utils/buckets.ts
690
819
  import _5 from "lodash";
691
- import path8 from "path";
820
+ import path9 from "path";
692
821
  import { glob as glob2 } from "glob";
693
822
  import { resolveOverridenLocale } from "@lingo.dev/_spec";
694
823
  function getBuckets(i18nConfig) {
@@ -723,9 +852,9 @@ function extractPathPatterns(sourceLocale, include, exclude) {
723
852
  return result;
724
853
  }
725
854
  function expandPlaceholderedGlob(_pathPattern, sourceLocale) {
726
- const absolutePathPattern = path8.resolve(_pathPattern);
727
- const pathPattern = path8.relative(process.cwd(), absolutePathPattern);
728
- if (path8.relative(process.cwd(), pathPattern).startsWith("..")) {
855
+ const absolutePathPattern = path9.resolve(_pathPattern);
856
+ const pathPattern = path9.relative(process.cwd(), absolutePathPattern);
857
+ if (path9.relative(process.cwd(), pathPattern).startsWith("..")) {
729
858
  throw new CLIError({
730
859
  message: `Invalid path pattern: ${pathPattern}. Path pattern must be within the current working directory.`,
731
860
  docUrl: "invalidPathPattern"
@@ -737,7 +866,7 @@ function expandPlaceholderedGlob(_pathPattern, sourceLocale) {
737
866
  docUrl: "invalidPathPattern"
738
867
  });
739
868
  }
740
- const pathPatternChunks = pathPattern.split(path8.sep);
869
+ const pathPatternChunks = pathPattern.split(path9.sep);
741
870
  const localeSegmentIndexes = pathPatternChunks.reduce((indexes, segment, index) => {
742
871
  if (segment.includes("[locale]")) {
743
872
  indexes.push(index);
@@ -745,9 +874,9 @@ function expandPlaceholderedGlob(_pathPattern, sourceLocale) {
745
874
  return indexes;
746
875
  }, []);
747
876
  const sourcePathPattern = pathPattern.replaceAll(/\[locale\]/g, sourceLocale);
748
- const sourcePaths = glob2.sync(sourcePathPattern, { follow: true, withFileTypes: true }).filter((file) => file.isFile() || file.isSymbolicLink()).map((file) => file.fullpath()).map((fullpath) => path8.relative(process.cwd(), fullpath));
877
+ const sourcePaths = glob2.sync(sourcePathPattern, { follow: true, withFileTypes: true }).filter((file) => file.isFile() || file.isSymbolicLink()).map((file) => file.fullpath()).map((fullpath) => path9.relative(process.cwd(), fullpath));
749
878
  const placeholderedPaths = sourcePaths.map((sourcePath) => {
750
- const sourcePathChunks = sourcePath.split(path8.sep);
879
+ const sourcePathChunks = sourcePath.split(path9.sep);
751
880
  localeSegmentIndexes.forEach((localeSegmentIndex) => {
752
881
  const pathPatternChunk = pathPatternChunks[localeSegmentIndex];
753
882
  const sourcePathChunk = sourcePathChunks[localeSegmentIndex];
@@ -761,7 +890,7 @@ function expandPlaceholderedGlob(_pathPattern, sourceLocale) {
761
890
  sourcePathChunks[localeSegmentIndex] = placeholderedSegment;
762
891
  }
763
892
  });
764
- const placeholderedPath = sourcePathChunks.join(path8.sep);
893
+ const placeholderedPath = sourcePathChunks.join(path9.sep);
765
894
  return placeholderedPath;
766
895
  });
767
896
  return placeholderedPaths;
@@ -803,8 +932,8 @@ var files_default = new Command4().command("files").description("Print out the l
803
932
  } else if (type.target) {
804
933
  result.push(...targetPaths);
805
934
  }
806
- result.forEach((path12) => {
807
- console.log(path12);
935
+ result.forEach((path13) => {
936
+ console.log(path13);
808
937
  });
809
938
  }
810
939
  }
@@ -1026,8 +1155,8 @@ function normalizeObjectKeys(obj) {
1026
1155
  }
1027
1156
 
1028
1157
  // src/cli/loaders/text-file.ts
1029
- import fs7 from "fs/promises";
1030
- import path9 from "path";
1158
+ import fs8 from "fs/promises";
1159
+ import path10 from "path";
1031
1160
  function createTextFileLoader(pathPattern) {
1032
1161
  return createLoader({
1033
1162
  async pull(locale) {
@@ -1037,13 +1166,13 @@ function createTextFileLoader(pathPattern) {
1037
1166
  },
1038
1167
  async push(locale, data, _21, originalLocale) {
1039
1168
  const draftPath = pathPattern.replaceAll("[locale]", locale);
1040
- const finalPath = path9.resolve(draftPath);
1041
- const dirPath = path9.dirname(finalPath);
1042
- await fs7.mkdir(dirPath, { recursive: true });
1169
+ const finalPath = path10.resolve(draftPath);
1170
+ const dirPath = path10.dirname(finalPath);
1171
+ await fs8.mkdir(dirPath, { recursive: true });
1043
1172
  const trimmedPayload = data.trim();
1044
1173
  const trailingNewLine = await getTrailingNewLine(pathPattern, locale, originalLocale);
1045
1174
  let finalPayload = trimmedPayload + trailingNewLine;
1046
- await fs7.writeFile(finalPath, finalPayload, {
1175
+ await fs8.writeFile(finalPath, finalPayload, {
1047
1176
  encoding: "utf-8",
1048
1177
  flag: "w"
1049
1178
  });
@@ -1052,12 +1181,12 @@ function createTextFileLoader(pathPattern) {
1052
1181
  }
1053
1182
  async function readFileForLocale(pathPattern, locale) {
1054
1183
  const draftPath = pathPattern.replaceAll("[locale]", locale);
1055
- const finalPath = path9.resolve(draftPath);
1056
- const exists = await fs7.access(finalPath).then(() => true).catch(() => false);
1184
+ const finalPath = path10.resolve(draftPath);
1185
+ const exists = await fs8.access(finalPath).then(() => true).catch(() => false);
1057
1186
  if (!exists) {
1058
1187
  return "";
1059
1188
  }
1060
- return fs7.readFile(finalPath, "utf-8");
1189
+ return fs8.readFile(finalPath, "utf-8");
1061
1190
  }
1062
1191
  async function getTrailingNewLine(pathPattern, locale, originalLocale) {
1063
1192
  let templateData = await readFileForLocale(pathPattern, locale);
@@ -1344,9 +1473,9 @@ function createHtmlLoader() {
1344
1473
  const bDepth = b.split("/").length;
1345
1474
  return aDepth - bDepth;
1346
1475
  });
1347
- paths.forEach((path12) => {
1348
- const value = data[path12];
1349
- const [nodePath, attribute] = path12.split("#");
1476
+ paths.forEach((path13) => {
1477
+ const value = data[path13];
1478
+ const [nodePath, attribute] = path13.split("#");
1350
1479
  const [rootTag, ...indices] = nodePath.split("/");
1351
1480
  let parent = rootTag === "head" ? document.head : document.body;
1352
1481
  let current = parent;
@@ -1647,7 +1776,7 @@ import { isValid, parseISO } from "date-fns";
1647
1776
  function createUnlocalizableLoader(isCacheRestore = false) {
1648
1777
  const rules = {
1649
1778
  isEmpty: (v) => _10.isEmpty(v),
1650
- isNumber: (v) => !_10.isNaN(_10.toNumber(v)),
1779
+ isNumber: (v) => typeof v === "number" || /^[0-9]+$/.test(v),
1651
1780
  isBoolean: (v) => _10.isBoolean(v),
1652
1781
  isIsoDate: (v) => _10.isString(v) && _isIsoDate(v),
1653
1782
  isSystemId: (v) => _10.isString(v) && _isSystemId(v),
@@ -1850,7 +1979,7 @@ function createSrtLoader() {
1850
1979
  }
1851
1980
 
1852
1981
  // src/cli/loaders/dato/index.ts
1853
- import fs8 from "fs";
1982
+ import fs9 from "fs";
1854
1983
  import JSON5 from "json5";
1855
1984
 
1856
1985
  // src/cli/loaders/dato/_base.ts
@@ -2353,18 +2482,18 @@ function createRawDatoValue(parsedDatoValue, originalRawDatoValue, isClean = fal
2353
2482
  }
2354
2483
  function serializeStructuredText(rawStructuredText) {
2355
2484
  return serializeStructuredTextNode(rawStructuredText);
2356
- function serializeStructuredTextNode(node, path12 = [], acc = {}) {
2485
+ function serializeStructuredTextNode(node, path13 = [], acc = {}) {
2357
2486
  if ("document" in node) {
2358
- return serializeStructuredTextNode(node.document, [...path12, "document"], acc);
2487
+ return serializeStructuredTextNode(node.document, [...path13, "document"], acc);
2359
2488
  }
2360
2489
  if (!_15.isNil(node.value)) {
2361
- acc[[...path12, "value"].join(".")] = node.value;
2490
+ acc[[...path13, "value"].join(".")] = node.value;
2362
2491
  } else if (_15.get(node, "type") === "block") {
2363
- acc[[...path12, "item"].join(".")] = serializeBlock(node.item);
2492
+ acc[[...path13, "item"].join(".")] = serializeBlock(node.item);
2364
2493
  }
2365
2494
  if (node.children) {
2366
2495
  for (let i = 0; i < node.children.length; i++) {
2367
- serializeStructuredTextNode(node.children[i], [...path12, i.toString()], acc);
2496
+ serializeStructuredTextNode(node.children[i], [...path13, i.toString()], acc);
2368
2497
  }
2369
2498
  }
2370
2499
  return acc;
@@ -2423,8 +2552,8 @@ function deserializeBlockList(parsedBlockList, originalRawBlockList, isClean = f
2423
2552
  }
2424
2553
  function deserializeStructuredText(parsedStructuredText, originalRawStructuredText) {
2425
2554
  const result = _15.cloneDeep(originalRawStructuredText);
2426
- for (const [path12, value] of _15.entries(parsedStructuredText)) {
2427
- const realPath = _15.chain(path12.split(".")).flatMap((s) => !_15.isNaN(_15.toNumber(s)) ? ["children", s] : s).value();
2555
+ for (const [path13, value] of _15.entries(parsedStructuredText)) {
2556
+ const realPath = _15.chain(path13.split(".")).flatMap((s) => !_15.isNaN(_15.toNumber(s)) ? ["children", s] : s).value();
2428
2557
  const deserializedValue = createRawDatoValue(value, _15.get(originalRawStructuredText, realPath), true);
2429
2558
  _15.set(result, realPath, deserializedValue);
2430
2559
  }
@@ -2449,12 +2578,12 @@ function _isVideo(rawDatoValue) {
2449
2578
  // src/cli/loaders/dato/index.ts
2450
2579
  function createDatoLoader(configFilePath) {
2451
2580
  try {
2452
- const configContent = fs8.readFileSync(configFilePath, "utf-8");
2581
+ const configContent = fs9.readFileSync(configFilePath, "utf-8");
2453
2582
  const datoConfig = datoConfigSchema.parse(JSON5.parse(configContent));
2454
2583
  return composeLoaders(
2455
2584
  createDatoApiLoader(
2456
2585
  datoConfig,
2457
- (updatedConfig) => fs8.writeFileSync(configFilePath, JSON5.stringify(updatedConfig, null, 2))
2586
+ (updatedConfig) => fs9.writeFileSync(configFilePath, JSON5.stringify(updatedConfig, null, 2))
2458
2587
  ),
2459
2588
  createDatoFilterLoader(),
2460
2589
  createDatoExtractLoader()
@@ -2876,8 +3005,8 @@ function createBucketLoader(bucketType, bucketPathPattern, { isCacheRestore = fa
2876
3005
  }
2877
3006
 
2878
3007
  // src/cli/utils/lockfile.ts
2879
- import fs9 from "fs";
2880
- import path10 from "path";
3008
+ import fs10 from "fs";
3009
+ import path11 from "path";
2881
3010
  import Z3 from "zod";
2882
3011
  import YAML3 from "yaml";
2883
3012
  import { MD5 } from "object-hash";
@@ -2886,7 +3015,7 @@ function createLockfileHelper() {
2886
3015
  return {
2887
3016
  isLockfileExists: () => {
2888
3017
  const lockfilePath = _getLockfilePath();
2889
- return fs9.existsSync(lockfilePath);
3018
+ return fs10.existsSync(lockfilePath);
2890
3019
  },
2891
3020
  registerSourceData: (pathPattern, sourceData) => {
2892
3021
  const lockfile = _loadLockfile();
@@ -2913,20 +3042,20 @@ function createLockfileHelper() {
2913
3042
  };
2914
3043
  function _loadLockfile() {
2915
3044
  const lockfilePath = _getLockfilePath();
2916
- if (!fs9.existsSync(lockfilePath)) {
3045
+ if (!fs10.existsSync(lockfilePath)) {
2917
3046
  return LockfileSchema.parse({});
2918
3047
  }
2919
- const content = fs9.readFileSync(lockfilePath, "utf-8");
3048
+ const content = fs10.readFileSync(lockfilePath, "utf-8");
2920
3049
  const result = LockfileSchema.parse(YAML3.parse(content));
2921
3050
  return result;
2922
3051
  }
2923
3052
  function _saveLockfile(lockfile) {
2924
3053
  const lockfilePath = _getLockfilePath();
2925
3054
  const content = YAML3.stringify(lockfile);
2926
- fs9.writeFileSync(lockfilePath, content);
3055
+ fs10.writeFileSync(lockfilePath, content);
2927
3056
  }
2928
3057
  function _getLockfilePath() {
2929
- return path10.join(process.cwd(), "i18n.lock");
3058
+ return path11.join(process.cwd(), "i18n.lock");
2930
3059
  }
2931
3060
  }
2932
3061
  var LockfileSchema = Z3.object({
@@ -2951,8 +3080,8 @@ import inquirer2 from "inquirer";
2951
3080
  import externalEditor from "external-editor";
2952
3081
 
2953
3082
  // src/cli/utils/cache.ts
2954
- import path11 from "path";
2955
- import fs10 from "fs";
3083
+ import path12 from "path";
3084
+ import fs11 from "fs";
2956
3085
  var cacheChunk = (targetLocale, sourceChunk, processedChunk) => {
2957
3086
  const rows = Object.entries(sourceChunk).map(([key, source]) => ({
2958
3087
  targetLocale,
@@ -2982,26 +3111,26 @@ function getNormalizedCache() {
2982
3111
  function deleteCache() {
2983
3112
  const cacheFilePath = _getCacheFilePath();
2984
3113
  try {
2985
- fs10.unlinkSync(cacheFilePath);
3114
+ fs11.unlinkSync(cacheFilePath);
2986
3115
  } catch (e) {
2987
3116
  }
2988
3117
  }
2989
3118
  function _loadCache() {
2990
3119
  const cacheFilePath = _getCacheFilePath();
2991
- if (!fs10.existsSync(cacheFilePath)) {
3120
+ if (!fs11.existsSync(cacheFilePath)) {
2992
3121
  return [];
2993
3122
  }
2994
- const content = fs10.readFileSync(cacheFilePath, "utf-8");
3123
+ const content = fs11.readFileSync(cacheFilePath, "utf-8");
2995
3124
  const result = _parseJSONLines(content);
2996
3125
  return result;
2997
3126
  }
2998
3127
  function _appendToCache(rows) {
2999
3128
  const cacheFilePath = _getCacheFilePath();
3000
3129
  const lines = _buildJSONLines(rows);
3001
- fs10.appendFileSync(cacheFilePath, lines);
3130
+ fs11.appendFileSync(cacheFilePath, lines);
3002
3131
  }
3003
3132
  function _getCacheFilePath() {
3004
- return path11.join(process.cwd(), "i18n.cache");
3133
+ return path12.join(process.cwd(), "i18n.cache");
3005
3134
  }
3006
3135
  function _buildJSONLines(rows) {
3007
3136
  return rows.map((row) => JSON.stringify(row)).join("\n") + "\n";
@@ -3623,7 +3752,7 @@ var mcp_default = new Command9().command("mcp").description("Use Lingo.dev model
3623
3752
  // package.json
3624
3753
  var package_default = {
3625
3754
  name: "lingo.dev",
3626
- version: "0.77.4",
3755
+ version: "0.77.6",
3627
3756
  description: "Lingo.dev CLI",
3628
3757
  private: false,
3629
3758
  publishConfig: {