lingo.dev 0.114.0 → 0.114.2

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
@@ -2363,7 +2363,7 @@ async function parseAndroidDocument(input2) {
2363
2363
  function buildPullResult(document) {
2364
2364
  const result = {};
2365
2365
  for (const resource of document.resourceNodes) {
2366
- if (!resource.translatable) {
2366
+ if (!isTranslatable(resource)) {
2367
2367
  continue;
2368
2368
  }
2369
2369
  switch (resource.type) {
@@ -2406,6 +2406,9 @@ function buildPullResult(document) {
2406
2406
  }
2407
2407
  return result;
2408
2408
  }
2409
+ function isTranslatable(resource) {
2410
+ return resource.translatable;
2411
+ }
2409
2412
  function buildTranslatedDocument(payload, existingDocument, sourceDocument) {
2410
2413
  const templateDocument = sourceDocument;
2411
2414
  const finalDocument = cloneDocumentStructure(templateDocument);
@@ -2434,6 +2437,9 @@ function buildTranslatedDocument(payload, existingDocument, sourceDocument) {
2434
2437
  if (finalMap.has(resource.name)) {
2435
2438
  continue;
2436
2439
  }
2440
+ if (!isTranslatable(resource)) {
2441
+ continue;
2442
+ }
2437
2443
  const cloned = cloneResourceNode(resource);
2438
2444
  appendResourceNode(finalDocument, cloned);
2439
2445
  finalMap.set(cloned.name, cloned);
@@ -2550,7 +2556,7 @@ function appendResourceNode(document, resourceNode) {
2550
2556
  document.resourceNodes.push(resourceNode);
2551
2557
  }
2552
2558
  function setTextualNodeContent(node, value, useCdata) {
2553
- const escapedValue = useCdata ? value : escapeAndroidString(value);
2559
+ const escapedValue = useCdata ? escapeApostrophesOnly(value) : escapeAndroidString(value);
2554
2560
  node._ = escapedValue;
2555
2561
  node.$$ = node.$$ ?? [];
2556
2562
  let textNode = node.$$.find(
@@ -2561,7 +2567,7 @@ function setTextualNodeContent(node, value, useCdata) {
2561
2567
  node.$$.push(textNode);
2562
2568
  }
2563
2569
  textNode["#name"] = useCdata ? "__cdata" : "__text__";
2564
- textNode._ = useCdata ? value : escapedValue;
2570
+ textNode._ = escapedValue;
2565
2571
  }
2566
2572
  function buildResourceNameMap(document) {
2567
2573
  const map = /* @__PURE__ */ new Map();
@@ -2721,6 +2727,9 @@ function asInteger(value, name) {
2721
2727
  function escapeAndroidString(value) {
2722
2728
  return value.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/(?<!\\)'/g, "\\'");
2723
2729
  }
2730
+ function escapeApostrophesOnly(value) {
2731
+ return value.replace(/(?<!\\)'/g, "\\'");
2732
+ }
2724
2733
  function segmentsToString(segments) {
2725
2734
  return segments.map((segment) => segment.value).join("");
2726
2735
  }
@@ -2851,13 +2860,42 @@ function createResourceNodeFromValue(name, value) {
2851
2860
  }
2852
2861
  }
2853
2862
  function cloneDocumentStructure(document) {
2863
+ const translatableResources = document.resourceNodes.filter(isTranslatable);
2854
2864
  const resourcesClone = deepClone(document.resources);
2855
2865
  const lookup = buildResourceLookup(resourcesClone);
2856
2866
  const resourceNodes = [];
2857
- for (const resource of document.resourceNodes) {
2867
+ for (const resource of translatableResources) {
2858
2868
  const cloned = cloneResourceNodeFromLookup(resource, lookup);
2859
2869
  resourceNodes.push(cloned);
2860
2870
  }
2871
+ if (resourcesClone.$$ && Array.isArray(resourcesClone.$$)) {
2872
+ const includedKeys = new Set(
2873
+ resourceNodes.map((r) => resourceLookupKey(r.type, r.name))
2874
+ );
2875
+ let filtered = resourcesClone.$$.filter((child) => {
2876
+ const elementName = child?.["#name"];
2877
+ const name = child?.$?.name;
2878
+ if (!isResourceElementName(elementName) || !name) {
2879
+ return true;
2880
+ }
2881
+ return includedKeys.has(resourceLookupKey(elementName, name));
2882
+ });
2883
+ const cleaned = [];
2884
+ let lastWasWhitespace = false;
2885
+ for (const child of filtered) {
2886
+ const isWhitespace = child?.["#name"] === "__text__" && (!child._ || child._.trim() === "");
2887
+ if (isWhitespace) {
2888
+ if (!lastWasWhitespace) {
2889
+ cleaned.push(child);
2890
+ lastWasWhitespace = true;
2891
+ }
2892
+ } else {
2893
+ cleaned.push(child);
2894
+ lastWasWhitespace = false;
2895
+ }
2896
+ }
2897
+ resourcesClone.$$ = cleaned;
2898
+ }
2861
2899
  return {
2862
2900
  resources: resourcesClone,
2863
2901
  resourceNodes
@@ -11432,6 +11470,14 @@ async function execute(input2) {
11432
11470
  }
11433
11471
  const i18nLimiter = pLimit(effectiveConcurrency);
11434
11472
  const ioLimiter = pLimit(1);
11473
+ const perFileIoLimiters = /* @__PURE__ */ new Map();
11474
+ const getFileIoLimiter = (bucketPathPattern) => {
11475
+ const lockKey = bucketPathPattern;
11476
+ if (!perFileIoLimiters.has(lockKey)) {
11477
+ perFileIoLimiters.set(lockKey, pLimit(1));
11478
+ }
11479
+ return perFileIoLimiters.get(lockKey);
11480
+ };
11435
11481
  const workersCount = effectiveConcurrency;
11436
11482
  const workerTasks = [];
11437
11483
  for (let i = 0; i < workersCount; i++) {
@@ -11445,6 +11491,7 @@ async function execute(input2) {
11445
11491
  ioLimiter,
11446
11492
  i18nLimiter,
11447
11493
  initialChecksumsMap,
11494
+ getFileIoLimiter,
11448
11495
  onDone() {
11449
11496
  task.title = createExecutionProgressMessage(ctx);
11450
11497
  }
@@ -11528,12 +11575,17 @@ function createWorkerTask(args) {
11528
11575
  const initialChecksums = args.initialChecksumsMap.get(assignedTask.bucketPathPattern) || {};
11529
11576
  const taskResult = await args.i18nLimiter(async () => {
11530
11577
  try {
11531
- const sourceData = await bucketLoader.pull(
11532
- assignedTask.sourceLocale
11578
+ const fileIoLimiter = args.getFileIoLimiter(
11579
+ assignedTask.bucketPathPattern
11580
+ );
11581
+ const sourceData = await fileIoLimiter(
11582
+ async () => bucketLoader.pull(assignedTask.sourceLocale)
11583
+ );
11584
+ const hints = await fileIoLimiter(
11585
+ async () => bucketLoader.pullHints()
11533
11586
  );
11534
- const hints = await bucketLoader.pullHints();
11535
- const targetData = await bucketLoader.pull(
11536
- assignedTask.targetLocale
11587
+ const targetData = await fileIoLimiter(
11588
+ async () => bucketLoader.pull(assignedTask.targetLocale)
11537
11589
  );
11538
11590
  const delta = await deltaProcessor.calculateDelta({
11539
11591
  sourceData,
@@ -11548,7 +11600,7 @@ function createWorkerTask(args) {
11548
11600
  )
11549
11601
  ).fromPairs().value();
11550
11602
  if (!Object.keys(processableData).length) {
11551
- await args.ioLimiter(async () => {
11603
+ await fileIoLimiter(async () => {
11552
11604
  await bucketLoader.push(assignedTask.targetLocale, targetData);
11553
11605
  });
11554
11606
  return {
@@ -11569,7 +11621,7 @@ function createWorkerTask(args) {
11569
11621
  hints: relevantHints
11570
11622
  },
11571
11623
  async (progress, _sourceChunk, processedChunk) => {
11572
- await args.ioLimiter(async () => {
11624
+ await fileIoLimiter(async () => {
11573
11625
  await bucketLoader.pull(assignedTask.sourceLocale);
11574
11626
  const latestTargetData = await bucketLoader.pull(
11575
11627
  assignedTask.targetLocale
@@ -11604,7 +11656,7 @@ function createWorkerTask(args) {
11604
11656
  delta,
11605
11657
  finalTargetData
11606
11658
  );
11607
- await args.ioLimiter(async () => {
11659
+ await fileIoLimiter(async () => {
11608
11660
  await bucketLoader.pull(assignedTask.sourceLocale);
11609
11661
  await bucketLoader.push(
11610
11662
  assignedTask.targetLocale,
@@ -13458,7 +13510,7 @@ async function renderHero2() {
13458
13510
  // package.json
13459
13511
  var package_default = {
13460
13512
  name: "lingo.dev",
13461
- version: "0.114.0",
13513
+ version: "0.114.2",
13462
13514
  description: "Lingo.dev CLI",
13463
13515
  private: false,
13464
13516
  publishConfig: {