lingo.dev 0.74.12 → 0.74.13
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.cjs +114 -52
- package/build/cli.cjs.map +1 -1
- package/build/cli.mjs +175 -113
- package/build/cli.mjs.map +1 -1
- package/package.json +2 -1
package/build/cli.mjs
CHANGED
|
@@ -580,7 +580,7 @@ import { bucketTypeSchema, localeCodeSchema, resolveOverridenLocale as resolveOv
|
|
|
580
580
|
import { ReplexicaEngine } from "@lingo.dev/_sdk";
|
|
581
581
|
import { Command as Command6 } from "interactive-commander";
|
|
582
582
|
import Z4 from "zod";
|
|
583
|
-
import
|
|
583
|
+
import _18 from "lodash";
|
|
584
584
|
import Ora5 from "ora";
|
|
585
585
|
|
|
586
586
|
// src/cli/loaders/_utils.ts
|
|
@@ -682,26 +682,87 @@ function createJsonLoader() {
|
|
|
682
682
|
|
|
683
683
|
// src/cli/loaders/flat.ts
|
|
684
684
|
import { flatten, unflatten } from "flat";
|
|
685
|
+
import _5 from "lodash";
|
|
686
|
+
var OBJECT_NUMERIC_KEY_PREFIX = "__lingodotdev__obj__";
|
|
685
687
|
function createFlatLoader() {
|
|
688
|
+
let denormalizedKeysMap = {};
|
|
686
689
|
return createLoader({
|
|
687
690
|
pull: async (locale, input) => {
|
|
688
|
-
|
|
691
|
+
const denormalized = denormalizeObjectKeys(input || {});
|
|
692
|
+
const flattened = flatten(denormalized, {
|
|
689
693
|
delimiter: "/",
|
|
690
694
|
transformKey(key) {
|
|
691
695
|
return encodeURIComponent(String(key));
|
|
692
696
|
}
|
|
693
697
|
});
|
|
698
|
+
denormalizedKeysMap = { ...denormalizedKeysMap, ...buildDenormalizedKeysMap(flattened) };
|
|
699
|
+
const normalized = normalizeObjectKeys(flattened);
|
|
700
|
+
return normalized;
|
|
694
701
|
},
|
|
695
702
|
push: async (locale, data) => {
|
|
696
|
-
|
|
703
|
+
const denormalized = mapDenormalizedKeys(data, denormalizedKeysMap);
|
|
704
|
+
const unflattened = unflatten(denormalized || {}, {
|
|
697
705
|
delimiter: "/",
|
|
698
706
|
transformKey(key) {
|
|
699
707
|
return decodeURIComponent(String(key));
|
|
700
708
|
}
|
|
701
709
|
});
|
|
710
|
+
const normalized = normalizeObjectKeys(unflattened);
|
|
711
|
+
return normalized;
|
|
702
712
|
}
|
|
703
713
|
});
|
|
704
714
|
}
|
|
715
|
+
function buildDenormalizedKeysMap(obj) {
|
|
716
|
+
if (!obj) return {};
|
|
717
|
+
return Object.keys(obj).reduce(
|
|
718
|
+
(acc, key) => {
|
|
719
|
+
if (key) {
|
|
720
|
+
const normalizedKey = `${key}`.replace(OBJECT_NUMERIC_KEY_PREFIX, "");
|
|
721
|
+
acc[normalizedKey] = key;
|
|
722
|
+
}
|
|
723
|
+
return acc;
|
|
724
|
+
},
|
|
725
|
+
{}
|
|
726
|
+
);
|
|
727
|
+
}
|
|
728
|
+
function mapDenormalizedKeys(obj, denormalizedKeysMap) {
|
|
729
|
+
return Object.keys(obj).reduce(
|
|
730
|
+
(acc, key) => {
|
|
731
|
+
const denormalizedKey = denormalizedKeysMap[key];
|
|
732
|
+
acc[denormalizedKey] = obj[key];
|
|
733
|
+
return acc;
|
|
734
|
+
},
|
|
735
|
+
{}
|
|
736
|
+
);
|
|
737
|
+
}
|
|
738
|
+
function denormalizeObjectKeys(obj) {
|
|
739
|
+
if (_5.isObject(obj) && !_5.isArray(obj)) {
|
|
740
|
+
return _5.transform(
|
|
741
|
+
obj,
|
|
742
|
+
(result, value, key) => {
|
|
743
|
+
const newKey = !isNaN(Number(key)) ? `${OBJECT_NUMERIC_KEY_PREFIX}${key}` : key;
|
|
744
|
+
result[newKey] = _5.isObject(value) ? denormalizeObjectKeys(value) : value;
|
|
745
|
+
},
|
|
746
|
+
{}
|
|
747
|
+
);
|
|
748
|
+
} else {
|
|
749
|
+
return obj;
|
|
750
|
+
}
|
|
751
|
+
}
|
|
752
|
+
function normalizeObjectKeys(obj) {
|
|
753
|
+
if (_5.isObject(obj) && !_5.isArray(obj)) {
|
|
754
|
+
return _5.transform(
|
|
755
|
+
obj,
|
|
756
|
+
(result, value, key) => {
|
|
757
|
+
const newKey = `${key}`.replace(OBJECT_NUMERIC_KEY_PREFIX, "");
|
|
758
|
+
result[newKey] = _5.isObject(value) ? normalizeObjectKeys(value) : value;
|
|
759
|
+
},
|
|
760
|
+
{}
|
|
761
|
+
);
|
|
762
|
+
} else {
|
|
763
|
+
return obj;
|
|
764
|
+
}
|
|
765
|
+
}
|
|
705
766
|
|
|
706
767
|
// src/cli/loaders/text-file.ts
|
|
707
768
|
import fs5 from "fs/promises";
|
|
@@ -713,7 +774,7 @@ function createTextFileLoader(pathPattern) {
|
|
|
713
774
|
const trimmedResult = result.trim();
|
|
714
775
|
return trimmedResult;
|
|
715
776
|
},
|
|
716
|
-
async push(locale, data,
|
|
777
|
+
async push(locale, data, _20, originalLocale) {
|
|
717
778
|
const draftPath = pathPattern.replace("[locale]", locale);
|
|
718
779
|
const finalPath = path6.resolve(draftPath);
|
|
719
780
|
const dirPath = path6.dirname(finalPath);
|
|
@@ -782,15 +843,15 @@ function createRootKeyLoader(replaceAll = false) {
|
|
|
782
843
|
}
|
|
783
844
|
|
|
784
845
|
// src/cli/loaders/flutter.ts
|
|
785
|
-
import
|
|
846
|
+
import _6 from "lodash";
|
|
786
847
|
function createFlutterLoader() {
|
|
787
848
|
return createLoader({
|
|
788
849
|
async pull(locale, input) {
|
|
789
|
-
const result =
|
|
850
|
+
const result = _6.pickBy(input, (value, key) => !key.startsWith("@"));
|
|
790
851
|
return result;
|
|
791
852
|
},
|
|
792
853
|
async push(locale, data, originalInput) {
|
|
793
|
-
const result =
|
|
854
|
+
const result = _6.merge({}, originalInput, { "@@locale": locale }, data);
|
|
794
855
|
return result;
|
|
795
856
|
}
|
|
796
857
|
});
|
|
@@ -892,7 +953,7 @@ function createAndroidLoader() {
|
|
|
892
953
|
// src/cli/loaders/csv.ts
|
|
893
954
|
import { parse } from "csv-parse/sync";
|
|
894
955
|
import { stringify } from "csv-stringify/sync";
|
|
895
|
-
import
|
|
956
|
+
import _7 from "lodash";
|
|
896
957
|
function createCsvLoader() {
|
|
897
958
|
return createLoader({
|
|
898
959
|
async pull(locale, _input) {
|
|
@@ -900,7 +961,7 @@ function createCsvLoader() {
|
|
|
900
961
|
columns: true
|
|
901
962
|
});
|
|
902
963
|
const result = {};
|
|
903
|
-
|
|
964
|
+
_7.forEach(input, (row) => {
|
|
904
965
|
const key = row.id;
|
|
905
966
|
if (key && row[locale]) {
|
|
906
967
|
result[key] = row[locale];
|
|
@@ -1118,7 +1179,7 @@ function createPropertiesLoader() {
|
|
|
1118
1179
|
return result;
|
|
1119
1180
|
},
|
|
1120
1181
|
async push(locale, payload) {
|
|
1121
|
-
const result = Object.entries(payload).filter(([
|
|
1182
|
+
const result = Object.entries(payload).filter(([_20, value]) => value != null).map(([key, value]) => `${key}=${value}`).join("\n");
|
|
1122
1183
|
return result;
|
|
1123
1184
|
}
|
|
1124
1185
|
});
|
|
@@ -1204,7 +1265,7 @@ function createXcodeStringsdictLoader() {
|
|
|
1204
1265
|
}
|
|
1205
1266
|
|
|
1206
1267
|
// src/cli/loaders/xcode-xcstrings.ts
|
|
1207
|
-
import
|
|
1268
|
+
import _8 from "lodash";
|
|
1208
1269
|
function createXcodeXcstringsLoader() {
|
|
1209
1270
|
return createLoader({
|
|
1210
1271
|
async pull(locale, input) {
|
|
@@ -1268,7 +1329,7 @@ function createXcodeXcstringsLoader() {
|
|
|
1268
1329
|
};
|
|
1269
1330
|
}
|
|
1270
1331
|
}
|
|
1271
|
-
const result =
|
|
1332
|
+
const result = _8.merge({}, originalInput, langDataToMerge);
|
|
1272
1333
|
return result;
|
|
1273
1334
|
}
|
|
1274
1335
|
});
|
|
@@ -1310,17 +1371,17 @@ async function loadPrettierConfig() {
|
|
|
1310
1371
|
}
|
|
1311
1372
|
|
|
1312
1373
|
// src/cli/loaders/unlocalizable.ts
|
|
1313
|
-
import
|
|
1374
|
+
import _9 from "lodash";
|
|
1314
1375
|
import _isUrl from "is-url";
|
|
1315
1376
|
import { isValid, parseISO } from "date-fns";
|
|
1316
1377
|
function createUnlocalizableLoader() {
|
|
1317
1378
|
const rules = {
|
|
1318
|
-
isEmpty: (v) =>
|
|
1319
|
-
isNumber: (v) => !
|
|
1320
|
-
isBoolean: (v) =>
|
|
1321
|
-
isIsoDate: (v) =>
|
|
1322
|
-
isSystemId: (v) =>
|
|
1323
|
-
isUrl: (v) =>
|
|
1379
|
+
isEmpty: (v) => _9.isEmpty(v),
|
|
1380
|
+
isNumber: (v) => !_9.isNaN(_9.toNumber(v)),
|
|
1381
|
+
isBoolean: (v) => _9.isBoolean(v),
|
|
1382
|
+
isIsoDate: (v) => _9.isString(v) && _isIsoDate(v),
|
|
1383
|
+
isSystemId: (v) => _9.isString(v) && _isSystemId(v),
|
|
1384
|
+
isUrl: (v) => _9.isString(v) && _isUrl(v)
|
|
1324
1385
|
};
|
|
1325
1386
|
return createLoader({
|
|
1326
1387
|
async pull(locale, input) {
|
|
@@ -1331,12 +1392,12 @@ function createUnlocalizableLoader() {
|
|
|
1331
1392
|
}
|
|
1332
1393
|
}
|
|
1333
1394
|
return false;
|
|
1334
|
-
}).map(([key,
|
|
1335
|
-
const result =
|
|
1395
|
+
}).map(([key, _20]) => key);
|
|
1396
|
+
const result = _9.omitBy(input, (_20, key) => passthroughKeys.includes(key));
|
|
1336
1397
|
return result;
|
|
1337
1398
|
},
|
|
1338
1399
|
async push(locale, data, originalInput) {
|
|
1339
|
-
const result =
|
|
1400
|
+
const result = _9.merge({}, originalInput, data);
|
|
1340
1401
|
return result;
|
|
1341
1402
|
}
|
|
1342
1403
|
});
|
|
@@ -1349,7 +1410,7 @@ function _isIsoDate(v) {
|
|
|
1349
1410
|
}
|
|
1350
1411
|
|
|
1351
1412
|
// src/cli/loaders/po/index.ts
|
|
1352
|
-
import
|
|
1413
|
+
import _10 from "lodash";
|
|
1353
1414
|
import gettextParser from "gettext-parser";
|
|
1354
1415
|
function createPoLoader(params = { multiline: false }) {
|
|
1355
1416
|
return composeLoaders(createPoDataLoader(params), createPoContentLoader());
|
|
@@ -1362,7 +1423,7 @@ function createPoDataLoader(params) {
|
|
|
1362
1423
|
const sections = input.split("\n\n").filter(Boolean);
|
|
1363
1424
|
for (const section of sections) {
|
|
1364
1425
|
const sectionPo = gettextParser.po.parse(section);
|
|
1365
|
-
const contextKey =
|
|
1426
|
+
const contextKey = _10.keys(sectionPo.translations)[0];
|
|
1366
1427
|
const entries = sectionPo.translations[contextKey];
|
|
1367
1428
|
Object.entries(entries).forEach(([msgid, entry]) => {
|
|
1368
1429
|
if (msgid && entry.msgid) {
|
|
@@ -1380,12 +1441,12 @@ function createPoDataLoader(params) {
|
|
|
1380
1441
|
const sections = originalInput?.split("\n\n").filter(Boolean) || [];
|
|
1381
1442
|
const result = sections.map((section) => {
|
|
1382
1443
|
const sectionPo = gettextParser.po.parse(section);
|
|
1383
|
-
const contextKey =
|
|
1444
|
+
const contextKey = _10.keys(sectionPo.translations)[0];
|
|
1384
1445
|
const entries = sectionPo.translations[contextKey];
|
|
1385
1446
|
const msgid = Object.keys(entries).find((key) => entries[key].msgid);
|
|
1386
1447
|
if (!msgid) return section;
|
|
1387
1448
|
if (data[msgid]) {
|
|
1388
|
-
const updatedPo =
|
|
1449
|
+
const updatedPo = _10.merge({}, sectionPo, {
|
|
1389
1450
|
translations: {
|
|
1390
1451
|
[contextKey]: {
|
|
1391
1452
|
[msgid]: {
|
|
@@ -1405,7 +1466,7 @@ function createPoDataLoader(params) {
|
|
|
1405
1466
|
function createPoContentLoader() {
|
|
1406
1467
|
return createLoader({
|
|
1407
1468
|
async pull(locale, input) {
|
|
1408
|
-
const result =
|
|
1469
|
+
const result = _10.chain(input).entries().filter(([, entry]) => !!entry.msgid).map(([, entry]) => [
|
|
1409
1470
|
entry.msgid,
|
|
1410
1471
|
{
|
|
1411
1472
|
singular: entry.msgstr[0] || entry.msgid,
|
|
@@ -1415,7 +1476,7 @@ function createPoContentLoader() {
|
|
|
1415
1476
|
return result;
|
|
1416
1477
|
},
|
|
1417
1478
|
async push(locale, data, originalInput) {
|
|
1418
|
-
const result =
|
|
1479
|
+
const result = _10.chain(originalInput).entries().map(([, entry]) => [
|
|
1419
1480
|
entry.msgid,
|
|
1420
1481
|
{
|
|
1421
1482
|
...entry,
|
|
@@ -1538,34 +1599,34 @@ var datoSettingsSchema = Z2.object({
|
|
|
1538
1599
|
});
|
|
1539
1600
|
|
|
1540
1601
|
// src/cli/loaders/dato/filter.ts
|
|
1541
|
-
import
|
|
1602
|
+
import _11 from "lodash";
|
|
1542
1603
|
function createDatoFilterLoader() {
|
|
1543
1604
|
return createLoader({
|
|
1544
1605
|
async pull(locale, input) {
|
|
1545
1606
|
const result = {};
|
|
1546
|
-
for (const [modelId, modelInfo] of
|
|
1607
|
+
for (const [modelId, modelInfo] of _11.entries(input)) {
|
|
1547
1608
|
result[modelId] = {};
|
|
1548
1609
|
for (const record of modelInfo.records) {
|
|
1549
|
-
result[modelId][record.id] =
|
|
1610
|
+
result[modelId][record.id] = _11.chain(modelInfo.fields).mapKeys((field) => field.api_key).mapValues((field) => _11.get(record, [field.api_key, locale])).value();
|
|
1550
1611
|
}
|
|
1551
1612
|
}
|
|
1552
1613
|
return result;
|
|
1553
1614
|
},
|
|
1554
1615
|
async push(locale, data, originalInput, originalLocale) {
|
|
1555
|
-
const result =
|
|
1556
|
-
for (const [modelId, modelInfo] of
|
|
1616
|
+
const result = _11.cloneDeep(originalInput || {});
|
|
1617
|
+
for (const [modelId, modelInfo] of _11.entries(result)) {
|
|
1557
1618
|
for (const record of modelInfo.records) {
|
|
1558
|
-
for (const [fieldId, fieldValue] of
|
|
1619
|
+
for (const [fieldId, fieldValue] of _11.entries(record)) {
|
|
1559
1620
|
const fieldInfo = modelInfo.fields.find((field) => field.api_key === fieldId);
|
|
1560
1621
|
if (fieldInfo) {
|
|
1561
|
-
const sourceFieldValue =
|
|
1562
|
-
const targetFieldValue =
|
|
1622
|
+
const sourceFieldValue = _11.get(fieldValue, [originalLocale]);
|
|
1623
|
+
const targetFieldValue = _11.get(data, [modelId, record.id, fieldId]);
|
|
1563
1624
|
if (targetFieldValue) {
|
|
1564
|
-
|
|
1625
|
+
_11.set(record, [fieldId, locale], targetFieldValue);
|
|
1565
1626
|
} else {
|
|
1566
|
-
|
|
1627
|
+
_11.set(record, [fieldId, locale], sourceFieldValue);
|
|
1567
1628
|
}
|
|
1568
|
-
|
|
1629
|
+
_11.chain(fieldValue).keys().reject((loc) => loc === locale || loc === originalLocale).filter((loc) => _11.isEmpty(_11.get(fieldValue, [loc]))).forEach((loc) => _11.set(record, [fieldId, loc], sourceFieldValue)).value();
|
|
1569
1630
|
}
|
|
1570
1631
|
}
|
|
1571
1632
|
}
|
|
@@ -1576,10 +1637,10 @@ function createDatoFilterLoader() {
|
|
|
1576
1637
|
}
|
|
1577
1638
|
|
|
1578
1639
|
// src/cli/loaders/dato/api.ts
|
|
1579
|
-
import
|
|
1640
|
+
import _13 from "lodash";
|
|
1580
1641
|
|
|
1581
1642
|
// src/cli/loaders/dato/_utils.ts
|
|
1582
|
-
import
|
|
1643
|
+
import _12 from "lodash";
|
|
1583
1644
|
import { buildClient } from "@datocms/cma-client-node";
|
|
1584
1645
|
function createDatoClient(params) {
|
|
1585
1646
|
if (!params.apiKey) {
|
|
@@ -1754,7 +1815,7 @@ function createDatoApiLoader(config, onConfigUpdate) {
|
|
|
1754
1815
|
const result = {
|
|
1755
1816
|
models: {}
|
|
1756
1817
|
};
|
|
1757
|
-
const updatedConfig =
|
|
1818
|
+
const updatedConfig = _13.cloneDeep(config);
|
|
1758
1819
|
console.log(`Initializing DatoCMS loader...`);
|
|
1759
1820
|
const project = await dato.findProject();
|
|
1760
1821
|
const modelChoices = await getModelChoices(dato, config);
|
|
@@ -1772,7 +1833,7 @@ function createDatoApiLoader(config, onConfigUpdate) {
|
|
|
1772
1833
|
delete updatedConfig.models[modelId];
|
|
1773
1834
|
}
|
|
1774
1835
|
}
|
|
1775
|
-
for (const modelId of
|
|
1836
|
+
for (const modelId of _13.keys(updatedConfig.models)) {
|
|
1776
1837
|
const { modelName, fields } = await getModelFields(dato, modelId);
|
|
1777
1838
|
if (fields.length > 0) {
|
|
1778
1839
|
result.models[modelId] = { fields: [], records: [] };
|
|
@@ -1783,7 +1844,7 @@ function createDatoApiLoader(config, onConfigUpdate) {
|
|
|
1783
1844
|
const isLocalized = await updateFieldLocalization(dato, fieldInfo, selectedFields.includes(fieldInfo.id));
|
|
1784
1845
|
if (isLocalized) {
|
|
1785
1846
|
result.models[modelId].fields.push(fieldInfo);
|
|
1786
|
-
updatedConfig.models[modelId].fields =
|
|
1847
|
+
updatedConfig.models[modelId].fields = _13.uniq([
|
|
1787
1848
|
...updatedConfig.models[modelId].fields || [],
|
|
1788
1849
|
fieldInfo.api_key
|
|
1789
1850
|
]);
|
|
@@ -1802,7 +1863,7 @@ function createDatoApiLoader(config, onConfigUpdate) {
|
|
|
1802
1863
|
},
|
|
1803
1864
|
async pull(locale, input, initCtx) {
|
|
1804
1865
|
const result = {};
|
|
1805
|
-
for (const modelId of
|
|
1866
|
+
for (const modelId of _13.keys(initCtx?.models || {})) {
|
|
1806
1867
|
let records = initCtx?.models[modelId].records || [];
|
|
1807
1868
|
const recordIds = records.map((record) => record.id);
|
|
1808
1869
|
records = await dato.findRecords(recordIds);
|
|
@@ -1817,7 +1878,7 @@ function createDatoApiLoader(config, onConfigUpdate) {
|
|
|
1817
1878
|
return result;
|
|
1818
1879
|
},
|
|
1819
1880
|
async push(locale, data, originalInput) {
|
|
1820
|
-
for (const modelId of
|
|
1881
|
+
for (const modelId of _13.keys(data)) {
|
|
1821
1882
|
for (let i = 0; i < data[modelId].records.length; i++) {
|
|
1822
1883
|
const record = data[modelId].records[i];
|
|
1823
1884
|
console.log(`Updating record ${i + 1}/${data[modelId].records.length} for model ${modelId}...`);
|
|
@@ -1831,7 +1892,7 @@ async function getModelFields(dato, modelId) {
|
|
|
1831
1892
|
const modelInfo = await dato.findModel(modelId);
|
|
1832
1893
|
return {
|
|
1833
1894
|
modelName: modelInfo.name,
|
|
1834
|
-
fields:
|
|
1895
|
+
fields: _13.filter(modelInfo.fields, (field) => field.type === "field")
|
|
1835
1896
|
};
|
|
1836
1897
|
}
|
|
1837
1898
|
async function getFieldDetails(dato, fields) {
|
|
@@ -1909,17 +1970,17 @@ async function promptModelSelection(choices) {
|
|
|
1909
1970
|
}
|
|
1910
1971
|
|
|
1911
1972
|
// src/cli/loaders/dato/extract.ts
|
|
1912
|
-
import
|
|
1973
|
+
import _14 from "lodash";
|
|
1913
1974
|
function createDatoExtractLoader() {
|
|
1914
1975
|
return createLoader({
|
|
1915
1976
|
async pull(locale, input) {
|
|
1916
1977
|
const result = {};
|
|
1917
|
-
for (const [modelId, modelInfo] of
|
|
1918
|
-
for (const [recordId, record] of
|
|
1919
|
-
for (const [fieldName, fieldValue] of
|
|
1978
|
+
for (const [modelId, modelInfo] of _14.entries(input)) {
|
|
1979
|
+
for (const [recordId, record] of _14.entries(modelInfo)) {
|
|
1980
|
+
for (const [fieldName, fieldValue] of _14.entries(record)) {
|
|
1920
1981
|
const parsedValue = createParsedDatoValue(fieldValue);
|
|
1921
1982
|
if (parsedValue) {
|
|
1922
|
-
|
|
1983
|
+
_14.set(result, [modelId, `_${recordId}`, fieldName], parsedValue);
|
|
1923
1984
|
}
|
|
1924
1985
|
}
|
|
1925
1986
|
}
|
|
@@ -1927,14 +1988,14 @@ function createDatoExtractLoader() {
|
|
|
1927
1988
|
return result;
|
|
1928
1989
|
},
|
|
1929
1990
|
async push(locale, data, originalInput) {
|
|
1930
|
-
const result =
|
|
1931
|
-
for (const [modelId, modelInfo] of
|
|
1932
|
-
for (const [virtualRecordId, record] of
|
|
1933
|
-
for (const [fieldName, fieldValue] of
|
|
1991
|
+
const result = _14.cloneDeep(originalInput || {});
|
|
1992
|
+
for (const [modelId, modelInfo] of _14.entries(data)) {
|
|
1993
|
+
for (const [virtualRecordId, record] of _14.entries(modelInfo)) {
|
|
1994
|
+
for (const [fieldName, fieldValue] of _14.entries(record)) {
|
|
1934
1995
|
const [, recordId] = virtualRecordId.split("_");
|
|
1935
|
-
const originalFieldValue =
|
|
1996
|
+
const originalFieldValue = _14.get(originalInput, [modelId, recordId, fieldName]);
|
|
1936
1997
|
const rawValue = createRawDatoValue(fieldValue, originalFieldValue, true);
|
|
1937
|
-
|
|
1998
|
+
_14.set(result, [modelId, recordId, fieldName], rawValue || originalFieldValue);
|
|
1938
1999
|
}
|
|
1939
2000
|
}
|
|
1940
2001
|
}
|
|
@@ -1943,25 +2004,25 @@ function createDatoExtractLoader() {
|
|
|
1943
2004
|
});
|
|
1944
2005
|
}
|
|
1945
2006
|
function detectDatoFieldType(rawDatoValue) {
|
|
1946
|
-
if (
|
|
2007
|
+
if (_14.has(rawDatoValue, "document") && _14.get(rawDatoValue, "schema") === "dast") {
|
|
1947
2008
|
return "structured_text";
|
|
1948
|
-
} else if (
|
|
2009
|
+
} else if (_14.has(rawDatoValue, "no_index") || _14.has(rawDatoValue, "twitter_card")) {
|
|
1949
2010
|
return "seo";
|
|
1950
|
-
} else if (
|
|
2011
|
+
} else if (_14.get(rawDatoValue, "type") === "item") {
|
|
1951
2012
|
return "single_block";
|
|
1952
|
-
} else if (
|
|
2013
|
+
} else if (_14.isArray(rawDatoValue) && _14.every(rawDatoValue, (item) => _14.get(item, "type") === "item")) {
|
|
1953
2014
|
return "rich_text";
|
|
1954
2015
|
} else if (_isFile(rawDatoValue)) {
|
|
1955
2016
|
return "file";
|
|
1956
|
-
} else if (
|
|
2017
|
+
} else if (_14.isArray(rawDatoValue) && _14.every(rawDatoValue, (item) => _isFile(item))) {
|
|
1957
2018
|
return "gallery";
|
|
1958
2019
|
} else if (_isJson(rawDatoValue)) {
|
|
1959
2020
|
return "json";
|
|
1960
|
-
} else if (
|
|
2021
|
+
} else if (_14.isString(rawDatoValue)) {
|
|
1961
2022
|
return "string";
|
|
1962
2023
|
} else if (_isVideo(rawDatoValue)) {
|
|
1963
2024
|
return "video";
|
|
1964
|
-
} else if (
|
|
2025
|
+
} else if (_14.isArray(rawDatoValue) && _14.every(rawDatoValue, (item) => _14.isString(item))) {
|
|
1965
2026
|
return "ref_list";
|
|
1966
2027
|
} else {
|
|
1967
2028
|
return null;
|
|
@@ -2023,9 +2084,9 @@ function serializeStructuredText(rawStructuredText) {
|
|
|
2023
2084
|
if ("document" in node) {
|
|
2024
2085
|
return serializeStructuredTextNode(node.document, [...path9, "document"], acc);
|
|
2025
2086
|
}
|
|
2026
|
-
if (!
|
|
2087
|
+
if (!_14.isNil(node.value)) {
|
|
2027
2088
|
acc[[...path9, "value"].join(".")] = node.value;
|
|
2028
|
-
} else if (
|
|
2089
|
+
} else if (_14.get(node, "type") === "block") {
|
|
2029
2090
|
acc[[...path9, "item"].join(".")] = serializeBlock(node.item);
|
|
2030
2091
|
}
|
|
2031
2092
|
if (node.children) {
|
|
@@ -2037,44 +2098,44 @@ function serializeStructuredText(rawStructuredText) {
|
|
|
2037
2098
|
}
|
|
2038
2099
|
}
|
|
2039
2100
|
function serializeSeo(rawSeo) {
|
|
2040
|
-
return
|
|
2101
|
+
return _14.chain(rawSeo).pick(["title", "description"]).value();
|
|
2041
2102
|
}
|
|
2042
2103
|
function serializeBlock(rawBlock) {
|
|
2043
|
-
if (
|
|
2104
|
+
if (_14.get(rawBlock, "type") === "item" && _14.has(rawBlock, "id")) {
|
|
2044
2105
|
return serializeBlock(rawBlock.attributes);
|
|
2045
2106
|
}
|
|
2046
2107
|
const result = {};
|
|
2047
|
-
for (const [attributeName, attributeValue] of
|
|
2108
|
+
for (const [attributeName, attributeValue] of _14.entries(rawBlock)) {
|
|
2048
2109
|
result[attributeName] = createParsedDatoValue(attributeValue);
|
|
2049
2110
|
}
|
|
2050
2111
|
return result;
|
|
2051
2112
|
}
|
|
2052
2113
|
function serializeBlockList(rawBlockList) {
|
|
2053
|
-
return
|
|
2114
|
+
return _14.chain(rawBlockList).map((block) => serializeBlock(block)).value();
|
|
2054
2115
|
}
|
|
2055
2116
|
function serializeVideo(rawVideo) {
|
|
2056
|
-
return
|
|
2117
|
+
return _14.chain(rawVideo).pick(["title"]).value();
|
|
2057
2118
|
}
|
|
2058
2119
|
function serializeFile(rawFile) {
|
|
2059
|
-
return
|
|
2120
|
+
return _14.chain(rawFile).pick(["alt", "title"]).value();
|
|
2060
2121
|
}
|
|
2061
2122
|
function serializeGallery(rawGallery) {
|
|
2062
|
-
return
|
|
2123
|
+
return _14.chain(rawGallery).map((item) => serializeFile(item)).value();
|
|
2063
2124
|
}
|
|
2064
2125
|
function deserializeFile(parsedFile, originalRawFile) {
|
|
2065
|
-
return
|
|
2126
|
+
return _14.chain(parsedFile).defaults(originalRawFile).value();
|
|
2066
2127
|
}
|
|
2067
2128
|
function deserializeGallery(parsedGallery, originalRawGallery) {
|
|
2068
|
-
return
|
|
2129
|
+
return _14.chain(parsedGallery).map((item, i) => deserializeFile(item, originalRawGallery[i])).value();
|
|
2069
2130
|
}
|
|
2070
2131
|
function deserializeVideo(parsedVideo, originalRawVideo) {
|
|
2071
|
-
return
|
|
2132
|
+
return _14.chain(parsedVideo).defaults(originalRawVideo).value();
|
|
2072
2133
|
}
|
|
2073
2134
|
function deserializeBlock(payload, rawNode, isClean = false) {
|
|
2074
|
-
const result =
|
|
2075
|
-
for (const [attributeName, attributeValue] of
|
|
2135
|
+
const result = _14.cloneDeep(rawNode);
|
|
2136
|
+
for (const [attributeName, attributeValue] of _14.entries(rawNode.attributes)) {
|
|
2076
2137
|
const rawValue = createRawDatoValue(payload[attributeName], attributeValue, isClean);
|
|
2077
|
-
|
|
2138
|
+
_14.set(result, ["attributes", attributeName], rawValue);
|
|
2078
2139
|
}
|
|
2079
2140
|
if (isClean) {
|
|
2080
2141
|
delete result["id"];
|
|
@@ -2082,33 +2143,33 @@ function deserializeBlock(payload, rawNode, isClean = false) {
|
|
|
2082
2143
|
return result;
|
|
2083
2144
|
}
|
|
2084
2145
|
function deserializeSeo(parsedSeo, originalRawSeo) {
|
|
2085
|
-
return
|
|
2146
|
+
return _14.chain(parsedSeo).pick(["title", "description"]).defaults(originalRawSeo).value();
|
|
2086
2147
|
}
|
|
2087
2148
|
function deserializeBlockList(parsedBlockList, originalRawBlockList, isClean = false) {
|
|
2088
|
-
return
|
|
2149
|
+
return _14.chain(parsedBlockList).map((block, i) => deserializeBlock(block, originalRawBlockList[i], isClean)).value();
|
|
2089
2150
|
}
|
|
2090
2151
|
function deserializeStructuredText(parsedStructuredText, originalRawStructuredText) {
|
|
2091
|
-
const result =
|
|
2092
|
-
for (const [path9, value] of
|
|
2093
|
-
const realPath =
|
|
2094
|
-
const deserializedValue = createRawDatoValue(value,
|
|
2095
|
-
|
|
2152
|
+
const result = _14.cloneDeep(originalRawStructuredText);
|
|
2153
|
+
for (const [path9, value] of _14.entries(parsedStructuredText)) {
|
|
2154
|
+
const realPath = _14.chain(path9.split(".")).flatMap((s) => !_14.isNaN(_14.toNumber(s)) ? ["children", s] : s).value();
|
|
2155
|
+
const deserializedValue = createRawDatoValue(value, _14.get(originalRawStructuredText, realPath), true);
|
|
2156
|
+
_14.set(result, realPath, deserializedValue);
|
|
2096
2157
|
}
|
|
2097
2158
|
return result;
|
|
2098
2159
|
}
|
|
2099
2160
|
function _isJson(rawDatoValue) {
|
|
2100
2161
|
try {
|
|
2101
|
-
return
|
|
2162
|
+
return _14.isString(rawDatoValue) && rawDatoValue.startsWith("{") && rawDatoValue.endsWith("}") && !!JSON.parse(rawDatoValue);
|
|
2102
2163
|
} catch (e) {
|
|
2103
2164
|
return false;
|
|
2104
2165
|
}
|
|
2105
2166
|
}
|
|
2106
2167
|
function _isFile(rawDatoValue) {
|
|
2107
|
-
return
|
|
2168
|
+
return _14.isObject(rawDatoValue) && ["alt", "title", "custom_data", "focal_point", "upload_id"].every((key) => _14.has(rawDatoValue, key));
|
|
2108
2169
|
}
|
|
2109
2170
|
function _isVideo(rawDatoValue) {
|
|
2110
|
-
return
|
|
2111
|
-
(key) =>
|
|
2171
|
+
return _14.isObject(rawDatoValue) && ["url", "title", "width", "height", "provider", "provider_uid", "thumbnail_url"].every(
|
|
2172
|
+
(key) => _14.has(rawDatoValue, key)
|
|
2112
2173
|
);
|
|
2113
2174
|
}
|
|
2114
2175
|
|
|
@@ -2169,7 +2230,7 @@ function createVttLoader() {
|
|
|
2169
2230
|
}
|
|
2170
2231
|
|
|
2171
2232
|
// src/cli/loaders/variable/index.ts
|
|
2172
|
-
import
|
|
2233
|
+
import _15 from "lodash";
|
|
2173
2234
|
function createVariableLoader(params) {
|
|
2174
2235
|
return composeLoaders(variableExtractLoader(params), variableContentLoader());
|
|
2175
2236
|
}
|
|
@@ -2212,11 +2273,11 @@ function variableExtractLoader(params) {
|
|
|
2212
2273
|
function variableContentLoader() {
|
|
2213
2274
|
return createLoader({
|
|
2214
2275
|
pull: async (locale, input) => {
|
|
2215
|
-
const result =
|
|
2276
|
+
const result = _15.mapValues(input, (payload) => payload.value);
|
|
2216
2277
|
return result;
|
|
2217
2278
|
},
|
|
2218
2279
|
push: async (locale, data, originalInput) => {
|
|
2219
|
-
const result =
|
|
2280
|
+
const result = _15.cloneDeep(originalInput || {});
|
|
2220
2281
|
for (const [key, originalValueObj] of Object.entries(result)) {
|
|
2221
2282
|
result[key] = {
|
|
2222
2283
|
...originalValueObj,
|
|
@@ -2239,20 +2300,20 @@ function getFormatSpecifierPattern(type) {
|
|
|
2239
2300
|
}
|
|
2240
2301
|
|
|
2241
2302
|
// src/cli/loaders/sync.ts
|
|
2242
|
-
import
|
|
2303
|
+
import _16 from "lodash";
|
|
2243
2304
|
function createSyncLoader() {
|
|
2244
2305
|
return createLoader({
|
|
2245
2306
|
async pull(locale, input, originalInput) {
|
|
2246
2307
|
if (!originalInput) {
|
|
2247
2308
|
return input;
|
|
2248
2309
|
}
|
|
2249
|
-
return
|
|
2310
|
+
return _16.chain(originalInput).mapValues((value, key) => input[key]).value();
|
|
2250
2311
|
},
|
|
2251
2312
|
async push(locale, data, originalInput) {
|
|
2252
2313
|
if (!originalInput) {
|
|
2253
2314
|
return data;
|
|
2254
2315
|
}
|
|
2255
|
-
return
|
|
2316
|
+
return _16.chain(originalInput || {}).mapValues((value, key) => data[key]).value();
|
|
2256
2317
|
}
|
|
2257
2318
|
});
|
|
2258
2319
|
}
|
|
@@ -2479,7 +2540,7 @@ import path7 from "path";
|
|
|
2479
2540
|
import Z3 from "zod";
|
|
2480
2541
|
import YAML3 from "yaml";
|
|
2481
2542
|
import { MD5 } from "object-hash";
|
|
2482
|
-
import
|
|
2543
|
+
import _17 from "lodash";
|
|
2483
2544
|
function createLockfileHelper() {
|
|
2484
2545
|
return {
|
|
2485
2546
|
isLockfileExists: () => {
|
|
@@ -2489,23 +2550,23 @@ function createLockfileHelper() {
|
|
|
2489
2550
|
registerSourceData: (pathPattern, sourceData) => {
|
|
2490
2551
|
const lockfile = _loadLockfile();
|
|
2491
2552
|
const sectionKey = MD5(pathPattern);
|
|
2492
|
-
const sectionChecksums =
|
|
2553
|
+
const sectionChecksums = _17.mapValues(sourceData, (value) => MD5(value));
|
|
2493
2554
|
lockfile.checksums[sectionKey] = sectionChecksums;
|
|
2494
2555
|
_saveLockfile(lockfile);
|
|
2495
2556
|
},
|
|
2496
2557
|
registerPartialSourceData: (pathPattern, partialSourceData) => {
|
|
2497
2558
|
const lockfile = _loadLockfile();
|
|
2498
2559
|
const sectionKey = MD5(pathPattern);
|
|
2499
|
-
const sectionChecksums =
|
|
2500
|
-
lockfile.checksums[sectionKey] =
|
|
2560
|
+
const sectionChecksums = _17.mapValues(partialSourceData, (value) => MD5(value));
|
|
2561
|
+
lockfile.checksums[sectionKey] = _17.merge({}, lockfile.checksums[sectionKey] ?? {}, sectionChecksums);
|
|
2501
2562
|
_saveLockfile(lockfile);
|
|
2502
2563
|
},
|
|
2503
2564
|
extractUpdatedData: (pathPattern, sourceData) => {
|
|
2504
2565
|
const lockfile = _loadLockfile();
|
|
2505
2566
|
const sectionKey = MD5(pathPattern);
|
|
2506
|
-
const currentChecksums =
|
|
2567
|
+
const currentChecksums = _17.mapValues(sourceData, (value) => MD5(value));
|
|
2507
2568
|
const savedChecksums = lockfile.checksums[sectionKey] || {};
|
|
2508
|
-
const updatedData =
|
|
2569
|
+
const updatedData = _17.pickBy(sourceData, (value, key) => savedChecksums[key] !== currentChecksums[key]);
|
|
2509
2570
|
return updatedData;
|
|
2510
2571
|
}
|
|
2511
2572
|
};
|
|
@@ -2753,7 +2814,7 @@ var i18n_default = new Command6().command("i18n").description("Run Localization
|
|
|
2753
2814
|
targetData
|
|
2754
2815
|
});
|
|
2755
2816
|
if (flags.key) {
|
|
2756
|
-
processableData =
|
|
2817
|
+
processableData = _18.pickBy(processableData, (_20, key) => key === flags.key);
|
|
2757
2818
|
}
|
|
2758
2819
|
if (flags.verbose) {
|
|
2759
2820
|
bucketOra.info(JSON.stringify(processableData, null, 2));
|
|
@@ -2789,7 +2850,7 @@ var i18n_default = new Command6().command("i18n").description("Run Localization
|
|
|
2789
2850
|
if (flags.verbose) {
|
|
2790
2851
|
bucketOra.info(JSON.stringify(processedTargetData, null, 2));
|
|
2791
2852
|
}
|
|
2792
|
-
let finalTargetData =
|
|
2853
|
+
let finalTargetData = _18.merge({}, sourceData, targetData, processedTargetData);
|
|
2793
2854
|
if (flags.interactive) {
|
|
2794
2855
|
bucketOra.stop();
|
|
2795
2856
|
const reviewedData = await reviewChanges({
|
|
@@ -2803,7 +2864,7 @@ var i18n_default = new Command6().command("i18n").description("Run Localization
|
|
|
2803
2864
|
finalTargetData = reviewedData;
|
|
2804
2865
|
bucketOra.start(`Applying changes to ${bucketConfig} (${targetLocale})`);
|
|
2805
2866
|
}
|
|
2806
|
-
const finalDiffSize =
|
|
2867
|
+
const finalDiffSize = _18.chain(finalTargetData).omitBy((value, key) => value === targetData[key]).size().value();
|
|
2807
2868
|
if (finalDiffSize > 0 || flags.force) {
|
|
2808
2869
|
await bucketLoader.push(targetLocale, finalTargetData);
|
|
2809
2870
|
bucketOra.succeed(`[${sourceLocale} -> ${targetLocale}] Localization completed`);
|
|
@@ -2848,9 +2909,9 @@ var i18n_default = new Command6().command("i18n").description("Run Localization
|
|
|
2848
2909
|
}
|
|
2849
2910
|
});
|
|
2850
2911
|
function calculateDataDelta(args) {
|
|
2851
|
-
const newKeys =
|
|
2912
|
+
const newKeys = _18.difference(Object.keys(args.sourceData), Object.keys(args.targetData));
|
|
2852
2913
|
const updatedKeys = Object.keys(args.updatedSourceData);
|
|
2853
|
-
const result =
|
|
2914
|
+
const result = _18.chain(args.sourceData).pickBy((value, key) => newKeys.includes(key) || updatedKeys.includes(key)).value();
|
|
2854
2915
|
return result;
|
|
2855
2916
|
}
|
|
2856
2917
|
async function retryWithExponentialBackoff(operation, maxAttempts, baseDelay = 1e3) {
|
|
@@ -2991,7 +3052,7 @@ Reviewing changes for ${chalk.blue(args.pathPattern)} (${chalk.yellow(args.targe
|
|
|
2991
3052
|
return args.currentData;
|
|
2992
3053
|
}
|
|
2993
3054
|
const customData = { ...args.currentData };
|
|
2994
|
-
const changes =
|
|
3055
|
+
const changes = _18.reduce(
|
|
2995
3056
|
args.proposedData,
|
|
2996
3057
|
(result, value, key) => {
|
|
2997
3058
|
if (args.currentData[key] !== value) {
|
|
@@ -3072,7 +3133,7 @@ var flagsSchema = Z5.object({
|
|
|
3072
3133
|
// src/cli/cmd/cleanup.ts
|
|
3073
3134
|
import { resolveOverridenLocale as resolveOverridenLocale5 } from "@lingo.dev/_spec";
|
|
3074
3135
|
import { Command as Command8 } from "interactive-commander";
|
|
3075
|
-
import
|
|
3136
|
+
import _19 from "lodash";
|
|
3076
3137
|
import Ora7 from "ora";
|
|
3077
3138
|
var cleanup_default = new Command8().command("cleanup").description("Remove keys from target files that do not exist in the source file").helpOption("-h, --help", "Show help").option("--locale <locale>", "Specific locale to cleanup").option("--bucket <bucket>", "Specific bucket to cleanup").option("--dry-run", "Show what would be removed without making changes").option("--verbose", "Show verbose output").action(async function(options) {
|
|
3078
3139
|
const ora = Ora7();
|
|
@@ -3102,7 +3163,7 @@ var cleanup_default = new Command8().command("cleanup").description("Remove keys
|
|
|
3102
3163
|
try {
|
|
3103
3164
|
const targetData = await bucketLoader.pull(targetLocale);
|
|
3104
3165
|
const targetKeys = Object.keys(targetData);
|
|
3105
|
-
const keysToRemove =
|
|
3166
|
+
const keysToRemove = _19.difference(targetKeys, sourceKeys);
|
|
3106
3167
|
if (keysToRemove.length === 0) {
|
|
3107
3168
|
bucketOra.succeed(`[${targetLocale}] No keys to remove`);
|
|
3108
3169
|
continue;
|
|
@@ -3111,7 +3172,7 @@ var cleanup_default = new Command8().command("cleanup").description("Remove keys
|
|
|
3111
3172
|
bucketOra.info(`[${targetLocale}] Keys to remove: ${JSON.stringify(keysToRemove, null, 2)}`);
|
|
3112
3173
|
}
|
|
3113
3174
|
if (!options.dryRun) {
|
|
3114
|
-
const cleanedData =
|
|
3175
|
+
const cleanedData = _19.pick(targetData, sourceKeys);
|
|
3115
3176
|
await bucketLoader.push(targetLocale, cleanedData);
|
|
3116
3177
|
bucketOra.succeed(`[${targetLocale}] Removed ${keysToRemove.length} keys`);
|
|
3117
3178
|
} else {
|
|
@@ -3163,7 +3224,7 @@ function displaySummary(results) {
|
|
|
3163
3224
|
// package.json
|
|
3164
3225
|
var package_default = {
|
|
3165
3226
|
name: "lingo.dev",
|
|
3166
|
-
version: "0.74.
|
|
3227
|
+
version: "0.74.13",
|
|
3167
3228
|
description: "Lingo.dev CLI",
|
|
3168
3229
|
private: false,
|
|
3169
3230
|
publishConfig: {
|
|
@@ -3200,6 +3261,7 @@ var package_default = {
|
|
|
3200
3261
|
dev: "tsup --watch",
|
|
3201
3262
|
build: "tsc --noEmit && tsup",
|
|
3202
3263
|
test: "vitest run",
|
|
3264
|
+
"test:watch": "vitest",
|
|
3203
3265
|
clean: "rm -rf build"
|
|
3204
3266
|
},
|
|
3205
3267
|
keywords: [],
|