lingo.dev 0.77.2 → 0.77.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/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,7 +688,7 @@ import Ora4 from "ora";
650
688
 
651
689
  // src/cli/utils/buckets.ts
652
690
  import _5 from "lodash";
653
- import path7 from "path";
691
+ import path8 from "path";
654
692
  import * as glob2 from "glob";
655
693
  import { resolveOverridenLocale } from "@lingo.dev/_spec";
656
694
  function getBuckets(i18nConfig) {
@@ -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,9 +745,9 @@ 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
752
  const localePlaceholderIndex = pathPatternChunks[localeSegmentIndex]?.indexOf("[locale]") ?? -1;
715
753
  if (localeSegmentIndex >= 0 && localePlaceholderIndex >= 0) {
@@ -718,7 +756,7 @@ function expandPlaceholderedGlob(_pathPattern, sourceLocale) {
718
756
  sourcePathChunks[localeSegmentIndex] = placeholderedSegment;
719
757
  }
720
758
  });
721
- const placeholderedPath = sourcePathChunks.join(path7.sep);
759
+ const placeholderedPath = sourcePathChunks.join(path8.sep);
722
760
  return placeholderedPath;
723
761
  });
724
762
  return placeholderedPaths;
@@ -760,8 +798,8 @@ var files_default = new Command4().command("files").description("Print out the l
760
798
  } else if (type.target) {
761
799
  result.push(...targetPaths);
762
800
  }
763
- result.forEach((path11) => {
764
- console.log(path11);
801
+ result.forEach((path12) => {
802
+ console.log(path12);
765
803
  });
766
804
  }
767
805
  }
@@ -983,8 +1021,8 @@ function normalizeObjectKeys(obj) {
983
1021
  }
984
1022
 
985
1023
  // src/cli/loaders/text-file.ts
986
- import fs6 from "fs/promises";
987
- import path8 from "path";
1024
+ import fs7 from "fs/promises";
1025
+ import path9 from "path";
988
1026
  function createTextFileLoader(pathPattern) {
989
1027
  return createLoader({
990
1028
  async pull(locale) {
@@ -994,13 +1032,13 @@ function createTextFileLoader(pathPattern) {
994
1032
  },
995
1033
  async push(locale, data, _21, originalLocale) {
996
1034
  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 });
1035
+ const finalPath = path9.resolve(draftPath);
1036
+ const dirPath = path9.dirname(finalPath);
1037
+ await fs7.mkdir(dirPath, { recursive: true });
1000
1038
  const trimmedPayload = data.trim();
1001
1039
  const trailingNewLine = await getTrailingNewLine(pathPattern, locale, originalLocale);
1002
1040
  let finalPayload = trimmedPayload + trailingNewLine;
1003
- await fs6.writeFile(finalPath, finalPayload, {
1041
+ await fs7.writeFile(finalPath, finalPayload, {
1004
1042
  encoding: "utf-8",
1005
1043
  flag: "w"
1006
1044
  });
@@ -1009,12 +1047,12 @@ function createTextFileLoader(pathPattern) {
1009
1047
  }
1010
1048
  async function readFileForLocale(pathPattern, locale) {
1011
1049
  const draftPath = pathPattern.replaceAll("[locale]", locale);
1012
- const finalPath = path8.resolve(draftPath);
1013
- const exists = await fs6.access(finalPath).then(() => true).catch(() => false);
1050
+ const finalPath = path9.resolve(draftPath);
1051
+ const exists = await fs7.access(finalPath).then(() => true).catch(() => false);
1014
1052
  if (!exists) {
1015
1053
  return "";
1016
1054
  }
1017
- return fs6.readFile(finalPath, "utf-8");
1055
+ return fs7.readFile(finalPath, "utf-8");
1018
1056
  }
1019
1057
  async function getTrailingNewLine(pathPattern, locale, originalLocale) {
1020
1058
  let templateData = await readFileForLocale(pathPattern, locale);
@@ -1301,9 +1339,9 @@ function createHtmlLoader() {
1301
1339
  const bDepth = b.split("/").length;
1302
1340
  return aDepth - bDepth;
1303
1341
  });
1304
- paths.forEach((path11) => {
1305
- const value = data[path11];
1306
- const [nodePath, attribute] = path11.split("#");
1342
+ paths.forEach((path12) => {
1343
+ const value = data[path12];
1344
+ const [nodePath, attribute] = path12.split("#");
1307
1345
  const [rootTag, ...indices] = nodePath.split("/");
1308
1346
  let parent = rootTag === "head" ? document.head : document.body;
1309
1347
  let current = parent;
@@ -1807,7 +1845,7 @@ function createSrtLoader() {
1807
1845
  }
1808
1846
 
1809
1847
  // src/cli/loaders/dato/index.ts
1810
- import fs7 from "fs";
1848
+ import fs8 from "fs";
1811
1849
  import JSON5 from "json5";
1812
1850
 
1813
1851
  // src/cli/loaders/dato/_base.ts
@@ -2310,18 +2348,18 @@ function createRawDatoValue(parsedDatoValue, originalRawDatoValue, isClean = fal
2310
2348
  }
2311
2349
  function serializeStructuredText(rawStructuredText) {
2312
2350
  return serializeStructuredTextNode(rawStructuredText);
2313
- function serializeStructuredTextNode(node, path11 = [], acc = {}) {
2351
+ function serializeStructuredTextNode(node, path12 = [], acc = {}) {
2314
2352
  if ("document" in node) {
2315
- return serializeStructuredTextNode(node.document, [...path11, "document"], acc);
2353
+ return serializeStructuredTextNode(node.document, [...path12, "document"], acc);
2316
2354
  }
2317
2355
  if (!_15.isNil(node.value)) {
2318
- acc[[...path11, "value"].join(".")] = node.value;
2356
+ acc[[...path12, "value"].join(".")] = node.value;
2319
2357
  } else if (_15.get(node, "type") === "block") {
2320
- acc[[...path11, "item"].join(".")] = serializeBlock(node.item);
2358
+ acc[[...path12, "item"].join(".")] = serializeBlock(node.item);
2321
2359
  }
2322
2360
  if (node.children) {
2323
2361
  for (let i = 0; i < node.children.length; i++) {
2324
- serializeStructuredTextNode(node.children[i], [...path11, i.toString()], acc);
2362
+ serializeStructuredTextNode(node.children[i], [...path12, i.toString()], acc);
2325
2363
  }
2326
2364
  }
2327
2365
  return acc;
@@ -2380,8 +2418,8 @@ function deserializeBlockList(parsedBlockList, originalRawBlockList, isClean = f
2380
2418
  }
2381
2419
  function deserializeStructuredText(parsedStructuredText, originalRawStructuredText) {
2382
2420
  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();
2421
+ for (const [path12, value] of _15.entries(parsedStructuredText)) {
2422
+ const realPath = _15.chain(path12.split(".")).flatMap((s) => !_15.isNaN(_15.toNumber(s)) ? ["children", s] : s).value();
2385
2423
  const deserializedValue = createRawDatoValue(value, _15.get(originalRawStructuredText, realPath), true);
2386
2424
  _15.set(result, realPath, deserializedValue);
2387
2425
  }
@@ -2406,12 +2444,12 @@ function _isVideo(rawDatoValue) {
2406
2444
  // src/cli/loaders/dato/index.ts
2407
2445
  function createDatoLoader(configFilePath) {
2408
2446
  try {
2409
- const configContent = fs7.readFileSync(configFilePath, "utf-8");
2447
+ const configContent = fs8.readFileSync(configFilePath, "utf-8");
2410
2448
  const datoConfig = datoConfigSchema.parse(JSON5.parse(configContent));
2411
2449
  return composeLoaders(
2412
2450
  createDatoApiLoader(
2413
2451
  datoConfig,
2414
- (updatedConfig) => fs7.writeFileSync(configFilePath, JSON5.stringify(updatedConfig, null, 2))
2452
+ (updatedConfig) => fs8.writeFileSync(configFilePath, JSON5.stringify(updatedConfig, null, 2))
2415
2453
  ),
2416
2454
  createDatoFilterLoader(),
2417
2455
  createDatoExtractLoader()
@@ -2833,8 +2871,8 @@ function createBucketLoader(bucketType, bucketPathPattern, { isCacheRestore = fa
2833
2871
  }
2834
2872
 
2835
2873
  // src/cli/utils/lockfile.ts
2836
- import fs8 from "fs";
2837
- import path9 from "path";
2874
+ import fs9 from "fs";
2875
+ import path10 from "path";
2838
2876
  import Z3 from "zod";
2839
2877
  import YAML3 from "yaml";
2840
2878
  import { MD5 } from "object-hash";
@@ -2843,7 +2881,7 @@ function createLockfileHelper() {
2843
2881
  return {
2844
2882
  isLockfileExists: () => {
2845
2883
  const lockfilePath = _getLockfilePath();
2846
- return fs8.existsSync(lockfilePath);
2884
+ return fs9.existsSync(lockfilePath);
2847
2885
  },
2848
2886
  registerSourceData: (pathPattern, sourceData) => {
2849
2887
  const lockfile = _loadLockfile();
@@ -2870,20 +2908,20 @@ function createLockfileHelper() {
2870
2908
  };
2871
2909
  function _loadLockfile() {
2872
2910
  const lockfilePath = _getLockfilePath();
2873
- if (!fs8.existsSync(lockfilePath)) {
2911
+ if (!fs9.existsSync(lockfilePath)) {
2874
2912
  return LockfileSchema.parse({});
2875
2913
  }
2876
- const content = fs8.readFileSync(lockfilePath, "utf-8");
2914
+ const content = fs9.readFileSync(lockfilePath, "utf-8");
2877
2915
  const result = LockfileSchema.parse(YAML3.parse(content));
2878
2916
  return result;
2879
2917
  }
2880
2918
  function _saveLockfile(lockfile) {
2881
2919
  const lockfilePath = _getLockfilePath();
2882
2920
  const content = YAML3.stringify(lockfile);
2883
- fs8.writeFileSync(lockfilePath, content);
2921
+ fs9.writeFileSync(lockfilePath, content);
2884
2922
  }
2885
2923
  function _getLockfilePath() {
2886
- return path9.join(process.cwd(), "i18n.lock");
2924
+ return path10.join(process.cwd(), "i18n.lock");
2887
2925
  }
2888
2926
  }
2889
2927
  var LockfileSchema = Z3.object({
@@ -2908,8 +2946,8 @@ import inquirer2 from "inquirer";
2908
2946
  import externalEditor from "external-editor";
2909
2947
 
2910
2948
  // src/cli/utils/cache.ts
2911
- import path10 from "path";
2912
- import fs9 from "fs";
2949
+ import path11 from "path";
2950
+ import fs10 from "fs";
2913
2951
  var cacheChunk = (targetLocale, sourceChunk, processedChunk) => {
2914
2952
  const rows = Object.entries(sourceChunk).map(([key, source]) => ({
2915
2953
  targetLocale,
@@ -2939,26 +2977,26 @@ function getNormalizedCache() {
2939
2977
  function deleteCache() {
2940
2978
  const cacheFilePath = _getCacheFilePath();
2941
2979
  try {
2942
- fs9.unlinkSync(cacheFilePath);
2980
+ fs10.unlinkSync(cacheFilePath);
2943
2981
  } catch (e) {
2944
2982
  }
2945
2983
  }
2946
2984
  function _loadCache() {
2947
2985
  const cacheFilePath = _getCacheFilePath();
2948
- if (!fs9.existsSync(cacheFilePath)) {
2986
+ if (!fs10.existsSync(cacheFilePath)) {
2949
2987
  return [];
2950
2988
  }
2951
- const content = fs9.readFileSync(cacheFilePath, "utf-8");
2989
+ const content = fs10.readFileSync(cacheFilePath, "utf-8");
2952
2990
  const result = _parseJSONLines(content);
2953
2991
  return result;
2954
2992
  }
2955
2993
  function _appendToCache(rows) {
2956
2994
  const cacheFilePath = _getCacheFilePath();
2957
2995
  const lines = _buildJSONLines(rows);
2958
- fs9.appendFileSync(cacheFilePath, lines);
2996
+ fs10.appendFileSync(cacheFilePath, lines);
2959
2997
  }
2960
2998
  function _getCacheFilePath() {
2961
- return path10.join(process.cwd(), "i18n.cache");
2999
+ return path11.join(process.cwd(), "i18n.cache");
2962
3000
  }
2963
3001
  function _buildJSONLines(rows) {
2964
3002
  return rows.map((row) => JSON.stringify(row)).join("\n") + "\n";
@@ -2976,6 +3014,7 @@ function _tryParseJSON(line) {
2976
3014
 
2977
3015
  // src/cli/cmd/i18n.ts
2978
3016
  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) {
3017
+ updateGitignore();
2979
3018
  const ora = Ora5();
2980
3019
  const flags = parseFlags(options);
2981
3020
  if (flags.debug) {
@@ -3579,7 +3618,7 @@ var mcp_default = new Command9().command("mcp").description("Use Lingo.dev model
3579
3618
  // package.json
3580
3619
  var package_default = {
3581
3620
  name: "lingo.dev",
3582
- version: "0.77.2",
3621
+ version: "0.77.3",
3583
3622
  description: "Lingo.dev CLI",
3584
3623
  private: false,
3585
3624
  publishConfig: {