lingo.dev 0.77.2 → 0.77.4

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,8 +264,8 @@ 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 fs4 from "fs";
268
- import path5 from "path";
267
+ import fs5 from "fs";
268
+ import path6 from "path";
269
269
  import { spawn } from "child_process";
270
270
  import _3 from "lodash";
271
271
  import { checkbox, confirm, input } from "@inquirer/prompts";
@@ -436,10 +436,47 @@ function getDefaultContent(ext, source) {
436
436
  }
437
437
  }
438
438
 
439
+ // src/cli/utils/update-gitignore.ts
440
+ import fs4 from "fs";
441
+ import path5 from "path";
442
+ function updateGitignore() {
443
+ const cacheFile = "i18n.cache";
444
+ const projectRoot = findCurrentProjectRoot();
445
+ if (!projectRoot) {
446
+ return;
447
+ }
448
+ const gitignorePath = path5.join(projectRoot, ".gitignore");
449
+ const gitignore = fs4.readFileSync(gitignorePath, "utf8").split("\n");
450
+ const cacheIsIgnored = gitignore.includes(cacheFile);
451
+ if (!cacheIsIgnored) {
452
+ let content = "";
453
+ if (fs4.existsSync(gitignorePath)) {
454
+ content = fs4.readFileSync(gitignorePath, "utf8");
455
+ if (content !== "" && !content.endsWith("\n")) {
456
+ content += "\n";
457
+ }
458
+ }
459
+ content += `${cacheFile}
460
+ `;
461
+ fs4.writeFileSync(gitignorePath, content);
462
+ }
463
+ }
464
+ function findCurrentProjectRoot() {
465
+ let currentDir = process.cwd();
466
+ while (currentDir !== path5.parse(currentDir).root) {
467
+ const gitDirPath = path5.join(currentDir, ".git");
468
+ if (fs4.existsSync(gitDirPath) && fs4.lstatSync(gitDirPath).isDirectory()) {
469
+ return currentDir;
470
+ }
471
+ currentDir = path5.dirname(currentDir);
472
+ }
473
+ return null;
474
+ }
475
+
439
476
  // src/cli/cmd/init.ts
440
- var openUrl = (path11) => {
477
+ var openUrl = (path12) => {
441
478
  const settings = getSettings(void 0);
442
- spawn("open", [`${settings.auth.webUrl}${path11}`]);
479
+ spawn("open", [`${settings.auth.webUrl}${path12}`]);
443
480
  };
444
481
  var throwHelpError = (option, value) => {
445
482
  if (value === "help") {
@@ -485,8 +522,8 @@ var init_default = new InteractiveCommand().command("init").description("Initial
485
522
  const values = value.includes(",") ? value.split(",") : value.split(" ");
486
523
  for (const p of values) {
487
524
  try {
488
- const dirPath = path5.dirname(p);
489
- const stats = fs4.statSync(dirPath);
525
+ const dirPath = path6.dirname(p);
526
+ const stats = fs5.statSync(dirPath);
490
527
  if (!stats.isDirectory()) {
491
528
  throw new Error(`${dirPath} is not a directory`);
492
529
  }
@@ -588,6 +625,7 @@ var init_default = new InteractiveCommand().command("init").description("Initial
588
625
  } else {
589
626
  Ora2().succeed(`Authenticated as ${auth.email}`);
590
627
  }
628
+ updateGitignore();
591
629
  if (!isInteractive) {
592
630
  Ora2().info("Please see https://docs.lingo.dev/");
593
631
  }
@@ -599,8 +637,8 @@ import { Command as Command5 } from "interactive-commander";
599
637
  // src/cli/cmd/show/config.ts
600
638
  import { Command as Command2 } from "interactive-commander";
601
639
  import _4 from "lodash";
602
- import fs5 from "fs";
603
- import path6 from "path";
640
+ import fs6 from "fs";
641
+ import path7 from "path";
604
642
  import { defaultConfig as defaultConfig2 } from "@lingo.dev/_spec";
605
643
  var config_default = new Command2().command("config").description("Print out the current configuration").helpOption("-h, --help", "Show help").action(async (options) => {
606
644
  const fileConfig = loadReplexicaFileConfig();
@@ -608,12 +646,12 @@ var config_default = new Command2().command("config").description("Print out the
608
646
  console.log(JSON.stringify(config, null, 2));
609
647
  });
610
648
  function loadReplexicaFileConfig() {
611
- const replexicaConfigPath = path6.resolve(process.cwd(), "i18n.json");
612
- const fileExists = fs5.existsSync(replexicaConfigPath);
649
+ const replexicaConfigPath = path7.resolve(process.cwd(), "i18n.json");
650
+ const fileExists = fs6.existsSync(replexicaConfigPath);
613
651
  if (!fileExists) {
614
652
  return void 0;
615
653
  }
616
- const fileContent = fs5.readFileSync(replexicaConfigPath, "utf-8");
654
+ const fileContent = fs6.readFileSync(replexicaConfigPath, "utf-8");
617
655
  const replexicaFileConfig = JSON.parse(fileContent);
618
656
  return replexicaFileConfig;
619
657
  }
@@ -650,8 +688,8 @@ import Ora4 from "ora";
650
688
 
651
689
  // src/cli/utils/buckets.ts
652
690
  import _5 from "lodash";
653
- import path7 from "path";
654
- import * as glob2 from "glob";
691
+ import path8 from "path";
692
+ import { glob as glob2 } from "glob";
655
693
  import { resolveOverridenLocale } from "@lingo.dev/_spec";
656
694
  function getBuckets(i18nConfig) {
657
695
  const result = Object.entries(i18nConfig.buckets).map(([bucketType, bucketEntry]) => {
@@ -685,9 +723,9 @@ function extractPathPatterns(sourceLocale, include, exclude) {
685
723
  return result;
686
724
  }
687
725
  function expandPlaceholderedGlob(_pathPattern, sourceLocale) {
688
- const absolutePathPattern = path7.resolve(_pathPattern);
689
- const pathPattern = path7.relative(process.cwd(), absolutePathPattern);
690
- if (path7.relative(process.cwd(), pathPattern).startsWith("..")) {
726
+ const absolutePathPattern = path8.resolve(_pathPattern);
727
+ const pathPattern = path8.relative(process.cwd(), absolutePathPattern);
728
+ if (path8.relative(process.cwd(), pathPattern).startsWith("..")) {
691
729
  throw new CLIError({
692
730
  message: `Invalid path pattern: ${pathPattern}. Path pattern must be within the current working directory.`,
693
731
  docUrl: "invalidPathPattern"
@@ -699,7 +737,7 @@ function expandPlaceholderedGlob(_pathPattern, sourceLocale) {
699
737
  docUrl: "invalidPathPattern"
700
738
  });
701
739
  }
702
- const pathPatternChunks = pathPattern.split(path7.sep);
740
+ const pathPatternChunks = pathPattern.split(path8.sep);
703
741
  const localeSegmentIndexes = pathPatternChunks.reduce((indexes, segment, index) => {
704
742
  if (segment.includes("[locale]")) {
705
743
  indexes.push(index);
@@ -707,18 +745,23 @@ function expandPlaceholderedGlob(_pathPattern, sourceLocale) {
707
745
  return indexes;
708
746
  }, []);
709
747
  const sourcePathPattern = pathPattern.replaceAll(/\[locale\]/g, sourceLocale);
710
- 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));
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));
711
749
  const placeholderedPaths = sourcePaths.map((sourcePath) => {
712
- const sourcePathChunks = sourcePath.split(path7.sep);
750
+ const sourcePathChunks = sourcePath.split(path8.sep);
713
751
  localeSegmentIndexes.forEach((localeSegmentIndex) => {
714
- const localePlaceholderIndex = pathPatternChunks[localeSegmentIndex]?.indexOf("[locale]") ?? -1;
715
- if (localeSegmentIndex >= 0 && localePlaceholderIndex >= 0) {
716
- const placeholderedPathChunk = sourcePathChunks[localeSegmentIndex];
717
- const placeholderedSegment = placeholderedPathChunk.substring(0, localePlaceholderIndex) + "[locale]" + placeholderedPathChunk.substring(localePlaceholderIndex + sourceLocale.length);
752
+ const pathPatternChunk = pathPatternChunks[localeSegmentIndex];
753
+ const sourcePathChunk = sourcePathChunks[localeSegmentIndex];
754
+ const regexp = new RegExp(
755
+ "(" + pathPatternChunk.replaceAll(".", "\\.").replaceAll("*", ".*").replace("[locale]", `)${sourceLocale}(`) + ")"
756
+ );
757
+ const match = sourcePathChunk.match(regexp);
758
+ if (match) {
759
+ const [, prefix, suffix] = match;
760
+ const placeholderedSegment = prefix + "[locale]" + suffix;
718
761
  sourcePathChunks[localeSegmentIndex] = placeholderedSegment;
719
762
  }
720
763
  });
721
- const placeholderedPath = sourcePathChunks.join(path7.sep);
764
+ const placeholderedPath = sourcePathChunks.join(path8.sep);
722
765
  return placeholderedPath;
723
766
  });
724
767
  return placeholderedPaths;
@@ -760,8 +803,8 @@ var files_default = new Command4().command("files").description("Print out the l
760
803
  } else if (type.target) {
761
804
  result.push(...targetPaths);
762
805
  }
763
- result.forEach((path11) => {
764
- console.log(path11);
806
+ result.forEach((path12) => {
807
+ console.log(path12);
765
808
  });
766
809
  }
767
810
  }
@@ -983,8 +1026,8 @@ function normalizeObjectKeys(obj) {
983
1026
  }
984
1027
 
985
1028
  // src/cli/loaders/text-file.ts
986
- import fs6 from "fs/promises";
987
- import path8 from "path";
1029
+ import fs7 from "fs/promises";
1030
+ import path9 from "path";
988
1031
  function createTextFileLoader(pathPattern) {
989
1032
  return createLoader({
990
1033
  async pull(locale) {
@@ -994,13 +1037,13 @@ function createTextFileLoader(pathPattern) {
994
1037
  },
995
1038
  async push(locale, data, _21, originalLocale) {
996
1039
  const draftPath = pathPattern.replaceAll("[locale]", locale);
997
- const finalPath = path8.resolve(draftPath);
998
- const dirPath = path8.dirname(finalPath);
999
- await fs6.mkdir(dirPath, { recursive: true });
1040
+ const finalPath = path9.resolve(draftPath);
1041
+ const dirPath = path9.dirname(finalPath);
1042
+ await fs7.mkdir(dirPath, { recursive: true });
1000
1043
  const trimmedPayload = data.trim();
1001
1044
  const trailingNewLine = await getTrailingNewLine(pathPattern, locale, originalLocale);
1002
1045
  let finalPayload = trimmedPayload + trailingNewLine;
1003
- await fs6.writeFile(finalPath, finalPayload, {
1046
+ await fs7.writeFile(finalPath, finalPayload, {
1004
1047
  encoding: "utf-8",
1005
1048
  flag: "w"
1006
1049
  });
@@ -1009,12 +1052,12 @@ function createTextFileLoader(pathPattern) {
1009
1052
  }
1010
1053
  async function readFileForLocale(pathPattern, locale) {
1011
1054
  const draftPath = pathPattern.replaceAll("[locale]", locale);
1012
- const finalPath = path8.resolve(draftPath);
1013
- const exists = await fs6.access(finalPath).then(() => true).catch(() => false);
1055
+ const finalPath = path9.resolve(draftPath);
1056
+ const exists = await fs7.access(finalPath).then(() => true).catch(() => false);
1014
1057
  if (!exists) {
1015
1058
  return "";
1016
1059
  }
1017
- return fs6.readFile(finalPath, "utf-8");
1060
+ return fs7.readFile(finalPath, "utf-8");
1018
1061
  }
1019
1062
  async function getTrailingNewLine(pathPattern, locale, originalLocale) {
1020
1063
  let templateData = await readFileForLocale(pathPattern, locale);
@@ -1301,9 +1344,9 @@ function createHtmlLoader() {
1301
1344
  const bDepth = b.split("/").length;
1302
1345
  return aDepth - bDepth;
1303
1346
  });
1304
- paths.forEach((path11) => {
1305
- const value = data[path11];
1306
- const [nodePath, attribute] = path11.split("#");
1347
+ paths.forEach((path12) => {
1348
+ const value = data[path12];
1349
+ const [nodePath, attribute] = path12.split("#");
1307
1350
  const [rootTag, ...indices] = nodePath.split("/");
1308
1351
  let parent = rootTag === "head" ? document.head : document.body;
1309
1352
  let current = parent;
@@ -1807,7 +1850,7 @@ function createSrtLoader() {
1807
1850
  }
1808
1851
 
1809
1852
  // src/cli/loaders/dato/index.ts
1810
- import fs7 from "fs";
1853
+ import fs8 from "fs";
1811
1854
  import JSON5 from "json5";
1812
1855
 
1813
1856
  // src/cli/loaders/dato/_base.ts
@@ -2310,18 +2353,18 @@ function createRawDatoValue(parsedDatoValue, originalRawDatoValue, isClean = fal
2310
2353
  }
2311
2354
  function serializeStructuredText(rawStructuredText) {
2312
2355
  return serializeStructuredTextNode(rawStructuredText);
2313
- function serializeStructuredTextNode(node, path11 = [], acc = {}) {
2356
+ function serializeStructuredTextNode(node, path12 = [], acc = {}) {
2314
2357
  if ("document" in node) {
2315
- return serializeStructuredTextNode(node.document, [...path11, "document"], acc);
2358
+ return serializeStructuredTextNode(node.document, [...path12, "document"], acc);
2316
2359
  }
2317
2360
  if (!_15.isNil(node.value)) {
2318
- acc[[...path11, "value"].join(".")] = node.value;
2361
+ acc[[...path12, "value"].join(".")] = node.value;
2319
2362
  } else if (_15.get(node, "type") === "block") {
2320
- acc[[...path11, "item"].join(".")] = serializeBlock(node.item);
2363
+ acc[[...path12, "item"].join(".")] = serializeBlock(node.item);
2321
2364
  }
2322
2365
  if (node.children) {
2323
2366
  for (let i = 0; i < node.children.length; i++) {
2324
- serializeStructuredTextNode(node.children[i], [...path11, i.toString()], acc);
2367
+ serializeStructuredTextNode(node.children[i], [...path12, i.toString()], acc);
2325
2368
  }
2326
2369
  }
2327
2370
  return acc;
@@ -2380,8 +2423,8 @@ function deserializeBlockList(parsedBlockList, originalRawBlockList, isClean = f
2380
2423
  }
2381
2424
  function deserializeStructuredText(parsedStructuredText, originalRawStructuredText) {
2382
2425
  const result = _15.cloneDeep(originalRawStructuredText);
2383
- for (const [path11, value] of _15.entries(parsedStructuredText)) {
2384
- const realPath = _15.chain(path11.split(".")).flatMap((s) => !_15.isNaN(_15.toNumber(s)) ? ["children", s] : s).value();
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();
2385
2428
  const deserializedValue = createRawDatoValue(value, _15.get(originalRawStructuredText, realPath), true);
2386
2429
  _15.set(result, realPath, deserializedValue);
2387
2430
  }
@@ -2406,12 +2449,12 @@ function _isVideo(rawDatoValue) {
2406
2449
  // src/cli/loaders/dato/index.ts
2407
2450
  function createDatoLoader(configFilePath) {
2408
2451
  try {
2409
- const configContent = fs7.readFileSync(configFilePath, "utf-8");
2452
+ const configContent = fs8.readFileSync(configFilePath, "utf-8");
2410
2453
  const datoConfig = datoConfigSchema.parse(JSON5.parse(configContent));
2411
2454
  return composeLoaders(
2412
2455
  createDatoApiLoader(
2413
2456
  datoConfig,
2414
- (updatedConfig) => fs7.writeFileSync(configFilePath, JSON5.stringify(updatedConfig, null, 2))
2457
+ (updatedConfig) => fs8.writeFileSync(configFilePath, JSON5.stringify(updatedConfig, null, 2))
2415
2458
  ),
2416
2459
  createDatoFilterLoader(),
2417
2460
  createDatoExtractLoader()
@@ -2833,8 +2876,8 @@ function createBucketLoader(bucketType, bucketPathPattern, { isCacheRestore = fa
2833
2876
  }
2834
2877
 
2835
2878
  // src/cli/utils/lockfile.ts
2836
- import fs8 from "fs";
2837
- import path9 from "path";
2879
+ import fs9 from "fs";
2880
+ import path10 from "path";
2838
2881
  import Z3 from "zod";
2839
2882
  import YAML3 from "yaml";
2840
2883
  import { MD5 } from "object-hash";
@@ -2843,7 +2886,7 @@ function createLockfileHelper() {
2843
2886
  return {
2844
2887
  isLockfileExists: () => {
2845
2888
  const lockfilePath = _getLockfilePath();
2846
- return fs8.existsSync(lockfilePath);
2889
+ return fs9.existsSync(lockfilePath);
2847
2890
  },
2848
2891
  registerSourceData: (pathPattern, sourceData) => {
2849
2892
  const lockfile = _loadLockfile();
@@ -2870,20 +2913,20 @@ function createLockfileHelper() {
2870
2913
  };
2871
2914
  function _loadLockfile() {
2872
2915
  const lockfilePath = _getLockfilePath();
2873
- if (!fs8.existsSync(lockfilePath)) {
2916
+ if (!fs9.existsSync(lockfilePath)) {
2874
2917
  return LockfileSchema.parse({});
2875
2918
  }
2876
- const content = fs8.readFileSync(lockfilePath, "utf-8");
2919
+ const content = fs9.readFileSync(lockfilePath, "utf-8");
2877
2920
  const result = LockfileSchema.parse(YAML3.parse(content));
2878
2921
  return result;
2879
2922
  }
2880
2923
  function _saveLockfile(lockfile) {
2881
2924
  const lockfilePath = _getLockfilePath();
2882
2925
  const content = YAML3.stringify(lockfile);
2883
- fs8.writeFileSync(lockfilePath, content);
2926
+ fs9.writeFileSync(lockfilePath, content);
2884
2927
  }
2885
2928
  function _getLockfilePath() {
2886
- return path9.join(process.cwd(), "i18n.lock");
2929
+ return path10.join(process.cwd(), "i18n.lock");
2887
2930
  }
2888
2931
  }
2889
2932
  var LockfileSchema = Z3.object({
@@ -2908,8 +2951,8 @@ import inquirer2 from "inquirer";
2908
2951
  import externalEditor from "external-editor";
2909
2952
 
2910
2953
  // src/cli/utils/cache.ts
2911
- import path10 from "path";
2912
- import fs9 from "fs";
2954
+ import path11 from "path";
2955
+ import fs10 from "fs";
2913
2956
  var cacheChunk = (targetLocale, sourceChunk, processedChunk) => {
2914
2957
  const rows = Object.entries(sourceChunk).map(([key, source]) => ({
2915
2958
  targetLocale,
@@ -2939,26 +2982,26 @@ function getNormalizedCache() {
2939
2982
  function deleteCache() {
2940
2983
  const cacheFilePath = _getCacheFilePath();
2941
2984
  try {
2942
- fs9.unlinkSync(cacheFilePath);
2985
+ fs10.unlinkSync(cacheFilePath);
2943
2986
  } catch (e) {
2944
2987
  }
2945
2988
  }
2946
2989
  function _loadCache() {
2947
2990
  const cacheFilePath = _getCacheFilePath();
2948
- if (!fs9.existsSync(cacheFilePath)) {
2991
+ if (!fs10.existsSync(cacheFilePath)) {
2949
2992
  return [];
2950
2993
  }
2951
- const content = fs9.readFileSync(cacheFilePath, "utf-8");
2994
+ const content = fs10.readFileSync(cacheFilePath, "utf-8");
2952
2995
  const result = _parseJSONLines(content);
2953
2996
  return result;
2954
2997
  }
2955
2998
  function _appendToCache(rows) {
2956
2999
  const cacheFilePath = _getCacheFilePath();
2957
3000
  const lines = _buildJSONLines(rows);
2958
- fs9.appendFileSync(cacheFilePath, lines);
3001
+ fs10.appendFileSync(cacheFilePath, lines);
2959
3002
  }
2960
3003
  function _getCacheFilePath() {
2961
- return path10.join(process.cwd(), "i18n.cache");
3004
+ return path11.join(process.cwd(), "i18n.cache");
2962
3005
  }
2963
3006
  function _buildJSONLines(rows) {
2964
3007
  return rows.map((row) => JSON.stringify(row)).join("\n") + "\n";
@@ -2976,6 +3019,7 @@ function _tryParseJSON(line) {
2976
3019
 
2977
3020
  // src/cli/cmd/i18n.ts
2978
3021
  var i18n_default = new Command6().command("i18n").description("Run Localization engine").helpOption("-h, --help", "Show help").option("--locale <locale>", "Locale to process", (val, prev) => prev ? [...prev, val] : [val]).option("--bucket <bucket>", "Bucket to process", (val, prev) => prev ? [...prev, val] : [val]).option("--key <key>", "Key to process").option("--frozen", `Don't update the translations and fail if an update is needed`).option("--force", "Ignore lockfile and process all keys").option("--verbose", "Show verbose output").option("--interactive", "Interactive mode").option("--api-key <api-key>", "Explicitly set the API key to use").option("--debug", "Debug mode").option("--strict", "Stop on first error").action(async function(options) {
3022
+ updateGitignore();
2979
3023
  const ora = Ora5();
2980
3024
  const flags = parseFlags(options);
2981
3025
  if (flags.debug) {
@@ -3579,7 +3623,7 @@ var mcp_default = new Command9().command("mcp").description("Use Lingo.dev model
3579
3623
  // package.json
3580
3624
  var package_default = {
3581
3625
  name: "lingo.dev",
3582
- version: "0.77.2",
3626
+ version: "0.77.4",
3583
3627
  description: "Lingo.dev CLI",
3584
3628
  private: false,
3585
3629
  publishConfig: {