lingo.dev 0.78.2 → 0.78.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
@@ -1803,7 +1803,7 @@ async function loadPrettierConfig() {
1803
1803
  import _10 from "lodash";
1804
1804
  import _isUrl from "is-url";
1805
1805
  import { isValid, parseISO } from "date-fns";
1806
- function createUnlocalizableLoader(isCacheRestore = false) {
1806
+ function createUnlocalizableLoader(isCacheRestore = false, returnUnlocalizedKeys = false) {
1807
1807
  const rules = {
1808
1808
  isEmpty: (v) => _10.isEmpty(v),
1809
1809
  isNumber: (v) => typeof v === "number" || /^[0-9]+$/.test(v),
@@ -1823,6 +1823,9 @@ function createUnlocalizableLoader(isCacheRestore = false) {
1823
1823
  return false;
1824
1824
  }).map(([key, _21]) => key);
1825
1825
  const result = _10.omitBy(input2, (_21, key) => passthroughKeys.includes(key));
1826
+ if (returnUnlocalizedKeys) {
1827
+ result.unlocalizable = _10.omitBy(input2, (_21, key) => !passthroughKeys.includes(key));
1828
+ }
1826
1829
  return result;
1827
1830
  },
1828
1831
  async push(locale, data, originalInput) {
@@ -2874,20 +2877,27 @@ import { jsonrepair as jsonrepair2 } from "jsonrepair";
2874
2877
  function createVueJsonLoader() {
2875
2878
  return createLoader({
2876
2879
  pull: async (locale, input2, ctx) => {
2877
- const { i18n } = parseVueFile(input2);
2878
- return i18n[locale] ?? {};
2880
+ const parsed = parseVueFile(input2);
2881
+ return parsed?.i18n?.[locale] ?? {};
2879
2882
  },
2880
2883
  push: async (locale, data, originalInput) => {
2881
- const { before, i18n, after } = parseVueFile(originalInput ?? "");
2882
- i18n[locale] = data;
2883
- return `${before}<i18n>
2884
- ${JSON.stringify(i18n, null, 2)}
2885
- </i18n>${after}`;
2884
+ const parsed = parseVueFile(originalInput ?? "");
2885
+ if (!parsed) {
2886
+ return originalInput ?? "";
2887
+ }
2888
+ parsed.i18n[locale] = data;
2889
+ return `${parsed.before}<i18n>
2890
+ ${JSON.stringify(parsed.i18n, null, 2)}
2891
+ </i18n>${parsed.after}`;
2886
2892
  }
2887
2893
  });
2888
2894
  }
2889
2895
  function parseVueFile(input2) {
2890
- const [, before, jsonString = "{}", after] = input2.match(/^([\s\S]*)<i18n>([\s\S]*)<\/i18n>([\s\S]*)$/) || [];
2896
+ const match = input2.match(/^([\s\S]*)<i18n>([\s\S]*)<\/i18n>([\s\S]*)$/);
2897
+ if (!match) {
2898
+ return null;
2899
+ }
2900
+ const [, before, jsonString = "{}", after] = match;
2891
2901
  let i18n;
2892
2902
  try {
2893
2903
  i18n = JSON.parse(jsonString);
@@ -2908,7 +2918,7 @@ function createBucketLoader(bucketType, bucketPathPattern, options) {
2908
2918
  createAndroidLoader(),
2909
2919
  createFlatLoader(),
2910
2920
  createSyncLoader(),
2911
- createUnlocalizableLoader(options.isCacheRestore)
2921
+ createUnlocalizableLoader(options.isCacheRestore, options.returnUnlocalizedKeys)
2912
2922
  );
2913
2923
  case "csv":
2914
2924
  return composeLoaders(
@@ -2916,7 +2926,7 @@ function createBucketLoader(bucketType, bucketPathPattern, options) {
2916
2926
  createCsvLoader(),
2917
2927
  createFlatLoader(),
2918
2928
  createSyncLoader(),
2919
- createUnlocalizableLoader(options.isCacheRestore)
2929
+ createUnlocalizableLoader(options.isCacheRestore, options.returnUnlocalizedKeys)
2920
2930
  );
2921
2931
  case "html":
2922
2932
  return composeLoaders(
@@ -2924,7 +2934,7 @@ function createBucketLoader(bucketType, bucketPathPattern, options) {
2924
2934
  createPrettierLoader({ parser: "html", alwaysFormat: true }),
2925
2935
  createHtmlLoader(),
2926
2936
  createSyncLoader(),
2927
- createUnlocalizableLoader(options.isCacheRestore)
2937
+ createUnlocalizableLoader(options.isCacheRestore, options.returnUnlocalizedKeys)
2928
2938
  );
2929
2939
  case "json":
2930
2940
  return composeLoaders(
@@ -2933,7 +2943,7 @@ function createBucketLoader(bucketType, bucketPathPattern, options) {
2933
2943
  createJsonLoader(),
2934
2944
  createFlatLoader(),
2935
2945
  createSyncLoader(),
2936
- createUnlocalizableLoader(options.isCacheRestore)
2946
+ createUnlocalizableLoader(options.isCacheRestore, options.returnUnlocalizedKeys)
2937
2947
  );
2938
2948
  case "markdown":
2939
2949
  return composeLoaders(
@@ -2941,7 +2951,7 @@ function createBucketLoader(bucketType, bucketPathPattern, options) {
2941
2951
  createPrettierLoader({ parser: "markdown" }),
2942
2952
  createMarkdownLoader(),
2943
2953
  createSyncLoader(),
2944
- createUnlocalizableLoader(options.isCacheRestore)
2954
+ createUnlocalizableLoader(options.isCacheRestore, options.returnUnlocalizedKeys)
2945
2955
  );
2946
2956
  case "po":
2947
2957
  return composeLoaders(
@@ -2949,7 +2959,7 @@ function createBucketLoader(bucketType, bucketPathPattern, options) {
2949
2959
  createPoLoader(),
2950
2960
  createFlatLoader(),
2951
2961
  createSyncLoader(),
2952
- createUnlocalizableLoader(options.isCacheRestore),
2962
+ createUnlocalizableLoader(options.isCacheRestore, options.returnUnlocalizedKeys),
2953
2963
  createVariableLoader({ type: "python" })
2954
2964
  );
2955
2965
  case "properties":
@@ -2957,14 +2967,14 @@ function createBucketLoader(bucketType, bucketPathPattern, options) {
2957
2967
  createTextFileLoader(bucketPathPattern),
2958
2968
  createPropertiesLoader(),
2959
2969
  createSyncLoader(),
2960
- createUnlocalizableLoader(options.isCacheRestore)
2970
+ createUnlocalizableLoader(options.isCacheRestore, options.returnUnlocalizedKeys)
2961
2971
  );
2962
2972
  case "xcode-strings":
2963
2973
  return composeLoaders(
2964
2974
  createTextFileLoader(bucketPathPattern),
2965
2975
  createXcodeStringsLoader(),
2966
2976
  createSyncLoader(),
2967
- createUnlocalizableLoader(options.isCacheRestore)
2977
+ createUnlocalizableLoader(options.isCacheRestore, options.returnUnlocalizedKeys)
2968
2978
  );
2969
2979
  case "xcode-stringsdict":
2970
2980
  return composeLoaders(
@@ -2972,7 +2982,7 @@ function createBucketLoader(bucketType, bucketPathPattern, options) {
2972
2982
  createXcodeStringsdictLoader(),
2973
2983
  createFlatLoader(),
2974
2984
  createSyncLoader(),
2975
- createUnlocalizableLoader(options.isCacheRestore)
2985
+ createUnlocalizableLoader(options.isCacheRestore, options.returnUnlocalizedKeys)
2976
2986
  );
2977
2987
  case "xcode-xcstrings":
2978
2988
  return composeLoaders(
@@ -2982,7 +2992,7 @@ function createBucketLoader(bucketType, bucketPathPattern, options) {
2982
2992
  createXcodeXcstringsLoader(options.defaultLocale),
2983
2993
  createFlatLoader(),
2984
2994
  createSyncLoader(),
2985
- createUnlocalizableLoader(options.isCacheRestore),
2995
+ createUnlocalizableLoader(options.isCacheRestore, options.returnUnlocalizedKeys),
2986
2996
  createVariableLoader({ type: "ieee" })
2987
2997
  );
2988
2998
  case "yaml":
@@ -2992,7 +3002,7 @@ function createBucketLoader(bucketType, bucketPathPattern, options) {
2992
3002
  createYamlLoader(),
2993
3003
  createFlatLoader(),
2994
3004
  createSyncLoader(),
2995
- createUnlocalizableLoader(options.isCacheRestore)
3005
+ createUnlocalizableLoader(options.isCacheRestore, options.returnUnlocalizedKeys)
2996
3006
  );
2997
3007
  case "yaml-root-key":
2998
3008
  return composeLoaders(
@@ -3002,7 +3012,7 @@ function createBucketLoader(bucketType, bucketPathPattern, options) {
3002
3012
  createRootKeyLoader(true),
3003
3013
  createFlatLoader(),
3004
3014
  createSyncLoader(),
3005
- createUnlocalizableLoader(options.isCacheRestore)
3015
+ createUnlocalizableLoader(options.isCacheRestore, options.returnUnlocalizedKeys)
3006
3016
  );
3007
3017
  case "flutter":
3008
3018
  return composeLoaders(
@@ -3012,7 +3022,7 @@ function createBucketLoader(bucketType, bucketPathPattern, options) {
3012
3022
  createFlutterLoader(),
3013
3023
  createFlatLoader(),
3014
3024
  createSyncLoader(),
3015
- createUnlocalizableLoader(options.isCacheRestore)
3025
+ createUnlocalizableLoader(options.isCacheRestore, options.returnUnlocalizedKeys)
3016
3026
  );
3017
3027
  case "xliff":
3018
3028
  return composeLoaders(
@@ -3020,7 +3030,7 @@ function createBucketLoader(bucketType, bucketPathPattern, options) {
3020
3030
  createXliffLoader(),
3021
3031
  createFlatLoader(),
3022
3032
  createSyncLoader(),
3023
- createUnlocalizableLoader(options.isCacheRestore)
3033
+ createUnlocalizableLoader(options.isCacheRestore, options.returnUnlocalizedKeys)
3024
3034
  );
3025
3035
  case "xml":
3026
3036
  return composeLoaders(
@@ -3028,28 +3038,28 @@ function createBucketLoader(bucketType, bucketPathPattern, options) {
3028
3038
  createXmlLoader(),
3029
3039
  createFlatLoader(),
3030
3040
  createSyncLoader(),
3031
- createUnlocalizableLoader(options.isCacheRestore)
3041
+ createUnlocalizableLoader(options.isCacheRestore, options.returnUnlocalizedKeys)
3032
3042
  );
3033
3043
  case "srt":
3034
3044
  return composeLoaders(
3035
3045
  createTextFileLoader(bucketPathPattern),
3036
3046
  createSrtLoader(),
3037
3047
  createSyncLoader(),
3038
- createUnlocalizableLoader(options.isCacheRestore)
3048
+ createUnlocalizableLoader(options.isCacheRestore, options.returnUnlocalizedKeys)
3039
3049
  );
3040
3050
  case "dato":
3041
3051
  return composeLoaders(
3042
3052
  createDatoLoader(bucketPathPattern),
3043
3053
  createSyncLoader(),
3044
3054
  createFlatLoader(),
3045
- createUnlocalizableLoader(options.isCacheRestore)
3055
+ createUnlocalizableLoader(options.isCacheRestore, options.returnUnlocalizedKeys)
3046
3056
  );
3047
3057
  case "vtt":
3048
3058
  return composeLoaders(
3049
3059
  createTextFileLoader(bucketPathPattern),
3050
3060
  createVttLoader(),
3051
3061
  createSyncLoader(),
3052
- createUnlocalizableLoader(options.isCacheRestore)
3062
+ createUnlocalizableLoader(options.isCacheRestore, options.returnUnlocalizedKeys)
3053
3063
  );
3054
3064
  case "php":
3055
3065
  return composeLoaders(
@@ -3057,7 +3067,7 @@ function createBucketLoader(bucketType, bucketPathPattern, options) {
3057
3067
  createPhpLoader(),
3058
3068
  createSyncLoader(),
3059
3069
  createFlatLoader(),
3060
- createUnlocalizableLoader(options.isCacheRestore)
3070
+ createUnlocalizableLoader(options.isCacheRestore, options.returnUnlocalizedKeys)
3061
3071
  );
3062
3072
  case "vue-json":
3063
3073
  return composeLoaders(
@@ -3065,7 +3075,7 @@ function createBucketLoader(bucketType, bucketPathPattern, options) {
3065
3075
  createVueJsonLoader(),
3066
3076
  createSyncLoader(),
3067
3077
  createFlatLoader(),
3068
- createUnlocalizableLoader()
3078
+ createUnlocalizableLoader(options.isCacheRestore, options.returnUnlocalizedKeys)
3069
3079
  );
3070
3080
  }
3071
3081
  }
@@ -3310,27 +3320,55 @@ var i18n_default = new Command6().command("i18n").description("Run Localization
3310
3320
  }
3311
3321
  if (flags.frozen) {
3312
3322
  ora.start("Checking for lockfile updates...");
3313
- let requiresUpdate = false;
3314
- for (const bucket of buckets) {
3323
+ let requiresUpdate = null;
3324
+ bucketLoop: for (const bucket of buckets) {
3315
3325
  for (const bucketConfig of bucket.config) {
3316
3326
  const sourceLocale = resolveOverridenLocale3(i18nConfig.locale.source, bucketConfig.delimiter);
3317
3327
  const bucketLoader = createBucketLoader(bucket.type, bucketConfig.pathPattern, {
3318
3328
  isCacheRestore: false,
3319
- defaultLocale: sourceLocale
3329
+ defaultLocale: sourceLocale,
3330
+ returnUnlocalizedKeys: true
3320
3331
  });
3321
3332
  bucketLoader.setDefaultLocale(sourceLocale);
3322
3333
  await bucketLoader.init();
3323
- const sourceData = await bucketLoader.pull(i18nConfig.locale.source);
3334
+ const { unlocalizable: sourceUnlocalizable, ...sourceData } = await bucketLoader.pull(
3335
+ i18nConfig.locale.source
3336
+ );
3324
3337
  const updatedSourceData = lockfileHelper.extractUpdatedData(bucketConfig.pathPattern, sourceData);
3325
3338
  if (Object.keys(updatedSourceData).length > 0) {
3326
- requiresUpdate = true;
3327
- break;
3339
+ requiresUpdate = "updated";
3340
+ break bucketLoop;
3341
+ }
3342
+ for (const _targetLocale of targetLocales) {
3343
+ const targetLocale = resolveOverridenLocale3(_targetLocale, bucketConfig.delimiter);
3344
+ const { unlocalizable: targetUnlocalizable, ...targetData } = await bucketLoader.pull(targetLocale);
3345
+ const missingKeys = _19.difference(Object.keys(sourceData), Object.keys(targetData));
3346
+ const extraKeys = _19.difference(Object.keys(targetData), Object.keys(sourceData));
3347
+ const unlocalizableDataDiff = !_19.isEqual(sourceUnlocalizable, targetUnlocalizable);
3348
+ if (missingKeys.length > 0) {
3349
+ requiresUpdate = "missing";
3350
+ break bucketLoop;
3351
+ }
3352
+ if (extraKeys.length > 0) {
3353
+ requiresUpdate = "extra";
3354
+ break bucketLoop;
3355
+ }
3356
+ if (unlocalizableDataDiff) {
3357
+ requiresUpdate = "unlocalizable";
3358
+ break bucketLoop;
3359
+ }
3328
3360
  }
3329
3361
  }
3330
- if (requiresUpdate) break;
3331
3362
  }
3332
3363
  if (requiresUpdate) {
3333
- ora.fail("Localization data has changed; please update i18n.lock or run without --frozen.");
3364
+ const message = {
3365
+ updated: "Source file has been updated.",
3366
+ missing: "Target file is missing translations.",
3367
+ extra: "Target file has extra translations not present in the source file.",
3368
+ unlocalizable: "Unlocalizable data (such as booleans, dates, URLs, etc.) do not match."
3369
+ }[requiresUpdate];
3370
+ ora.fail(`Localization data has changed; please update i18n.lock or run without --frozen.`);
3371
+ ora.fail(` Details: ${message}`);
3334
3372
  process.exit(1);
3335
3373
  } else {
3336
3374
  ora.succeed("No lockfile updates required.");
@@ -3414,8 +3452,8 @@ var i18n_default = new Command6().command("i18n").description("Run Localization
3414
3452
  bucketOra.start(`Applying changes to ${bucketConfig} (${targetLocale})`);
3415
3453
  }
3416
3454
  const finalDiffSize = _19.chain(finalTargetData).omitBy((value, key) => value === targetData[key]).size().value();
3455
+ await bucketLoader.push(targetLocale, finalTargetData);
3417
3456
  if (finalDiffSize > 0 || flags.force) {
3418
- await bucketLoader.push(targetLocale, finalTargetData);
3419
3457
  bucketOra.succeed(`[${sourceLocale} -> ${targetLocale}] Localization completed`);
3420
3458
  } else {
3421
3459
  bucketOra.succeed(`[${sourceLocale} -> ${targetLocale}] Localization completed (no changes).`);
@@ -3830,7 +3868,7 @@ var mcp_default = new Command9().command("mcp").description("Use Lingo.dev model
3830
3868
  // package.json
3831
3869
  var package_default = {
3832
3870
  name: "lingo.dev",
3833
- version: "0.78.2",
3871
+ version: "0.78.4",
3834
3872
  description: "Lingo.dev CLI",
3835
3873
  private: false,
3836
3874
  publishConfig: {