lingo.dev 0.116.2 → 0.116.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
@@ -1615,8 +1615,8 @@ function createLoader(lDefinition) {
1615
1615
  state.defaultLocale = locale;
1616
1616
  return this;
1617
1617
  },
1618
- async pullHints() {
1619
- return lDefinition.pullHints?.(state.originalInput);
1618
+ async pullHints(originalInput) {
1619
+ return lDefinition.pullHints?.(originalInput || state.originalInput);
1620
1620
  },
1621
1621
  async pull(locale, input2) {
1622
1622
  if (!state.defaultLocale) {
@@ -2036,7 +2036,7 @@ function createTextFileLoader(pathPattern) {
2036
2036
  const trimmedResult = result.trim();
2037
2037
  return trimmedResult;
2038
2038
  },
2039
- async push(locale, data, _36, originalLocale) {
2039
+ async push(locale, data, _37, originalLocale) {
2040
2040
  const draftPath = pathPattern.replaceAll("[locale]", locale);
2041
2041
  const finalPath = path10.resolve(draftPath);
2042
2042
  const dirPath = path10.dirname(finalPath);
@@ -3666,7 +3666,7 @@ function createPropertiesLoader() {
3666
3666
  return result;
3667
3667
  },
3668
3668
  async push(locale, payload) {
3669
- const result = Object.entries(payload).filter(([_36, value]) => value != null).map(([key, value]) => `${key}=${value}`).join("\n");
3669
+ const result = Object.entries(payload).filter(([_37, value]) => value != null).map(([key, value]) => `${key}=${value}`).join("\n");
3670
3670
  return result;
3671
3671
  }
3672
3672
  });
@@ -3988,7 +3988,7 @@ function createXcodeStringsLoader() {
3988
3988
  return result;
3989
3989
  },
3990
3990
  async push(locale, payload) {
3991
- const lines = Object.entries(payload).filter(([_36, value]) => value != null).map(([key, value]) => {
3991
+ const lines = Object.entries(payload).filter(([_37, value]) => value != null).map(([key, value]) => {
3992
3992
  const escapedValue = escapeString(value);
3993
3993
  return `"${key}" = "${escapedValue}";`;
3994
3994
  });
@@ -4186,218 +4186,46 @@ function _removeLocale(input2, locale) {
4186
4186
  return { ...input2, strings: newStrings };
4187
4187
  }
4188
4188
 
4189
- // src/cli/loaders/xcode-xcstrings-icu.ts
4190
- var ICU_TYPE_MARKER = Symbol.for("@lingo.dev/icu-plural-object");
4191
- var CLDR_PLURAL_CATEGORIES = /* @__PURE__ */ new Set([
4192
- "zero",
4193
- "one",
4194
- "two",
4195
- "few",
4196
- "many",
4197
- "other"
4198
- ]);
4199
- function isICUPluralObject(value) {
4200
- if (!value || typeof value !== "object" || Array.isArray(value)) {
4201
- return false;
4202
- }
4203
- if (ICU_TYPE_MARKER in value) {
4204
- return true;
4205
- }
4206
- if (!("icu" in value) || typeof value.icu !== "string") {
4207
- return false;
4208
- }
4209
- const icuPluralPattern = /^\{[\w]+,\s*plural,\s*.+\}$/;
4210
- if (!icuPluralPattern.test(value.icu)) {
4211
- return false;
4212
- }
4213
- if (value._meta !== void 0) {
4214
- if (typeof value._meta !== "object" || !value._meta.variables || typeof value._meta.variables !== "object") {
4215
- return false;
4216
- }
4217
- for (const [varName, varMeta] of Object.entries(value._meta.variables)) {
4218
- if (!varMeta || typeof varMeta !== "object" || typeof varMeta.format !== "string" || varMeta.role !== "plural" && varMeta.role !== "other") {
4219
- return false;
4220
- }
4221
- }
4222
- }
4223
- return true;
4224
- }
4225
- function isPluralFormsObject(value) {
4226
- if (!value || typeof value !== "object" || Array.isArray(value)) {
4227
- return false;
4228
- }
4229
- const keys = Object.keys(value);
4230
- if (keys.length === 0) {
4231
- return false;
4232
- }
4233
- const allKeysAreCldr = keys.every((key) => CLDR_PLURAL_CATEGORIES.has(key));
4234
- if (!allKeysAreCldr) {
4235
- return false;
4236
- }
4237
- const allValuesAreStrings = keys.every(
4238
- (key) => typeof value[key] === "string"
4239
- );
4240
- if (!allValuesAreStrings) {
4241
- return false;
4242
- }
4243
- if (!("other" in value)) {
4244
- return false;
4245
- }
4246
- return true;
4247
- }
4189
+ // src/cli/loaders/xcode-xcstrings-v2.ts
4190
+ import _10 from "lodash";
4248
4191
  function getRequiredPluralCategories(locale) {
4249
4192
  try {
4250
4193
  const pluralRules = new Intl.PluralRules(locale);
4251
4194
  const categories = pluralRules.resolvedOptions().pluralCategories;
4252
4195
  if (!categories || categories.length === 0) {
4253
- throw new Error(`No plural categories found for locale: ${locale}`);
4196
+ return ["other"];
4254
4197
  }
4255
4198
  return categories;
4256
4199
  } catch (error) {
4257
- console.warn(
4258
- `[xcode-xcstrings-icu] Failed to resolve plural categories for locale "${locale}". Using fallback ["one", "other"]. Error: ${error instanceof Error ? error.message : String(error)}`
4259
- );
4260
- return ["one", "other"];
4200
+ return ["other"];
4261
4201
  }
4262
4202
  }
4263
- var CLDR_CATEGORY_TO_NUMBER = {
4264
- zero: 0,
4265
- one: 1,
4266
- two: 2
4267
- };
4268
- var NUMBER_TO_CLDR_CATEGORY = {
4269
- 0: "zero",
4270
- 1: "one",
4271
- 2: "two"
4272
- };
4273
- function xcstringsToPluralWithMeta(pluralForms, sourceLocale = "en") {
4274
- if (!pluralForms || Object.keys(pluralForms).length === 0) {
4275
- throw new Error("pluralForms cannot be empty");
4276
- }
4277
- const requiredCategories = getRequiredPluralCategories(sourceLocale);
4278
- const variables = {};
4279
- const formatRegex = /(%(?:(\d+)\$)?(?:[+-])?(?:\d+)?(?:\.(\d+))?([lhqLzjt]*)([diuoxXfFeEgGaAcspn@]))/g;
4280
- let maxMatches = [];
4281
- let maxMatchText = "";
4282
- for (const [form, text] of Object.entries(pluralForms)) {
4283
- if (typeof text !== "string") {
4284
- console.warn(
4285
- `Warning: Plural form "${form}" has non-string value:`,
4286
- text
4287
- );
4288
- continue;
4289
- }
4290
- const matches = [...text.matchAll(formatRegex)];
4291
- if (matches.length > maxMatches.length) {
4292
- maxMatches = matches;
4293
- maxMatchText = text;
4294
- }
4295
- }
4296
- let lastNumericIndex = -1;
4297
- maxMatches.forEach((match2, idx) => {
4298
- const specifier = match2[5];
4299
- if (/[diuoxXfFeE]/.test(specifier)) {
4300
- lastNumericIndex = idx;
4203
+ function isValidPluralForm(form, locale) {
4204
+ if (form.startsWith("=")) return true;
4205
+ const requiredCategories = getRequiredPluralCategories(locale);
4206
+ return requiredCategories.includes(form);
4207
+ }
4208
+ function buildIcuPluralString(forms, sourceLocale) {
4209
+ const requiredCategories = new Set(getRequiredPluralCategories(sourceLocale));
4210
+ const parts = Object.entries(forms).map(([form, text]) => {
4211
+ let normalizedForm = form;
4212
+ if (!requiredCategories.has(form)) {
4213
+ if (form === "zero") normalizedForm = "=0";
4214
+ else if (form === "one") normalizedForm = "=1";
4215
+ else if (form === "two") normalizedForm = "=2";
4301
4216
  }
4217
+ return `${normalizedForm} {${text}}`;
4302
4218
  });
4303
- let nonPluralCounter = 0;
4304
- maxMatches.forEach((match2, idx) => {
4305
- const fullFormat = match2[1];
4306
- const position = match2[2];
4307
- const precision = match2[3];
4308
- const lengthMod = match2[4];
4309
- const specifier = match2[5];
4310
- const isPluralVar = idx === lastNumericIndex;
4311
- const varName = isPluralVar ? "count" : `var${nonPluralCounter++}`;
4312
- variables[varName] = {
4313
- format: fullFormat,
4314
- role: isPluralVar ? "plural" : "other"
4315
- };
4316
- });
4317
- const variableKeys = Object.keys(variables);
4318
- const icuForms = Object.entries(pluralForms).filter(([form, text]) => {
4319
- if (typeof text !== "string") {
4320
- return false;
4321
- }
4322
- return true;
4323
- }).map(([form, text]) => {
4324
- let processed = text;
4325
- let vIdx = 0;
4326
- processed = processed.replace(formatRegex, () => {
4327
- if (vIdx >= variableKeys.length) {
4328
- vIdx++;
4329
- return "#";
4330
- }
4331
- const varName = variableKeys[vIdx];
4332
- const varMeta = variables[varName];
4333
- vIdx++;
4334
- if (varMeta.role === "plural") {
4335
- return "#";
4336
- } else {
4337
- return `{${varName}}`;
4338
- }
4339
- });
4340
- const isRequired = requiredCategories.includes(form);
4341
- const formKey = !isRequired && form in CLDR_CATEGORY_TO_NUMBER ? `=${CLDR_CATEGORY_TO_NUMBER[form]}` : form;
4342
- return `${formKey} {${processed}}`;
4343
- }).join(" ");
4344
- const pluralVarName = Object.keys(variables).find((name) => variables[name].role === "plural") || "count";
4345
- const icu = `{${pluralVarName}, plural, ${icuForms}}`;
4346
- const result = {
4347
- icu,
4348
- _meta: Object.keys(variables).length > 0 ? { variables } : void 0,
4349
- [ICU_TYPE_MARKER]: true
4350
- // Add type marker for robust detection
4351
- };
4352
- return result;
4219
+ return `{count, plural, ${parts.join(" ")}}`;
4353
4220
  }
4354
- function pluralWithMetaToXcstrings(data) {
4355
- if (!data.icu) {
4356
- throw new Error("ICU string is required");
4357
- }
4358
- const ast = parseICU(data.icu);
4359
- if (!ast || ast.length === 0) {
4360
- throw new Error("Invalid ICU format");
4361
- }
4362
- const pluralNode = ast.find((node) => node.type === "plural");
4363
- if (!pluralNode) {
4364
- throw new Error("No plural found in ICU format");
4221
+ function parseIcuPluralString(icuString, locale) {
4222
+ const pluralMatch = icuString.match(/\{[\w]+,\s*plural,\s*(.+)\}$/);
4223
+ if (!pluralMatch) {
4224
+ throw new Error(`Invalid ICU plural format: ${icuString}`);
4365
4225
  }
4226
+ const formsText = pluralMatch[1];
4366
4227
  const forms = {};
4367
- for (const [form, option] of Object.entries(pluralNode.options)) {
4368
- let text = "";
4369
- const optionValue = option.value;
4370
- for (const element of optionValue) {
4371
- if (element.type === "literal") {
4372
- text += element.value;
4373
- } else if (element.type === "pound") {
4374
- const pluralVar = Object.entries(data._meta?.variables || {}).find(
4375
- ([_36, meta]) => meta.role === "plural"
4376
- );
4377
- text += pluralVar?.[1].format || "%lld";
4378
- } else if (element.type === "argument") {
4379
- const varName = element.value;
4380
- const varMeta = data._meta?.variables?.[varName];
4381
- text += varMeta?.format || "%@";
4382
- }
4383
- }
4384
- let xcstringsFormName = form;
4385
- if (form.startsWith("=")) {
4386
- const numValue = parseInt(form.substring(1), 10);
4387
- xcstringsFormName = NUMBER_TO_CLDR_CATEGORY[numValue] || form;
4388
- }
4389
- forms[xcstringsFormName] = text;
4390
- }
4391
- return forms;
4392
- }
4393
- function parseICU(icu) {
4394
- const match2 = icu.match(/\{(\w+),\s*plural,\s*(.+)\}$/);
4395
- if (!match2) {
4396
- throw new Error("Invalid ICU plural format");
4397
- }
4398
- const varName = match2[1];
4399
- const formsText = match2[2];
4400
- const options = {};
4228
+ const exactMatches = /* @__PURE__ */ new Set();
4401
4229
  let i = 0;
4402
4230
  while (i < formsText.length) {
4403
4231
  while (i < formsText.length && /\s/.test(formsText[i])) {
@@ -4419,6 +4247,16 @@ function parseICU(icu) {
4419
4247
  }
4420
4248
  }
4421
4249
  if (!formName) break;
4250
+ if (formName === "=0") {
4251
+ formName = "zero";
4252
+ exactMatches.add("zero");
4253
+ } else if (formName === "=1") {
4254
+ formName = "one";
4255
+ exactMatches.add("one");
4256
+ } else if (formName === "=2") {
4257
+ formName = "two";
4258
+ exactMatches.add("two");
4259
+ }
4422
4260
  while (i < formsText.length && /\s/.test(formsText[i])) {
4423
4261
  i++;
4424
4262
  }
@@ -4443,149 +4281,234 @@ function parseICU(icu) {
4443
4281
  i++;
4444
4282
  }
4445
4283
  if (braceCount !== 0) {
4446
- const preview = formsText.substring(
4447
- Math.max(0, i - 50),
4448
- Math.min(formsText.length, i + 50)
4449
- );
4450
4284
  throw new Error(
4451
- `Unclosed brace for form '${formName}' in ICU MessageFormat.
4452
- Expected ${braceCount} more closing brace(s).
4453
- Context: ...${preview}...
4454
- Full ICU: {${varName}, plural, ${formsText}}`
4285
+ `Unclosed brace for form '${formName}' in ICU: ${icuString}`
4455
4286
  );
4456
4287
  }
4457
- const elements = parseFormText(formText);
4458
- options[formName] = {
4459
- value: elements
4460
- };
4288
+ forms[formName] = formText;
4461
4289
  }
4462
- return [
4463
- {
4464
- type: "plural",
4465
- value: varName,
4466
- options
4467
- }
4468
- ];
4469
- }
4470
- function parseFormText(text) {
4471
- const elements = [];
4472
- let currentText = "";
4473
- let i = 0;
4474
- while (i < text.length) {
4475
- if (text[i] === "#") {
4476
- if (currentText) {
4477
- elements.push({ type: "literal", value: currentText });
4478
- currentText = "";
4479
- }
4480
- elements.push({ type: "pound" });
4481
- i++;
4482
- } else if (text[i] === "{") {
4483
- if (currentText) {
4484
- elements.push({ type: "literal", value: currentText });
4485
- currentText = "";
4486
- }
4487
- let braceCount = 1;
4488
- let j = i + 1;
4489
- while (j < text.length && braceCount > 0) {
4490
- if (text[j] === "{") {
4491
- braceCount++;
4492
- } else if (text[j] === "}") {
4493
- braceCount--;
4494
- }
4495
- j++;
4496
- }
4497
- if (braceCount !== 0) {
4498
- throw new Error("Unclosed variable reference");
4499
- }
4500
- const varName = text.slice(i + 1, j - 1);
4501
- elements.push({ type: "argument", value: varName });
4502
- i = j;
4503
- } else {
4504
- currentText += text[i];
4505
- i++;
4290
+ const filteredForms = {};
4291
+ for (const [form, text] of Object.entries(forms)) {
4292
+ if (exactMatches.has(form) || isValidPluralForm(form, locale)) {
4293
+ filteredForms[form] = text;
4506
4294
  }
4507
4295
  }
4508
- if (currentText) {
4509
- elements.push({ type: "literal", value: currentText });
4510
- }
4511
- return elements;
4296
+ return filteredForms;
4512
4297
  }
4513
-
4514
- // src/cli/loaders/xcode-xcstrings-v2-loader.ts
4515
- function createXcodeXcstringsV2Loader(defaultLocale = "en") {
4298
+ function isIcuPluralString(value) {
4299
+ return typeof value === "string" && /^\{[\w]+,\s*plural,\s*.+\}$/.test(value);
4300
+ }
4301
+ function createXcodeXcstringsV2Loader(defaultLocale) {
4516
4302
  return createLoader({
4517
- async pull(locale, input2) {
4518
- const result = {};
4519
- for (const [key, value] of Object.entries(input2)) {
4520
- if (isPluralFormsObject(value)) {
4521
- try {
4522
- result[key] = xcstringsToPluralWithMeta(value, locale);
4523
- } catch (error) {
4524
- console.error(
4525
- `
4526
- [xcode-xcstrings-icu] Failed to convert plural forms for key "${key}":`,
4527
- `
4528
- Error: ${error instanceof Error ? error.message : String(error)}`,
4529
- `
4530
- Locale: ${locale}
4531
- `
4532
- );
4533
- result[key] = value;
4303
+ async pull(locale, input2, initCtx) {
4304
+ const resultData = {};
4305
+ const isSourceLanguage = locale === defaultLocale;
4306
+ for (const [translationKey, _translationEntity] of Object.entries(
4307
+ input2.strings
4308
+ )) {
4309
+ const rootTranslationEntity = _translationEntity;
4310
+ if (rootTranslationEntity.shouldTranslate === false) {
4311
+ continue;
4312
+ }
4313
+ const langTranslationEntity = rootTranslationEntity?.localizations?.[locale];
4314
+ if (langTranslationEntity) {
4315
+ if (!resultData[translationKey]) {
4316
+ resultData[translationKey] = {};
4534
4317
  }
4535
- } else {
4536
- result[key] = value;
4318
+ if ("stringUnit" in langTranslationEntity) {
4319
+ resultData[translationKey].stringUnit = langTranslationEntity.stringUnit.value;
4320
+ if ("substitutions" in langTranslationEntity) {
4321
+ resultData[translationKey].substitutions = {};
4322
+ for (const [subName, subData] of Object.entries(
4323
+ langTranslationEntity.substitutions
4324
+ )) {
4325
+ const pluralForms = subData.variations?.plural;
4326
+ if (pluralForms) {
4327
+ const forms = {};
4328
+ for (const [form, formData] of Object.entries(pluralForms)) {
4329
+ forms[form] = formData.stringUnit.value;
4330
+ }
4331
+ const icuString = buildIcuPluralString(forms, locale);
4332
+ resultData[translationKey].substitutions[subName] = {
4333
+ variations: {
4334
+ plural: icuString
4335
+ }
4336
+ };
4337
+ }
4338
+ }
4339
+ }
4340
+ } else if ("stringSet" in langTranslationEntity) {
4341
+ const values = langTranslationEntity.stringSet.values;
4342
+ if (Array.isArray(values) && values.length > 0) {
4343
+ resultData[translationKey].stringSet = values;
4344
+ }
4345
+ } else if ("variations" in langTranslationEntity) {
4346
+ if ("plural" in langTranslationEntity.variations) {
4347
+ const pluralForms = langTranslationEntity.variations.plural;
4348
+ const forms = {};
4349
+ for (const [form, formData] of Object.entries(pluralForms)) {
4350
+ if (formData?.stringUnit?.value) {
4351
+ forms[form] = formData.stringUnit.value;
4352
+ }
4353
+ }
4354
+ const icuString = buildIcuPluralString(forms, locale);
4355
+ resultData[translationKey].variations = {
4356
+ plural: icuString
4357
+ };
4358
+ }
4359
+ }
4360
+ } else if (isSourceLanguage) {
4361
+ if (!resultData[translationKey]) {
4362
+ resultData[translationKey] = {};
4363
+ }
4364
+ resultData[translationKey].stringUnit = translationKey;
4537
4365
  }
4538
4366
  }
4539
- return result;
4367
+ return resultData;
4540
4368
  },
4541
- async push(locale, payload) {
4542
- const result = {};
4543
- for (const [key, value] of Object.entries(payload)) {
4544
- if (isICUPluralObject(value)) {
4545
- try {
4546
- const pluralForms = pluralWithMetaToXcstrings(value);
4547
- result[key] = pluralForms;
4548
- } catch (error) {
4549
- throw new Error(
4550
- `Failed to write plural translation for key "${key}" (locale: ${locale}).
4369
+ async push(locale, payload, originalInput) {
4370
+ const langDataToMerge = {};
4371
+ langDataToMerge.strings = {};
4372
+ const input2 = _10.cloneDeep(originalInput) || {
4373
+ sourceLanguage: locale,
4374
+ strings: {}
4375
+ };
4376
+ for (const [baseKey, keyData] of Object.entries(payload)) {
4377
+ if (!keyData || typeof keyData !== "object") {
4378
+ continue;
4379
+ }
4380
+ const hasDoNotTranslateFlag = originalInput && originalInput.strings && originalInput.strings[baseKey] && originalInput.strings[baseKey].shouldTranslate === false;
4381
+ const localizationData = {};
4382
+ if ("stringUnit" in keyData) {
4383
+ localizationData.stringUnit = {
4384
+ state: "translated",
4385
+ value: keyData.stringUnit
4386
+ };
4387
+ }
4388
+ if ("substitutions" in keyData && keyData.substitutions) {
4389
+ const subs = {};
4390
+ for (const [subName, subData] of Object.entries(
4391
+ keyData.substitutions
4392
+ )) {
4393
+ const pluralValue = subData?.variations?.plural;
4394
+ if (pluralValue && isIcuPluralString(pluralValue)) {
4395
+ try {
4396
+ const pluralForms = parseIcuPluralString(pluralValue, locale);
4397
+ const pluralOut = {};
4398
+ for (const [form, text] of Object.entries(pluralForms)) {
4399
+ pluralOut[form] = {
4400
+ stringUnit: {
4401
+ state: "translated",
4402
+ value: text
4403
+ }
4404
+ };
4405
+ }
4406
+ const sourceLocale = originalInput?.sourceLanguage || "en";
4407
+ const origFormatSpec = originalInput?.strings?.[baseKey]?.localizations?.[sourceLocale]?.substitutions?.[subName]?.formatSpecifier || subName;
4408
+ subs[subName] = {
4409
+ formatSpecifier: origFormatSpec,
4410
+ variations: {
4411
+ plural: pluralOut
4412
+ }
4413
+ };
4414
+ } catch (error) {
4415
+ throw new Error(
4416
+ `Failed to write substitution plural translation for key "${baseKey}/substitutions/${subName}" (locale: ${locale}).
4551
4417
  ${error instanceof Error ? error.message : String(error)}`
4552
- );
4418
+ );
4419
+ }
4420
+ }
4421
+ }
4422
+ if (Object.keys(subs).length > 0) {
4423
+ localizationData.substitutions = subs;
4424
+ }
4425
+ }
4426
+ if ("stringSet" in keyData && Array.isArray(keyData.stringSet)) {
4427
+ localizationData.stringSet = {
4428
+ state: "translated",
4429
+ values: keyData.stringSet
4430
+ };
4431
+ }
4432
+ if ("variations" in keyData && keyData.variations?.plural) {
4433
+ const pluralValue = keyData.variations.plural;
4434
+ if (isIcuPluralString(pluralValue)) {
4435
+ try {
4436
+ const pluralForms = parseIcuPluralString(pluralValue, locale);
4437
+ const pluralOut = {};
4438
+ for (const [form, text] of Object.entries(pluralForms)) {
4439
+ pluralOut[form] = {
4440
+ stringUnit: {
4441
+ state: "translated",
4442
+ value: text
4443
+ }
4444
+ };
4445
+ }
4446
+ localizationData.variations = {
4447
+ plural: pluralOut
4448
+ };
4449
+ } catch (error) {
4450
+ throw new Error(
4451
+ `Failed to write plural translation for key "${baseKey}" (locale: ${locale}).
4452
+ ${error instanceof Error ? error.message : String(error)}`
4453
+ );
4454
+ }
4455
+ }
4456
+ }
4457
+ if (Object.keys(localizationData).length > 0) {
4458
+ langDataToMerge.strings[baseKey] = {
4459
+ extractionState: originalInput?.strings?.[baseKey]?.extractionState,
4460
+ localizations: {
4461
+ [locale]: localizationData
4462
+ }
4463
+ };
4464
+ if (hasDoNotTranslateFlag) {
4465
+ langDataToMerge.strings[baseKey].shouldTranslate = false;
4553
4466
  }
4554
- } else {
4555
- result[key] = value;
4556
4467
  }
4557
4468
  }
4558
- return result;
4469
+ return _10.merge(input2, langDataToMerge);
4470
+ },
4471
+ async pullHints(input2) {
4472
+ const hints = {};
4473
+ for (const [translationKey, _translationEntity] of Object.entries(
4474
+ input2.strings || {}
4475
+ )) {
4476
+ const rootTranslationEntity = _translationEntity;
4477
+ if (rootTranslationEntity.comment && typeof rootTranslationEntity.comment === "string") {
4478
+ hints[translationKey] = { hint: rootTranslationEntity.comment };
4479
+ }
4480
+ }
4481
+ return hints;
4559
4482
  }
4560
4483
  });
4561
4484
  }
4562
4485
 
4563
4486
  // src/cli/loaders/unlocalizable.ts
4564
- import _10 from "lodash";
4487
+ import _11 from "lodash";
4565
4488
  import _isUrl from "is-url";
4566
4489
  import { isValid, parseISO } from "date-fns";
4567
4490
  function createUnlocalizableLoader(returnUnlocalizedKeys = false) {
4568
4491
  return createLoader({
4569
4492
  async pull(locale, input2) {
4570
4493
  const unlocalizableKeys = _getUnlocalizableKeys(input2);
4571
- const result = _10.omitBy(
4494
+ const result = _11.omitBy(
4572
4495
  input2,
4573
- (_36, key) => unlocalizableKeys.includes(key)
4496
+ (_37, key) => unlocalizableKeys.includes(key)
4574
4497
  );
4575
4498
  if (returnUnlocalizedKeys) {
4576
- result.unlocalizable = _10.omitBy(
4499
+ result.unlocalizable = _11.omitBy(
4577
4500
  input2,
4578
- (_36, key) => !unlocalizableKeys.includes(key)
4501
+ (_37, key) => !unlocalizableKeys.includes(key)
4579
4502
  );
4580
4503
  }
4581
4504
  return result;
4582
4505
  },
4583
4506
  async push(locale, data, originalInput) {
4584
4507
  const unlocalizableKeys = _getUnlocalizableKeys(originalInput);
4585
- const result = _10.merge(
4508
+ const result = _11.merge(
4586
4509
  {},
4587
4510
  data,
4588
- _10.omitBy(originalInput, (_36, key) => !unlocalizableKeys.includes(key))
4511
+ _11.omitBy(originalInput, (_37, key) => !unlocalizableKeys.includes(key))
4589
4512
  );
4590
4513
  return result;
4591
4514
  }
@@ -4599,12 +4522,12 @@ function _isIsoDate(v) {
4599
4522
  }
4600
4523
  function _getUnlocalizableKeys(input2) {
4601
4524
  const rules = {
4602
- isEmpty: (v) => _10.isEmpty(v),
4525
+ isEmpty: (v) => _11.isEmpty(v),
4603
4526
  isNumber: (v) => typeof v === "number" || /^[0-9]+$/.test(v),
4604
- isBoolean: (v) => _10.isBoolean(v),
4605
- isIsoDate: (v) => _10.isString(v) && _isIsoDate(v),
4606
- isSystemId: (v) => _10.isString(v) && _isSystemId(v),
4607
- isUrl: (v) => _10.isString(v) && _isUrl(v)
4527
+ isBoolean: (v) => _11.isBoolean(v),
4528
+ isIsoDate: (v) => _11.isString(v) && _isIsoDate(v),
4529
+ isSystemId: (v) => _11.isString(v) && _isSystemId(v),
4530
+ isUrl: (v) => _11.isString(v) && _isUrl(v)
4608
4531
  };
4609
4532
  if (!input2) {
4610
4533
  return [];
@@ -4616,7 +4539,7 @@ function _getUnlocalizableKeys(input2) {
4616
4539
  }
4617
4540
  }
4618
4541
  return false;
4619
- }).map(([key, _36]) => key);
4542
+ }).map(([key, _37]) => key);
4620
4543
  }
4621
4544
 
4622
4545
  // src/cli/loaders/formatters/prettier.ts
@@ -4783,7 +4706,7 @@ function createFormatterLoader(formatterType, parser, bucketPathPattern) {
4783
4706
  }
4784
4707
 
4785
4708
  // src/cli/loaders/po/index.ts
4786
- import _11 from "lodash";
4709
+ import _12 from "lodash";
4787
4710
  import gettextParser from "gettext-parser";
4788
4711
  function createPoLoader(params = { multiline: false }) {
4789
4712
  return composeLoaders(createPoDataLoader(params), createPoContentLoader());
@@ -4799,7 +4722,7 @@ function createPoDataLoader(params) {
4799
4722
  if (Object.keys(sectionPo.translations).length === 0) {
4800
4723
  continue;
4801
4724
  }
4802
- const contextKey = _11.keys(sectionPo.translations)[0];
4725
+ const contextKey = _12.keys(sectionPo.translations)[0];
4803
4726
  const entries = sectionPo.translations[contextKey];
4804
4727
  Object.entries(entries).forEach(([msgid, entry]) => {
4805
4728
  if (msgid && entry.msgid) {
@@ -4821,13 +4744,13 @@ function createPoDataLoader(params) {
4821
4744
  if (Object.keys(sectionPo.translations).length === 0) {
4822
4745
  return null;
4823
4746
  }
4824
- const contextKey = _11.keys(sectionPo.translations)[0];
4747
+ const contextKey = _12.keys(sectionPo.translations)[0];
4825
4748
  const entries = sectionPo.translations[contextKey];
4826
4749
  const msgid = Object.keys(entries).find((key) => entries[key].msgid);
4827
4750
  if (!msgid) {
4828
4751
  const currentSection = currentSections.find((cs) => {
4829
4752
  const csPo = gettextParser.po.parse(cs);
4830
- const csContextKey = _11.keys(csPo.translations)[0];
4753
+ const csContextKey = _12.keys(csPo.translations)[0];
4831
4754
  const csEntries = csPo.translations[csContextKey];
4832
4755
  const csMsgid = Object.keys(csEntries).find(
4833
4756
  (key) => csEntries[key].msgid
@@ -4840,7 +4763,7 @@ function createPoDataLoader(params) {
4840
4763
  return section;
4841
4764
  }
4842
4765
  if (data[msgid]) {
4843
- const updatedPo = _11.merge({}, sectionPo, {
4766
+ const updatedPo = _12.merge({}, sectionPo, {
4844
4767
  translations: {
4845
4768
  [contextKey]: {
4846
4769
  [msgid]: {
@@ -4864,7 +4787,7 @@ function createPoDataLoader(params) {
4864
4787
  function createPoContentLoader() {
4865
4788
  return createLoader({
4866
4789
  async pull(locale, input2, initCtx, originalLocale) {
4867
- const result = _11.chain(input2).entries().filter(([, entry]) => !!entry.msgid).map(([, entry]) => {
4790
+ const result = _12.chain(input2).entries().filter(([, entry]) => !!entry.msgid).map(([, entry]) => {
4868
4791
  const singularFallback = locale === originalLocale ? entry.msgid : null;
4869
4792
  const pluralFallback = locale === originalLocale ? entry.msgid_plural || entry.msgid : null;
4870
4793
  const hasPlural = entry.msgstr.length > 1;
@@ -4879,7 +4802,7 @@ function createPoContentLoader() {
4879
4802
  return result;
4880
4803
  },
4881
4804
  async push(locale, data, originalInput) {
4882
- const result = _11.chain(originalInput).entries().map(([, entry]) => [
4805
+ const result = _12.chain(originalInput).entries().map(([, entry]) => [
4883
4806
  entry.msgid,
4884
4807
  {
4885
4808
  ...entry,
@@ -5422,41 +5345,41 @@ var datoSettingsSchema = Z2.object({
5422
5345
  });
5423
5346
 
5424
5347
  // src/cli/loaders/dato/filter.ts
5425
- import _12 from "lodash";
5348
+ import _13 from "lodash";
5426
5349
  function createDatoFilterLoader() {
5427
5350
  return createLoader({
5428
5351
  async pull(locale, input2) {
5429
5352
  const result = {};
5430
- for (const [modelId, modelInfo] of _12.entries(input2)) {
5353
+ for (const [modelId, modelInfo] of _13.entries(input2)) {
5431
5354
  result[modelId] = {};
5432
5355
  for (const record of modelInfo.records) {
5433
- result[modelId][record.id] = _12.chain(modelInfo.fields).mapKeys((field) => field.api_key).mapValues((field) => _12.get(record, [field.api_key, locale])).value();
5356
+ result[modelId][record.id] = _13.chain(modelInfo.fields).mapKeys((field) => field.api_key).mapValues((field) => _13.get(record, [field.api_key, locale])).value();
5434
5357
  }
5435
5358
  }
5436
5359
  return result;
5437
5360
  },
5438
5361
  async push(locale, data, originalInput, originalLocale) {
5439
- const result = _12.cloneDeep(originalInput || {});
5440
- for (const [modelId, modelInfo] of _12.entries(result)) {
5362
+ const result = _13.cloneDeep(originalInput || {});
5363
+ for (const [modelId, modelInfo] of _13.entries(result)) {
5441
5364
  for (const record of modelInfo.records) {
5442
- for (const [fieldId, fieldValue] of _12.entries(record)) {
5365
+ for (const [fieldId, fieldValue] of _13.entries(record)) {
5443
5366
  const fieldInfo = modelInfo.fields.find(
5444
5367
  (field) => field.api_key === fieldId
5445
5368
  );
5446
5369
  if (fieldInfo) {
5447
- const sourceFieldValue = _12.get(fieldValue, [originalLocale]);
5448
- const targetFieldValue = _12.get(data, [
5370
+ const sourceFieldValue = _13.get(fieldValue, [originalLocale]);
5371
+ const targetFieldValue = _13.get(data, [
5449
5372
  modelId,
5450
5373
  record.id,
5451
5374
  fieldId
5452
5375
  ]);
5453
5376
  if (targetFieldValue) {
5454
- _12.set(record, [fieldId, locale], targetFieldValue);
5377
+ _13.set(record, [fieldId, locale], targetFieldValue);
5455
5378
  } else {
5456
- _12.set(record, [fieldId, locale], sourceFieldValue);
5379
+ _13.set(record, [fieldId, locale], sourceFieldValue);
5457
5380
  }
5458
- _12.chain(fieldValue).keys().reject((loc) => loc === locale || loc === originalLocale).filter((loc) => _12.isEmpty(_12.get(fieldValue, [loc]))).forEach(
5459
- (loc) => _12.set(record, [fieldId, loc], sourceFieldValue)
5381
+ _13.chain(fieldValue).keys().reject((loc) => loc === locale || loc === originalLocale).filter((loc) => _13.isEmpty(_13.get(fieldValue, [loc]))).forEach(
5382
+ (loc) => _13.set(record, [fieldId, loc], sourceFieldValue)
5460
5383
  ).value();
5461
5384
  }
5462
5385
  }
@@ -5468,10 +5391,10 @@ function createDatoFilterLoader() {
5468
5391
  }
5469
5392
 
5470
5393
  // src/cli/loaders/dato/api.ts
5471
- import _14 from "lodash";
5394
+ import _15 from "lodash";
5472
5395
 
5473
5396
  // src/cli/loaders/dato/_utils.ts
5474
- import _13 from "lodash";
5397
+ import _14 from "lodash";
5475
5398
  import { buildClient } from "@datocms/cma-client-node";
5476
5399
  function createDatoClient(params) {
5477
5400
  if (!params.apiKey) {
@@ -5664,7 +5587,7 @@ function createDatoApiLoader(config, onConfigUpdate) {
5664
5587
  const result = {
5665
5588
  models: {}
5666
5589
  };
5667
- const updatedConfig = _14.cloneDeep(config);
5590
+ const updatedConfig = _15.cloneDeep(config);
5668
5591
  console.log(`Initializing DatoCMS loader...`);
5669
5592
  const project = await dato.findProject();
5670
5593
  const modelChoices = await getModelChoices(dato, config);
@@ -5682,7 +5605,7 @@ function createDatoApiLoader(config, onConfigUpdate) {
5682
5605
  delete updatedConfig.models[modelId];
5683
5606
  }
5684
5607
  }
5685
- for (const modelId of _14.keys(updatedConfig.models)) {
5608
+ for (const modelId of _15.keys(updatedConfig.models)) {
5686
5609
  const { modelName, fields } = await getModelFields(dato, modelId);
5687
5610
  if (fields.length > 0) {
5688
5611
  result.models[modelId] = { fields: [], records: [] };
@@ -5700,7 +5623,7 @@ function createDatoApiLoader(config, onConfigUpdate) {
5700
5623
  );
5701
5624
  if (isLocalized) {
5702
5625
  result.models[modelId].fields.push(fieldInfo);
5703
- updatedConfig.models[modelId].fields = _14.uniq([
5626
+ updatedConfig.models[modelId].fields = _15.uniq([
5704
5627
  ...updatedConfig.models[modelId].fields || [],
5705
5628
  fieldInfo.api_key
5706
5629
  ]);
@@ -5728,7 +5651,7 @@ function createDatoApiLoader(config, onConfigUpdate) {
5728
5651
  },
5729
5652
  async pull(locale, input2, initCtx) {
5730
5653
  const result = {};
5731
- for (const modelId of _14.keys(initCtx?.models || {})) {
5654
+ for (const modelId of _15.keys(initCtx?.models || {})) {
5732
5655
  let records = initCtx?.models[modelId].records || [];
5733
5656
  const recordIds = records.map((record) => record.id);
5734
5657
  records = await dato.findRecords(recordIds);
@@ -5743,7 +5666,7 @@ function createDatoApiLoader(config, onConfigUpdate) {
5743
5666
  return result;
5744
5667
  },
5745
5668
  async push(locale, data, originalInput) {
5746
- for (const modelId of _14.keys(data)) {
5669
+ for (const modelId of _15.keys(data)) {
5747
5670
  for (let i = 0; i < data[modelId].records.length; i++) {
5748
5671
  const record = data[modelId].records[i];
5749
5672
  console.log(
@@ -5759,7 +5682,7 @@ async function getModelFields(dato, modelId) {
5759
5682
  const modelInfo = await dato.findModel(modelId);
5760
5683
  return {
5761
5684
  modelName: modelInfo.name,
5762
- fields: _14.filter(modelInfo.fields, (field) => field.type === "field")
5685
+ fields: _15.filter(modelInfo.fields, (field) => field.type === "field")
5763
5686
  };
5764
5687
  }
5765
5688
  async function getFieldDetails(dato, fields) {
@@ -5839,17 +5762,17 @@ async function promptModelSelection(choices) {
5839
5762
  }
5840
5763
 
5841
5764
  // src/cli/loaders/dato/extract.ts
5842
- import _15 from "lodash";
5765
+ import _16 from "lodash";
5843
5766
  function createDatoExtractLoader() {
5844
5767
  return createLoader({
5845
5768
  async pull(locale, input2) {
5846
5769
  const result = {};
5847
- for (const [modelId, modelInfo] of _15.entries(input2)) {
5848
- for (const [recordId, record] of _15.entries(modelInfo)) {
5849
- for (const [fieldName, fieldValue] of _15.entries(record)) {
5770
+ for (const [modelId, modelInfo] of _16.entries(input2)) {
5771
+ for (const [recordId, record] of _16.entries(modelInfo)) {
5772
+ for (const [fieldName, fieldValue] of _16.entries(record)) {
5850
5773
  const parsedValue = createParsedDatoValue(fieldValue);
5851
5774
  if (parsedValue) {
5852
- _15.set(result, [modelId, `_${recordId}`, fieldName], parsedValue);
5775
+ _16.set(result, [modelId, `_${recordId}`, fieldName], parsedValue);
5853
5776
  }
5854
5777
  }
5855
5778
  }
@@ -5857,12 +5780,12 @@ function createDatoExtractLoader() {
5857
5780
  return result;
5858
5781
  },
5859
5782
  async push(locale, data, originalInput) {
5860
- const result = _15.cloneDeep(originalInput || {});
5861
- for (const [modelId, modelInfo] of _15.entries(data)) {
5862
- for (const [virtualRecordId, record] of _15.entries(modelInfo)) {
5863
- for (const [fieldName, fieldValue] of _15.entries(record)) {
5783
+ const result = _16.cloneDeep(originalInput || {});
5784
+ for (const [modelId, modelInfo] of _16.entries(data)) {
5785
+ for (const [virtualRecordId, record] of _16.entries(modelInfo)) {
5786
+ for (const [fieldName, fieldValue] of _16.entries(record)) {
5864
5787
  const [, recordId] = virtualRecordId.split("_");
5865
- const originalFieldValue = _15.get(originalInput, [
5788
+ const originalFieldValue = _16.get(originalInput, [
5866
5789
  modelId,
5867
5790
  recordId,
5868
5791
  fieldName
@@ -5872,7 +5795,7 @@ function createDatoExtractLoader() {
5872
5795
  originalFieldValue,
5873
5796
  true
5874
5797
  );
5875
- _15.set(
5798
+ _16.set(
5876
5799
  result,
5877
5800
  [modelId, recordId, fieldName],
5878
5801
  rawValue || originalFieldValue
@@ -5885,25 +5808,25 @@ function createDatoExtractLoader() {
5885
5808
  });
5886
5809
  }
5887
5810
  function detectDatoFieldType(rawDatoValue) {
5888
- if (_15.has(rawDatoValue, "document") && _15.get(rawDatoValue, "schema") === "dast") {
5811
+ if (_16.has(rawDatoValue, "document") && _16.get(rawDatoValue, "schema") === "dast") {
5889
5812
  return "structured_text";
5890
- } else if (_15.has(rawDatoValue, "no_index") || _15.has(rawDatoValue, "twitter_card")) {
5813
+ } else if (_16.has(rawDatoValue, "no_index") || _16.has(rawDatoValue, "twitter_card")) {
5891
5814
  return "seo";
5892
- } else if (_15.get(rawDatoValue, "type") === "item") {
5815
+ } else if (_16.get(rawDatoValue, "type") === "item") {
5893
5816
  return "single_block";
5894
- } else if (_15.isArray(rawDatoValue) && _15.every(rawDatoValue, (item) => _15.get(item, "type") === "item")) {
5817
+ } else if (_16.isArray(rawDatoValue) && _16.every(rawDatoValue, (item) => _16.get(item, "type") === "item")) {
5895
5818
  return "rich_text";
5896
5819
  } else if (_isFile(rawDatoValue)) {
5897
5820
  return "file";
5898
- } else if (_15.isArray(rawDatoValue) && _15.every(rawDatoValue, (item) => _isFile(item))) {
5821
+ } else if (_16.isArray(rawDatoValue) && _16.every(rawDatoValue, (item) => _isFile(item))) {
5899
5822
  return "gallery";
5900
5823
  } else if (_isJson(rawDatoValue)) {
5901
5824
  return "json";
5902
- } else if (_15.isString(rawDatoValue)) {
5825
+ } else if (_16.isString(rawDatoValue)) {
5903
5826
  return "string";
5904
5827
  } else if (_isVideo(rawDatoValue)) {
5905
5828
  return "video";
5906
- } else if (_15.isArray(rawDatoValue) && _15.every(rawDatoValue, (item) => _15.isString(item))) {
5829
+ } else if (_16.isArray(rawDatoValue) && _16.every(rawDatoValue, (item) => _16.isString(item))) {
5907
5830
  return "ref_list";
5908
5831
  } else {
5909
5832
  return null;
@@ -5973,9 +5896,9 @@ function serializeStructuredText(rawStructuredText) {
5973
5896
  acc
5974
5897
  );
5975
5898
  }
5976
- if (!_15.isNil(node.value)) {
5899
+ if (!_16.isNil(node.value)) {
5977
5900
  acc[[...path19, "value"].join(".")] = node.value;
5978
- } else if (_15.get(node, "type") === "block") {
5901
+ } else if (_16.get(node, "type") === "block") {
5979
5902
  acc[[...path19, "item"].join(".")] = serializeBlock(node.item);
5980
5903
  }
5981
5904
  if (node.children) {
@@ -5991,48 +5914,48 @@ function serializeStructuredText(rawStructuredText) {
5991
5914
  }
5992
5915
  }
5993
5916
  function serializeSeo(rawSeo) {
5994
- return _15.chain(rawSeo).pick(["title", "description"]).value();
5917
+ return _16.chain(rawSeo).pick(["title", "description"]).value();
5995
5918
  }
5996
5919
  function serializeBlock(rawBlock) {
5997
- if (_15.get(rawBlock, "type") === "item" && _15.has(rawBlock, "id")) {
5920
+ if (_16.get(rawBlock, "type") === "item" && _16.has(rawBlock, "id")) {
5998
5921
  return serializeBlock(rawBlock.attributes);
5999
5922
  }
6000
5923
  const result = {};
6001
- for (const [attributeName, attributeValue] of _15.entries(rawBlock)) {
5924
+ for (const [attributeName, attributeValue] of _16.entries(rawBlock)) {
6002
5925
  result[attributeName] = createParsedDatoValue(attributeValue);
6003
5926
  }
6004
5927
  return result;
6005
5928
  }
6006
5929
  function serializeBlockList(rawBlockList) {
6007
- return _15.chain(rawBlockList).map((block) => serializeBlock(block)).value();
5930
+ return _16.chain(rawBlockList).map((block) => serializeBlock(block)).value();
6008
5931
  }
6009
5932
  function serializeVideo(rawVideo) {
6010
- return _15.chain(rawVideo).pick(["title"]).value();
5933
+ return _16.chain(rawVideo).pick(["title"]).value();
6011
5934
  }
6012
5935
  function serializeFile(rawFile) {
6013
- return _15.chain(rawFile).pick(["alt", "title"]).value();
5936
+ return _16.chain(rawFile).pick(["alt", "title"]).value();
6014
5937
  }
6015
5938
  function serializeGallery(rawGallery) {
6016
- return _15.chain(rawGallery).map((item) => serializeFile(item)).value();
5939
+ return _16.chain(rawGallery).map((item) => serializeFile(item)).value();
6017
5940
  }
6018
5941
  function deserializeFile(parsedFile, originalRawFile) {
6019
- return _15.chain(parsedFile).defaults(originalRawFile).value();
5942
+ return _16.chain(parsedFile).defaults(originalRawFile).value();
6020
5943
  }
6021
5944
  function deserializeGallery(parsedGallery, originalRawGallery) {
6022
- return _15.chain(parsedGallery).map((item, i) => deserializeFile(item, originalRawGallery[i])).value();
5945
+ return _16.chain(parsedGallery).map((item, i) => deserializeFile(item, originalRawGallery[i])).value();
6023
5946
  }
6024
5947
  function deserializeVideo(parsedVideo, originalRawVideo) {
6025
- return _15.chain(parsedVideo).defaults(originalRawVideo).value();
5948
+ return _16.chain(parsedVideo).defaults(originalRawVideo).value();
6026
5949
  }
6027
5950
  function deserializeBlock(payload, rawNode, isClean = false) {
6028
- const result = _15.cloneDeep(rawNode);
6029
- for (const [attributeName, attributeValue] of _15.entries(rawNode.attributes)) {
5951
+ const result = _16.cloneDeep(rawNode);
5952
+ for (const [attributeName, attributeValue] of _16.entries(rawNode.attributes)) {
6030
5953
  const rawValue = createRawDatoValue(
6031
5954
  payload[attributeName],
6032
5955
  attributeValue,
6033
5956
  isClean
6034
5957
  );
6035
- _15.set(result, ["attributes", attributeName], rawValue);
5958
+ _16.set(result, ["attributes", attributeName], rawValue);
6036
5959
  }
6037
5960
  if (isClean) {
6038
5961
  delete result["id"];
@@ -6040,40 +5963,40 @@ function deserializeBlock(payload, rawNode, isClean = false) {
6040
5963
  return result;
6041
5964
  }
6042
5965
  function deserializeSeo(parsedSeo, originalRawSeo) {
6043
- return _15.chain(parsedSeo).pick(["title", "description"]).defaults(originalRawSeo).value();
5966
+ return _16.chain(parsedSeo).pick(["title", "description"]).defaults(originalRawSeo).value();
6044
5967
  }
6045
5968
  function deserializeBlockList(parsedBlockList, originalRawBlockList, isClean = false) {
6046
- return _15.chain(parsedBlockList).map(
5969
+ return _16.chain(parsedBlockList).map(
6047
5970
  (block, i) => deserializeBlock(block, originalRawBlockList[i], isClean)
6048
5971
  ).value();
6049
5972
  }
6050
5973
  function deserializeStructuredText(parsedStructuredText, originalRawStructuredText) {
6051
- const result = _15.cloneDeep(originalRawStructuredText);
6052
- for (const [path19, value] of _15.entries(parsedStructuredText)) {
6053
- const realPath = _15.chain(path19.split(".")).flatMap((s) => !_15.isNaN(_15.toNumber(s)) ? ["children", s] : s).value();
5974
+ const result = _16.cloneDeep(originalRawStructuredText);
5975
+ for (const [path19, value] of _16.entries(parsedStructuredText)) {
5976
+ const realPath = _16.chain(path19.split(".")).flatMap((s) => !_16.isNaN(_16.toNumber(s)) ? ["children", s] : s).value();
6054
5977
  const deserializedValue = createRawDatoValue(
6055
5978
  value,
6056
- _15.get(originalRawStructuredText, realPath),
5979
+ _16.get(originalRawStructuredText, realPath),
6057
5980
  true
6058
5981
  );
6059
- _15.set(result, realPath, deserializedValue);
5982
+ _16.set(result, realPath, deserializedValue);
6060
5983
  }
6061
5984
  return result;
6062
5985
  }
6063
5986
  function _isJson(rawDatoValue) {
6064
5987
  try {
6065
- return _15.isString(rawDatoValue) && rawDatoValue.startsWith("{") && rawDatoValue.endsWith("}") && !!JSON.parse(rawDatoValue);
5988
+ return _16.isString(rawDatoValue) && rawDatoValue.startsWith("{") && rawDatoValue.endsWith("}") && !!JSON.parse(rawDatoValue);
6066
5989
  } catch (e) {
6067
5990
  return false;
6068
5991
  }
6069
5992
  }
6070
5993
  function _isFile(rawDatoValue) {
6071
- return _15.isObject(rawDatoValue) && ["alt", "title", "custom_data", "focal_point", "upload_id"].every(
6072
- (key) => _15.has(rawDatoValue, key)
5994
+ return _16.isObject(rawDatoValue) && ["alt", "title", "custom_data", "focal_point", "upload_id"].every(
5995
+ (key) => _16.has(rawDatoValue, key)
6073
5996
  );
6074
5997
  }
6075
5998
  function _isVideo(rawDatoValue) {
6076
- return _15.isObject(rawDatoValue) && [
5999
+ return _16.isObject(rawDatoValue) && [
6077
6000
  "url",
6078
6001
  "title",
6079
6002
  "width",
@@ -6081,7 +6004,7 @@ function _isVideo(rawDatoValue) {
6081
6004
  "provider",
6082
6005
  "provider_uid",
6083
6006
  "thumbnail_url"
6084
- ].every((key) => _15.has(rawDatoValue, key));
6007
+ ].every((key) => _16.has(rawDatoValue, key));
6085
6008
  }
6086
6009
 
6087
6010
  // src/cli/loaders/dato/index.ts
@@ -6151,7 +6074,7 @@ function createVttLoader() {
6151
6074
  }
6152
6075
 
6153
6076
  // src/cli/loaders/variable/index.ts
6154
- import _16 from "lodash";
6077
+ import _17 from "lodash";
6155
6078
  function createVariableLoader(params) {
6156
6079
  return composeLoaders(variableExtractLoader(params), variableContentLoader());
6157
6080
  }
@@ -6160,18 +6083,9 @@ function variableExtractLoader(params) {
6160
6083
  return createLoader({
6161
6084
  pull: async (locale, input2, initXtx, originalLocale, originalInput) => {
6162
6085
  const result = {};
6163
- const inputValues = _16.omitBy(input2, _16.isEmpty);
6086
+ const inputValues = _17.omitBy(input2, _17.isEmpty);
6164
6087
  for (const [key, value] of Object.entries(inputValues)) {
6165
6088
  const originalValue = originalInput[key];
6166
- if (isICUPluralObject(originalValue)) {
6167
- const icuValue = isICUPluralObject(value) ? { icu: value.icu } : value;
6168
- result[key] = {
6169
- value: icuValue,
6170
- variables: []
6171
- // Metadata stored separately, not in variables
6172
- };
6173
- continue;
6174
- }
6175
6089
  const matches = originalValue.match(specifierPattern) || [];
6176
6090
  result[key] = result[key] || {
6177
6091
  value,
@@ -6191,19 +6105,14 @@ function variableExtractLoader(params) {
6191
6105
  const result = {};
6192
6106
  for (const [key, valueObj] of Object.entries(data)) {
6193
6107
  result[key] = valueObj.value;
6194
- const resultValue = result[key];
6195
- if (isICUPluralObject(resultValue)) {
6196
- const originalValue = originalInput?.[key];
6197
- if (isICUPluralObject(originalValue) && originalValue._meta) {
6198
- resultValue._meta = originalValue._meta;
6199
- resultValue[Symbol.for("@lingo.dev/icu-plural-object")] = true;
6200
- }
6201
- }
6202
6108
  for (let i = 0; i < valueObj.variables.length; i++) {
6203
6109
  const variable = valueObj.variables[i];
6204
6110
  const currentValue = result[key];
6205
6111
  if (typeof currentValue === "string") {
6206
- const newValue = currentValue?.replace(`{variable:${i}}`, variable);
6112
+ const newValue = currentValue?.replaceAll(
6113
+ `{variable:${i}}`,
6114
+ variable
6115
+ );
6207
6116
  result[key] = newValue;
6208
6117
  }
6209
6118
  }
@@ -6215,11 +6124,11 @@ function variableExtractLoader(params) {
6215
6124
  function variableContentLoader() {
6216
6125
  return createLoader({
6217
6126
  pull: async (locale, input2) => {
6218
- const result = _16.mapValues(input2, (payload) => payload.value);
6127
+ const result = _17.mapValues(input2, (payload) => payload.value);
6219
6128
  return result;
6220
6129
  },
6221
6130
  push: async (locale, data, originalInput, defaultLocale, pullInput) => {
6222
- const result = _16.cloneDeep(
6131
+ const result = _17.cloneDeep(
6223
6132
  originalInput || {}
6224
6133
  );
6225
6134
  for (const [key, originalValueObj] of Object.entries(result)) {
@@ -6244,20 +6153,20 @@ function getFormatSpecifierPattern(type) {
6244
6153
  }
6245
6154
 
6246
6155
  // src/cli/loaders/sync.ts
6247
- import _17 from "lodash";
6156
+ import _18 from "lodash";
6248
6157
  function createSyncLoader() {
6249
6158
  return createLoader({
6250
6159
  async pull(locale, input2, initCtx, originalLocale, originalInput) {
6251
6160
  if (!originalInput) {
6252
6161
  return input2;
6253
6162
  }
6254
- return _17.chain(originalInput).mapValues((value, key) => input2[key]).value();
6163
+ return _18.chain(originalInput).mapValues((value, key) => input2[key]).value();
6255
6164
  },
6256
6165
  async push(locale, data, originalInput) {
6257
6166
  if (!originalInput) {
6258
6167
  return data;
6259
6168
  }
6260
- return _17.chain(originalInput || {}).mapValues((value, key) => data[key]).value();
6169
+ return _18.chain(originalInput || {}).mapValues((value, key) => data[key]).value();
6261
6170
  }
6262
6171
  });
6263
6172
  }
@@ -6439,7 +6348,7 @@ function parseVueFile(input2) {
6439
6348
 
6440
6349
  // src/cli/loaders/typescript/index.ts
6441
6350
  import { parse as parse3 } from "@babel/parser";
6442
- import _18 from "lodash";
6351
+ import _19 from "lodash";
6443
6352
  import babelTraverseModule from "@babel/traverse";
6444
6353
  import * as t from "@babel/types";
6445
6354
  import babelGenerateModule from "@babel/generator";
@@ -6475,7 +6384,7 @@ function createTypescriptLoader() {
6475
6384
  },
6476
6385
  push: async (locale, data, originalInput, defaultLocale, pullInput, pullOutput) => {
6477
6386
  const ast = parseTypeScript(originalInput || "");
6478
- const finalData = _18.merge({}, pullOutput, data);
6387
+ const finalData = _19.merge({}, pullOutput, data);
6479
6388
  updateStringsInDefaultExport(ast, finalData);
6480
6389
  const { code } = generate(ast, {
6481
6390
  jsescOption: {
@@ -6676,7 +6585,7 @@ function getPropertyKey(prop) {
6676
6585
  }
6677
6586
 
6678
6587
  // src/cli/loaders/inject-locale.ts
6679
- import _19 from "lodash";
6588
+ import _20 from "lodash";
6680
6589
 
6681
6590
  // ../../node_modules/.pnpm/@isaacs+balanced-match@4.0.1/node_modules/@isaacs/balanced-match/dist/esm/index.js
6682
6591
  var balanced = (a, b, str) => {
@@ -7367,7 +7276,7 @@ var AST = class _AST {
7367
7276
  if (!this.type) {
7368
7277
  const noEmpty = this.isStart() && this.isEnd();
7369
7278
  const src = this.#parts.map((p) => {
7370
- const [re, _36, hasMagic, uflag] = typeof p === "string" ? _AST.#parseGlob(p, this.#hasMagic, noEmpty) : p.toRegExpSource(allowDot);
7279
+ const [re, _37, hasMagic, uflag] = typeof p === "string" ? _AST.#parseGlob(p, this.#hasMagic, noEmpty) : p.toRegExpSource(allowDot);
7371
7280
  this.#hasMagic = this.#hasMagic || hasMagic;
7372
7281
  this.#uflag = this.#uflag || uflag;
7373
7282
  return re;
@@ -7440,7 +7349,7 @@ var AST = class _AST {
7440
7349
  if (typeof p === "string") {
7441
7350
  throw new Error("string type in extglob ast??");
7442
7351
  }
7443
- const [re, _36, _hasMagic, uflag] = p.toRegExpSource(dot);
7352
+ const [re, _37, _hasMagic, uflag] = p.toRegExpSource(dot);
7444
7353
  this.#uflag = this.#uflag || uflag;
7445
7354
  return re;
7446
7355
  }).filter((p) => !(this.isStart() && this.isEnd()) || !!p).join("|");
@@ -7685,7 +7594,7 @@ var Minimatch = class {
7685
7594
  }
7686
7595
  return false;
7687
7596
  }
7688
- debug(..._36) {
7597
+ debug(..._37) {
7689
7598
  }
7690
7599
  make() {
7691
7600
  const pattern = this.pattern;
@@ -7707,7 +7616,7 @@ var Minimatch = class {
7707
7616
  const rawGlobParts = this.globSet.map((s) => this.slashSplit(s));
7708
7617
  this.globParts = this.preprocess(rawGlobParts);
7709
7618
  this.debug(this.pattern, this.globParts);
7710
- let set = this.globParts.map((s, _36, __) => {
7619
+ let set = this.globParts.map((s, _37, __) => {
7711
7620
  if (this.isWindows && this.windowsNoMagicRoot) {
7712
7621
  const isUNC = s[0] === "" && s[1] === "" && (s[2] === "?" || !globMagic.test(s[2])) && !globMagic.test(s[3]);
7713
7622
  const isDrive = /^[a-z]:/i.test(s[0]);
@@ -8224,7 +8133,7 @@ function createInjectLocaleLoader(injectLocaleKeys) {
8224
8133
  return data;
8225
8134
  }
8226
8135
  const omitKeys = _getKeysWithLocales(data, injectLocaleKeys, locale);
8227
- const result = _19.omit(data, omitKeys);
8136
+ const result = _20.omit(data, omitKeys);
8228
8137
  return result;
8229
8138
  },
8230
8139
  async push(locale, data, originalInput, originalLocale) {
@@ -8237,7 +8146,7 @@ function createInjectLocaleLoader(injectLocaleKeys) {
8237
8146
  originalLocale
8238
8147
  );
8239
8148
  localeKeys.forEach((key) => {
8240
- _19.set(data, key, locale);
8149
+ _20.set(data, key, locale);
8241
8150
  });
8242
8151
  return data;
8243
8152
  }
@@ -8246,7 +8155,7 @@ function createInjectLocaleLoader(injectLocaleKeys) {
8246
8155
  function _getKeysWithLocales(data, injectLocaleKeys, locale) {
8247
8156
  const allKeys = _getAllKeys(data);
8248
8157
  return allKeys.filter((key) => {
8249
- return injectLocaleKeys.some((pattern) => minimatch(key, pattern)) && _19.get(data, key) === locale;
8158
+ return injectLocaleKeys.some((pattern) => minimatch(key, pattern)) && _20.get(data, key) === locale;
8250
8159
  });
8251
8160
  }
8252
8161
  function _getAllKeys(obj, prefix = "") {
@@ -8264,7 +8173,7 @@ function _getAllKeys(obj, prefix = "") {
8264
8173
  }
8265
8174
 
8266
8175
  // src/cli/loaders/locked-keys.ts
8267
- import _20 from "lodash";
8176
+ import _21 from "lodash";
8268
8177
 
8269
8178
  // src/cli/utils/key-matching.ts
8270
8179
  function matchesKeyPattern(key, patterns) {
@@ -8283,14 +8192,14 @@ function formatDisplayValue(value, maxLength = 50) {
8283
8192
  function createLockedKeysLoader(lockedKeys) {
8284
8193
  return createLoader({
8285
8194
  pull: async (locale, data) => {
8286
- return _20.pickBy(
8195
+ return _21.pickBy(
8287
8196
  data,
8288
8197
  (value, key) => !matchesKeyPattern(key, lockedKeys)
8289
8198
  );
8290
8199
  },
8291
8200
  push: async (locale, data, originalInput) => {
8292
- const lockedSubObject = _20.chain(originalInput).pickBy((value, key) => matchesKeyPattern(key, lockedKeys)).value();
8293
- return _20.merge({}, data, lockedSubObject);
8201
+ const lockedSubObject = _21.chain(originalInput).pickBy((value, key) => matchesKeyPattern(key, lockedKeys)).value();
8202
+ return _21.merge({}, data, lockedSubObject);
8294
8203
  }
8295
8204
  });
8296
8205
  }
@@ -8342,7 +8251,7 @@ function md5(input2) {
8342
8251
  }
8343
8252
 
8344
8253
  // src/cli/loaders/mdx2/code-placeholder.ts
8345
- import _21 from "lodash";
8254
+ import _22 from "lodash";
8346
8255
  var fenceRegex = /([ \t]*)(^>\s*)?```([\s\S]*?)```/gm;
8347
8256
  var inlineCodeRegex = /(?<!`)`([^`\r\n]+?)`(?!`)/g;
8348
8257
  var imageRegex = /([ \t]*)(^>\s*)?!\[[^\]]*?\]\(([^()]*(\([^()]*\)[^()]*)*)\)/gm;
@@ -8365,7 +8274,7 @@ ${match2}
8365
8274
  found = true;
8366
8275
  }
8367
8276
  } while (found);
8368
- content = _21.chain(content).split("\n\n").map((section) => _21.trim(section, "\n")).filter(Boolean).join("\n\n").value();
8277
+ content = _22.chain(content).split("\n\n").map((section) => _22.trim(section, "\n")).filter(Boolean).join("\n\n").value();
8369
8278
  return content;
8370
8279
  }
8371
8280
  function ensureTrailingFenceNewline(_content) {
@@ -8387,7 +8296,7 @@ ${match2}
8387
8296
  found = true;
8388
8297
  }
8389
8298
  } while (found);
8390
- content = _21.chain(content).split("\n\n").map((section) => _21.trim(section, "\n")).filter(Boolean).join("\n\n").value();
8299
+ content = _22.chain(content).split("\n\n").map((section) => _22.trim(section, "\n")).filter(Boolean).join("\n\n").value();
8391
8300
  return content;
8392
8301
  }
8393
8302
  function extractCodePlaceholders(content) {
@@ -8429,7 +8338,7 @@ function createMdxCodePlaceholderLoader() {
8429
8338
  async push(locale, data, originalInput, originalLocale, pullInput) {
8430
8339
  const sourceInfo = extractCodePlaceholders(originalInput ?? "");
8431
8340
  const currentInfo = extractCodePlaceholders(pullInput ?? "");
8432
- const codePlaceholders = _21.merge(
8341
+ const codePlaceholders = _22.merge(
8433
8342
  sourceInfo.codePlaceholders,
8434
8343
  currentInfo.codePlaceholders,
8435
8344
  globalPlaceholderRegistry
@@ -8437,7 +8346,7 @@ function createMdxCodePlaceholderLoader() {
8437
8346
  );
8438
8347
  let result = data;
8439
8348
  for (const [placeholder, original] of Object.entries(codePlaceholders)) {
8440
- const replacement = original.startsWith(">") ? _21.trimStart(original, "> ") : original;
8349
+ const replacement = original.startsWith(">") ? _22.trimStart(original, "> ") : original;
8441
8350
  result = result.replaceAll(placeholder, () => replacement);
8442
8351
  }
8443
8352
  return result;
@@ -8465,11 +8374,11 @@ function createLocalizableMdxDocumentLoader() {
8465
8374
  }
8466
8375
 
8467
8376
  // src/cli/loaders/mdx2/sections-split-2.ts
8468
- import _22 from "lodash";
8377
+ import _23 from "lodash";
8469
8378
  function createMdxSectionsSplit2Loader() {
8470
8379
  return createLoader({
8471
8380
  async pull(locale, input2) {
8472
- const sections = _22.chain(input2.content).split("\n\n").filter(Boolean).map((section, index) => [index, section]).fromPairs().value();
8381
+ const sections = _23.chain(input2.content).split("\n\n").filter(Boolean).map((section, index) => [index, section]).fromPairs().value();
8473
8382
  const result = {
8474
8383
  frontmatter: input2.frontmatter,
8475
8384
  sections
@@ -8477,7 +8386,7 @@ function createMdxSectionsSplit2Loader() {
8477
8386
  return result;
8478
8387
  },
8479
8388
  async push(locale, data, originalInput, _originalLocale, pullInput) {
8480
- const content = _22.chain(data.sections).values().join("\n\n").value();
8389
+ const content = _23.chain(data.sections).values().join("\n\n").value();
8481
8390
  const result = {
8482
8391
  frontmatter: data.frontmatter,
8483
8392
  codePlaceholders: pullInput?.codePlaceholders || {},
@@ -8543,18 +8452,18 @@ function createLockedPatternsLoader(defaultPatterns) {
8543
8452
  }
8544
8453
 
8545
8454
  // src/cli/loaders/ignored-keys.ts
8546
- import _23 from "lodash";
8455
+ import _24 from "lodash";
8547
8456
  function createIgnoredKeysLoader(ignoredKeys) {
8548
8457
  return createLoader({
8549
8458
  pull: async (locale, data) => {
8550
- const result = _23.omitBy(
8459
+ const result = _24.omitBy(
8551
8460
  data,
8552
8461
  (value, key) => matchesKeyPattern(key, ignoredKeys)
8553
8462
  );
8554
8463
  return result;
8555
8464
  },
8556
8465
  push: async (locale, data, originalInput, originalLocale, pullInput) => {
8557
- const result = _23.omitBy(
8466
+ const result = _24.omitBy(
8558
8467
  data,
8559
8468
  (value, key) => matchesKeyPattern(key, ignoredKeys)
8560
8469
  );
@@ -8695,7 +8604,7 @@ function createEjsLoader() {
8695
8604
  }
8696
8605
 
8697
8606
  // src/cli/loaders/ensure-key-order.ts
8698
- import _24 from "lodash";
8607
+ import _25 from "lodash";
8699
8608
  function createEnsureKeyOrderLoader() {
8700
8609
  return createLoader({
8701
8610
  pull: async (_locale, input2) => {
@@ -8710,10 +8619,10 @@ function createEnsureKeyOrderLoader() {
8710
8619
  });
8711
8620
  }
8712
8621
  function reorderKeys(data, originalInput) {
8713
- if (_24.isArray(originalInput) && _24.isArray(data)) {
8622
+ if (_25.isArray(originalInput) && _25.isArray(data)) {
8714
8623
  return data.map((item, idx) => reorderKeys(item, originalInput[idx] ?? {}));
8715
8624
  }
8716
- if (!_24.isObject(data) || _24.isArray(data) || _24.isDate(data)) {
8625
+ if (!_25.isObject(data) || _25.isArray(data) || _25.isDate(data)) {
8717
8626
  return data;
8718
8627
  }
8719
8628
  const orderedData = {};
@@ -8745,13 +8654,13 @@ function createTxtLoader() {
8745
8654
  const sortedEntries = Object.entries(payload).sort(
8746
8655
  ([a], [b]) => parseInt(a) - parseInt(b)
8747
8656
  );
8748
- return sortedEntries.map(([_36, value]) => value).join("\n");
8657
+ return sortedEntries.map(([_37, value]) => value).join("\n");
8749
8658
  }
8750
8659
  });
8751
8660
  }
8752
8661
 
8753
8662
  // src/cli/loaders/json-dictionary.ts
8754
- import _25 from "lodash";
8663
+ import _26 from "lodash";
8755
8664
  var TOP_LEVEL_KEY = "--content--";
8756
8665
  function createJsonDictionaryLoader() {
8757
8666
  return createLoader({
@@ -8766,7 +8675,7 @@ function createJsonDictionaryLoader() {
8766
8675
  if (!originalInput) {
8767
8676
  throw new Error("Error while parsing json-dictionary bucket");
8768
8677
  }
8769
- const input2 = _25.cloneDeep(originalInput);
8678
+ const input2 = _26.cloneDeep(originalInput);
8770
8679
  if (Object.keys(data).length === 1 && Object.keys(data)[0] === TOP_LEVEL_KEY) {
8771
8680
  setNestedLocale(
8772
8681
  { [TOP_LEVEL_KEY]: input2 },
@@ -9036,9 +8945,8 @@ function createBucketLoader(bucketType, bucketPathPattern, options, lockedKeys,
9036
8945
  createPlutilJsonTextLoader(),
9037
8946
  createLockedPatternsLoader(lockedPatterns),
9038
8947
  createJsonLoader(),
9039
- createXcodeXcstringsLoader(options.defaultLocale),
9040
8948
  createXcodeXcstringsV2Loader(options.defaultLocale),
9041
- createFlatLoader({ shouldPreserveObject: isICUPluralObject }),
8949
+ createFlatLoader(),
9042
8950
  createEnsureKeyOrderLoader(),
9043
8951
  createLockedKeysLoader(lockedKeys || []),
9044
8952
  createIgnoredKeysLoader(ignoredKeys || []),
@@ -9347,7 +9255,7 @@ import { Command as Command13 } from "interactive-commander";
9347
9255
  import { Command as Command10 } from "interactive-commander";
9348
9256
  import chalk2 from "chalk";
9349
9257
  import dedent from "dedent";
9350
- import _26 from "lodash";
9258
+ import _27 from "lodash";
9351
9259
  var set_default = new Command10().name("set").description("Set or update a CLI setting in ~/.lingodotdevrc").addHelpText("afterAll", `
9352
9260
  Available keys:
9353
9261
  ${SETTINGS_KEYS.join("\n ")}`).argument(
@@ -9365,8 +9273,8 @@ Available keys:
9365
9273
  return;
9366
9274
  }
9367
9275
  const current = loadSystemSettings();
9368
- const updated = _26.cloneDeep(current);
9369
- _26.set(updated, key, value);
9276
+ const updated = _27.cloneDeep(current);
9277
+ _27.set(updated, key, value);
9370
9278
  try {
9371
9279
  saveSettings(updated);
9372
9280
  console.log(`${chalk2.green("\u2714")} Set ${chalk2.bold(key)}`);
@@ -9386,7 +9294,7 @@ Available keys:
9386
9294
  import { Command as Command11 } from "interactive-commander";
9387
9295
  import chalk3 from "chalk";
9388
9296
  import dedent2 from "dedent";
9389
- import _27 from "lodash";
9297
+ import _28 from "lodash";
9390
9298
  var unset_default = new Command11().name("unset").description("Remove a CLI setting from ~/.lingodotdevrc").addHelpText("afterAll", `
9391
9299
  Available keys:
9392
9300
  ${SETTINGS_KEYS.join("\n ")}`).argument(
@@ -9406,13 +9314,13 @@ Available keys:
9406
9314
  return;
9407
9315
  }
9408
9316
  const settings = loadSystemSettings();
9409
- const currentValue = _27.get(settings, key);
9410
- if (!_27.trim(String(currentValue || ""))) {
9317
+ const currentValue = _28.get(settings, key);
9318
+ if (!_28.trim(String(currentValue || ""))) {
9411
9319
  console.log(`${chalk3.cyan("\u2139")} ${chalk3.bold(key)} is not set.`);
9412
9320
  return;
9413
9321
  } else {
9414
- const updated = _27.cloneDeep(settings);
9415
- _27.unset(updated, key);
9322
+ const updated = _28.cloneDeep(settings);
9323
+ _28.unset(updated, key);
9416
9324
  try {
9417
9325
  saveSettings(updated);
9418
9326
  console.log(
@@ -9434,7 +9342,7 @@ Available keys:
9434
9342
  // src/cli/cmd/config/get.ts
9435
9343
  import { Command as Command12 } from "interactive-commander";
9436
9344
  import chalk4 from "chalk";
9437
- import _28 from "lodash";
9345
+ import _29 from "lodash";
9438
9346
  import dedent3 from "dedent";
9439
9347
  var get_default = new Command12().name("get").description("Display the value of a CLI setting from ~/.lingodotdevrc").addHelpText("afterAll", `
9440
9348
  Available keys:
@@ -9453,7 +9361,7 @@ Available keys:
9453
9361
  return;
9454
9362
  }
9455
9363
  const settings = loadSystemSettings();
9456
- const value = _28.get(settings, key);
9364
+ const value = _29.get(settings, key);
9457
9365
  if (!value) {
9458
9366
  console.log(`${chalk4.cyan("\u2139")} ${chalk4.bold(key)} is not set.`);
9459
9367
  return;
@@ -9478,7 +9386,7 @@ import {
9478
9386
  } from "@lingo.dev/_spec";
9479
9387
  import { Command as Command14 } from "interactive-commander";
9480
9388
  import Z3 from "zod";
9481
- import _31 from "lodash";
9389
+ import _32 from "lodash";
9482
9390
  import Ora9 from "ora";
9483
9391
  import chalk6 from "chalk";
9484
9392
  import { createTwoFilesPatch } from "diff";
@@ -9518,7 +9426,7 @@ function createLingoLocalizer(params) {
9518
9426
 
9519
9427
  // src/cli/processor/basic.ts
9520
9428
  import { generateText } from "ai";
9521
- import _29 from "lodash";
9429
+ import _30 from "lodash";
9522
9430
  function createBasicTranslator(model, systemPrompt, settings = {}) {
9523
9431
  return async (input2, onProgress) => {
9524
9432
  const chunks = extractPayloadChunks(input2.processableData);
@@ -9532,7 +9440,7 @@ function createBasicTranslator(model, systemPrompt, settings = {}) {
9532
9440
  subResults.push(result2);
9533
9441
  onProgress(i / chunks.length * 100, chunk, result2);
9534
9442
  }
9535
- const result = _29.merge({}, ...subResults);
9443
+ const result = _30.merge({}, ...subResults);
9536
9444
  return result;
9537
9445
  };
9538
9446
  async function doJob(input2) {
@@ -9809,7 +9717,7 @@ function trackEvent(distinctId, event, properties) {
9809
9717
  }
9810
9718
 
9811
9719
  // src/cli/utils/delta.ts
9812
- import _30 from "lodash";
9720
+ import _31 from "lodash";
9813
9721
  import z from "zod";
9814
9722
 
9815
9723
  // src/cli/utils/fs.ts
@@ -9858,11 +9766,11 @@ function createDeltaProcessor(fileKey) {
9858
9766
  return checkIfFileExists(lockfilePath);
9859
9767
  },
9860
9768
  async calculateDelta(params) {
9861
- let added = _30.difference(
9769
+ let added = _31.difference(
9862
9770
  Object.keys(params.sourceData),
9863
9771
  Object.keys(params.targetData)
9864
9772
  );
9865
- let removed = _30.difference(
9773
+ let removed = _31.difference(
9866
9774
  Object.keys(params.targetData),
9867
9775
  Object.keys(params.sourceData)
9868
9776
  );
@@ -9924,7 +9832,7 @@ function createDeltaProcessor(fileKey) {
9924
9832
  await this.saveLock(lockfileData);
9925
9833
  },
9926
9834
  async createChecksums(sourceData) {
9927
- const checksums = _30.mapValues(sourceData, (value) => md5(value));
9835
+ const checksums = _31.mapValues(sourceData, (value) => md5(value));
9928
9836
  return checksums;
9929
9837
  }
9930
9838
  };
@@ -10117,7 +10025,7 @@ var i18n_default = new Command14().command("i18n").description(
10117
10025
  const deltaProcessor = createDeltaProcessor(bucketPath.pathPattern);
10118
10026
  const sourceChecksums = await deltaProcessor.createChecksums(sourceData);
10119
10027
  const savedChecksums = await deltaProcessor.loadChecksums();
10120
- const updatedSourceData = _31.pickBy(
10028
+ const updatedSourceData = _32.pickBy(
10121
10029
  sourceData,
10122
10030
  (value, key) => sourceChecksums[key] !== savedChecksums[key]
10123
10031
  );
@@ -10131,15 +10039,15 @@ var i18n_default = new Command14().command("i18n").description(
10131
10039
  bucketPath.delimiter
10132
10040
  );
10133
10041
  const { unlocalizable: targetUnlocalizable, ...targetData } = await bucketLoader.pull(targetLocale);
10134
- const missingKeys = _31.difference(
10042
+ const missingKeys = _32.difference(
10135
10043
  Object.keys(sourceData),
10136
10044
  Object.keys(targetData)
10137
10045
  );
10138
- const extraKeys = _31.difference(
10046
+ const extraKeys = _32.difference(
10139
10047
  Object.keys(targetData),
10140
10048
  Object.keys(sourceData)
10141
10049
  );
10142
- const unlocalizableDataDiff = !_31.isEqual(
10050
+ const unlocalizableDataDiff = !_32.isEqual(
10143
10051
  sourceUnlocalizable,
10144
10052
  targetUnlocalizable
10145
10053
  );
@@ -10223,13 +10131,13 @@ var i18n_default = new Command14().command("i18n").description(
10223
10131
  targetData,
10224
10132
  checksums: checksums2
10225
10133
  });
10226
- let processableData = _31.chain(sourceData).entries().filter(
10134
+ let processableData = _32.chain(sourceData).entries().filter(
10227
10135
  ([key, value]) => delta.added.includes(key) || delta.updated.includes(key) || !!flags.force
10228
10136
  ).fromPairs().value();
10229
10137
  if (flags.key) {
10230
- processableData = _31.pickBy(
10138
+ processableData = _32.pickBy(
10231
10139
  processableData,
10232
- (_36, key) => key === flags.key
10140
+ (_37, key) => key === flags.key
10233
10141
  );
10234
10142
  }
10235
10143
  if (flags.verbose) {
@@ -10262,13 +10170,13 @@ var i18n_default = new Command14().command("i18n").description(
10262
10170
  if (flags.verbose) {
10263
10171
  bucketOra.info(JSON.stringify(processedTargetData, null, 2));
10264
10172
  }
10265
- let finalTargetData = _31.merge(
10173
+ let finalTargetData = _32.merge(
10266
10174
  {},
10267
10175
  sourceData,
10268
10176
  targetData,
10269
10177
  processedTargetData
10270
10178
  );
10271
- finalTargetData = _31.chain(finalTargetData).entries().map(([key, value]) => {
10179
+ finalTargetData = _32.chain(finalTargetData).entries().map(([key, value]) => {
10272
10180
  const renaming = delta.renamed.find(
10273
10181
  ([oldKey, newKey]) => oldKey === key
10274
10182
  );
@@ -10292,13 +10200,10 @@ var i18n_default = new Command14().command("i18n").description(
10292
10200
  `Applying changes to ${bucketPath} (${targetLocale})`
10293
10201
  );
10294
10202
  }
10295
- const finalDiffSize = _31.chain(finalTargetData).omitBy((value, key) => {
10203
+ const finalDiffSize = _32.chain(finalTargetData).omitBy((value, key) => {
10296
10204
  const targetValue = targetData[key];
10297
- if (isICUPluralObject(value) && isICUPluralObject(targetValue)) {
10298
- return _31.isEqual(
10299
- { icu: value.icu, _meta: value._meta },
10300
- { icu: targetValue.icu, _meta: targetValue._meta }
10301
- );
10205
+ if (typeof value === "object" && value !== null) {
10206
+ return _32.isEqual(value, targetValue);
10302
10207
  }
10303
10208
  return value === targetValue;
10304
10209
  }).size().value();
@@ -10532,7 +10437,7 @@ Reviewing changes for ${chalk6.blue(args.pathPattern)} (${chalk6.yellow(
10532
10437
  return args.currentData;
10533
10438
  }
10534
10439
  const customData = { ...args.currentData };
10535
- const changes = _31.reduce(
10440
+ const changes = _32.reduce(
10536
10441
  args.proposedData,
10537
10442
  (result, value, key) => {
10538
10443
  if (args.currentData[key] !== value) {
@@ -10605,7 +10510,7 @@ import path16 from "path";
10605
10510
  import Z4 from "zod";
10606
10511
  import YAML6 from "yaml";
10607
10512
  import { MD5 as MD52 } from "object-hash";
10608
- import _32 from "lodash";
10513
+ import _33 from "lodash";
10609
10514
  function createLockfileHelper() {
10610
10515
  return {
10611
10516
  isLockfileExists: () => {
@@ -10615,18 +10520,18 @@ function createLockfileHelper() {
10615
10520
  registerSourceData: (pathPattern, sourceData) => {
10616
10521
  const lockfile = _loadLockfile();
10617
10522
  const sectionKey = MD52(pathPattern);
10618
- const sectionChecksums = _32.mapValues(sourceData, (value) => MD52(value));
10523
+ const sectionChecksums = _33.mapValues(sourceData, (value) => MD52(value));
10619
10524
  lockfile.checksums[sectionKey] = sectionChecksums;
10620
10525
  _saveLockfile(lockfile);
10621
10526
  },
10622
10527
  registerPartialSourceData: (pathPattern, partialSourceData) => {
10623
10528
  const lockfile = _loadLockfile();
10624
10529
  const sectionKey = MD52(pathPattern);
10625
- const sectionChecksums = _32.mapValues(
10530
+ const sectionChecksums = _33.mapValues(
10626
10531
  partialSourceData,
10627
10532
  (value) => MD52(value)
10628
10533
  );
10629
- lockfile.checksums[sectionKey] = _32.merge(
10534
+ lockfile.checksums[sectionKey] = _33.merge(
10630
10535
  {},
10631
10536
  lockfile.checksums[sectionKey] ?? {},
10632
10537
  sectionChecksums
@@ -10636,9 +10541,9 @@ function createLockfileHelper() {
10636
10541
  extractUpdatedData: (pathPattern, sourceData) => {
10637
10542
  const lockfile = _loadLockfile();
10638
10543
  const sectionKey = MD52(pathPattern);
10639
- const currentChecksums = _32.mapValues(sourceData, (value) => MD52(value));
10544
+ const currentChecksums = _33.mapValues(sourceData, (value) => MD52(value));
10640
10545
  const savedChecksums = lockfile.checksums[sectionKey] || {};
10641
- const updatedData = _32.pickBy(
10546
+ const updatedData = _33.pickBy(
10642
10547
  sourceData,
10643
10548
  (value, key) => savedChecksums[key] !== currentChecksums[key]
10644
10549
  );
@@ -10731,7 +10636,7 @@ var flagsSchema = Z5.object({
10731
10636
  // src/cli/cmd/cleanup.ts
10732
10637
  import { resolveOverriddenLocale as resolveOverriddenLocale6 } from "@lingo.dev/_spec";
10733
10638
  import { Command as Command16 } from "interactive-commander";
10734
- import _33 from "lodash";
10639
+ import _34 from "lodash";
10735
10640
  import Ora11 from "ora";
10736
10641
  var cleanup_default = new Command16().command("cleanup").description(
10737
10642
  "Remove translation keys from target locales that no longer exist in the source locale"
@@ -10795,7 +10700,7 @@ var cleanup_default = new Command16().command("cleanup").description(
10795
10700
  try {
10796
10701
  const targetData = await bucketLoader.pull(targetLocale);
10797
10702
  const targetKeys = Object.keys(targetData);
10798
- const keysToRemove = _33.difference(targetKeys, sourceKeys);
10703
+ const keysToRemove = _34.difference(targetKeys, sourceKeys);
10799
10704
  if (keysToRemove.length === 0) {
10800
10705
  bucketOra.succeed(`[${targetLocale}] No keys to remove`);
10801
10706
  continue;
@@ -10810,7 +10715,7 @@ var cleanup_default = new Command16().command("cleanup").description(
10810
10715
  );
10811
10716
  }
10812
10717
  if (!options.dryRun) {
10813
- const cleanedData = _33.pick(targetData, sourceKeys);
10718
+ const cleanedData = _34.pick(targetData, sourceKeys);
10814
10719
  await bucketLoader.push(targetLocale, cleanedData);
10815
10720
  bucketOra.succeed(
10816
10721
  `[${targetLocale}] Removed ${keysToRemove.length} keys`
@@ -10873,7 +10778,7 @@ import Z6 from "zod";
10873
10778
  import { ReplexicaEngine } from "@lingo.dev/_sdk";
10874
10779
  var mcp_default = new Command17().command("mcp").description(
10875
10780
  "Start a Model Context Protocol (MCP) server for AI assistant integration"
10876
- ).helpOption("-h, --help", "Show help").action(async (_36, program) => {
10781
+ ).helpOption("-h, --help", "Show help").action(async (_37, program) => {
10877
10782
  const apiKey = program.args[0];
10878
10783
  const settings = getSettings(apiKey);
10879
10784
  if (!settings.auth.apiKey) {
@@ -11459,7 +11364,7 @@ async function plan(input2) {
11459
11364
  import chalk12 from "chalk";
11460
11365
  import { Listr as Listr3 } from "listr2";
11461
11366
  import pLimit from "p-limit";
11462
- import _34 from "lodash";
11367
+ import _35 from "lodash";
11463
11368
  var MAX_WORKER_COUNT = 10;
11464
11369
  async function execute(input2) {
11465
11370
  const effectiveConcurrency = Math.min(
@@ -11489,7 +11394,7 @@ async function execute(input2) {
11489
11394
  return;
11490
11395
  }
11491
11396
  const initialChecksumsMap = /* @__PURE__ */ new Map();
11492
- const uniqueBucketPatterns = _34.uniq(
11397
+ const uniqueBucketPatterns = _35.uniq(
11493
11398
  ctx.tasks.map((t2) => t2.bucketPathPattern)
11494
11399
  );
11495
11400
  for (const bucketPathPattern of uniqueBucketPatterns) {
@@ -11511,7 +11416,7 @@ async function execute(input2) {
11511
11416
  const workerTasks = [];
11512
11417
  for (let i = 0; i < workersCount; i++) {
11513
11418
  const assignedTasks = ctx.tasks.filter(
11514
- (_36, idx) => idx % workersCount === i
11419
+ (_37, idx) => idx % workersCount === i
11515
11420
  );
11516
11421
  workerTasks.push(
11517
11422
  createWorkerTask({
@@ -11621,7 +11526,7 @@ function createWorkerTask(args) {
11621
11526
  targetData,
11622
11527
  checksums: initialChecksums
11623
11528
  });
11624
- const processableData = _34.chain(sourceData).entries().filter(
11529
+ const processableData = _35.chain(sourceData).entries().filter(
11625
11530
  ([key, value]) => delta.added.includes(key) || delta.updated.includes(key) || !!args.ctx.flags.force
11626
11531
  ).filter(
11627
11532
  ([key]) => !assignedTask.onlyKeys.length || assignedTask.onlyKeys?.some(
@@ -11639,7 +11544,7 @@ function createWorkerTask(args) {
11639
11544
  targetLocale: assignedTask.targetLocale
11640
11545
  };
11641
11546
  }
11642
- const relevantHints = _34.pick(hints, Object.keys(processableData));
11547
+ const relevantHints = _35.pick(hints, Object.keys(processableData));
11643
11548
  const processedTargetData = await args.ctx.localizer.localize(
11644
11549
  {
11645
11550
  sourceLocale: assignedTask.sourceLocale,
@@ -11655,7 +11560,7 @@ function createWorkerTask(args) {
11655
11560
  const latestTargetData = await bucketLoader.pull(
11656
11561
  assignedTask.targetLocale
11657
11562
  );
11658
- const _partialData = _34.merge(
11563
+ const _partialData = _35.merge(
11659
11564
  {},
11660
11565
  latestTargetData,
11661
11566
  processedChunk
@@ -11675,7 +11580,7 @@ function createWorkerTask(args) {
11675
11580
  });
11676
11581
  }
11677
11582
  );
11678
- const finalTargetData = _34.merge(
11583
+ const finalTargetData = _35.merge(
11679
11584
  {},
11680
11585
  sourceData,
11681
11586
  targetData,
@@ -11724,7 +11629,7 @@ function countTasks(ctx, predicate) {
11724
11629
  ).length;
11725
11630
  }
11726
11631
  function processRenamedKeys(delta, targetData) {
11727
- return _34.chain(targetData).entries().map(([key, value]) => {
11632
+ return _35.chain(targetData).entries().map(([key, value]) => {
11728
11633
  const renaming = delta.renamed.find(([oldKey]) => oldKey === key);
11729
11634
  if (!renaming) {
11730
11635
  return [key, value];
@@ -11892,7 +11797,7 @@ var flagsSchema2 = z2.object({
11892
11797
  // src/cli/cmd/run/frozen.ts
11893
11798
  import chalk14 from "chalk";
11894
11799
  import { Listr as Listr4 } from "listr2";
11895
- import _35 from "lodash";
11800
+ import _36 from "lodash";
11896
11801
  import { resolveOverriddenLocale as resolveOverriddenLocale8 } from "@lingo.dev/_spec";
11897
11802
  async function frozen(input2) {
11898
11803
  console.log(chalk14.hex(colors.orange)("[Frozen]"));
@@ -11980,7 +11885,7 @@ async function frozen(input2) {
11980
11885
  const delta = createDeltaProcessor(bucketPath.pathPattern);
11981
11886
  const sourceChecksums = await delta.createChecksums(src);
11982
11887
  const savedChecksums = await delta.loadChecksums();
11983
- const updatedSourceData = _35.pickBy(
11888
+ const updatedSourceData = _36.pickBy(
11984
11889
  src,
11985
11890
  (value, key) => sourceChecksums[key] !== savedChecksums[key]
11986
11891
  );
@@ -11995,7 +11900,7 @@ async function frozen(input2) {
11995
11900
  bucketPath.delimiter
11996
11901
  );
11997
11902
  const { unlocalizable: tgtUnlocalizable, ...tgt } = await loader.pull(resolvedTargetLocale);
11998
- const missingKeys = _35.difference(
11903
+ const missingKeys = _36.difference(
11999
11904
  Object.keys(src),
12000
11905
  Object.keys(tgt)
12001
11906
  );
@@ -12004,7 +11909,7 @@ async function frozen(input2) {
12004
11909
  `Localization data has changed; please update i18n.lock or run without --frozen. Details: Target file is missing translations.`
12005
11910
  );
12006
11911
  }
12007
- const extraKeys = _35.difference(
11912
+ const extraKeys = _36.difference(
12008
11913
  Object.keys(tgt),
12009
11914
  Object.keys(src)
12010
11915
  );
@@ -12013,7 +11918,7 @@ async function frozen(input2) {
12013
11918
  `Localization data has changed; please update i18n.lock or run without --frozen. Details: Target file has extra translations not present in the source file.`
12014
11919
  );
12015
11920
  }
12016
- const unlocalizableDataDiff = !_35.isEqual(
11921
+ const unlocalizableDataDiff = !_36.isEqual(
12017
11922
  srcUnlocalizable,
12018
11923
  tgtUnlocalizable
12019
11924
  );
@@ -13556,7 +13461,7 @@ async function renderHero2() {
13556
13461
  // package.json
13557
13462
  var package_default = {
13558
13463
  name: "lingo.dev",
13559
- version: "0.116.2",
13464
+ version: "0.116.4",
13560
13465
  description: "Lingo.dev CLI",
13561
13466
  private: false,
13562
13467
  publishConfig: {