Skip to content

Commit 0e3916c

Browse files
fix: dates in mdx (#678)
feat: support locked keys in mdx
1 parent 1f92c80 commit 0e3916c

10 files changed

Lines changed: 190 additions & 158 deletions

File tree

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"lingo.dev": patch
3+
---
4+
5+
dates in mdx

packages/cli/demo/mdx/en.mdx

Whitespace-only changes.

packages/cli/demo/mdx/es.mdx

Whitespace-only changes.

packages/cli/i18n.json

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,11 @@
44
"source": "en",
55
"targets": ["es"]
66
},
7-
"buckets": {},
7+
"buckets": {
8+
"mdx": {
9+
"lockedKeys": ["meta/slug", "meta/category"],
10+
"include": ["demo/mdx/[locale].mdx"]
11+
}
12+
},
813
"$schema": "https://lingo.dev/schema/i18n.json"
914
}

packages/cli/i18n.lock

Lines changed: 29 additions & 140 deletions
Original file line numberDiff line numberDiff line change
@@ -1,143 +1,32 @@
11
version: 1
22
checksums:
33
77624f597c2092ea61483d71313398c3:
4-
meta/title: e2fb2a02229795be33772c83e43d6ec0
5-
meta/description: 22cb80fdc3ff54436a6e911c897b5563
6-
content/0: 8669019fdbb2cfc2d94a8fdc76333289
7-
content/1: 0b3e6591c20e9c2f7995fb8ea8150c0d
8-
content/2: a885b09c29f2d77fbb7240e8ecb82d71
9-
content/3: 3db42a3ab228c0867d2904c8d9326e78
10-
content/4: fc67acac41259de6a882fb90a0ba97c7
11-
content/5: f962f29f56ae53c1e45c7f84972845fe
12-
content/6: 48a70bf3dc2328eaa3d0a0fa0da266b6
13-
content/7: 51229b58a8a0092674e11f0b779cc669
14-
content/8: 8d16b73b16f0247208893f7832306e14
15-
content/9: 8bb8615f257ea78084a436256f6a0383
16-
content/10: c7d13744dbfb66641d7bfe744274668c
17-
content/11: fbb2ae34b45a0d9d1aae59fdcb7f3697
18-
content/12: 29b0c41292ab1b8dd84bc7019ab8c110
19-
content/13: 57a519330e9311aac242f67fb675da40
20-
content/14: 1983a13000b7186a172b411f752f5a87
21-
content/15: fb506d8078da4d699b0bb09af7859ba2
22-
content/16: df3fc2cca7a7dbd073411c12538cc2d8
23-
content/17: 75434b5cec52c7992e82b16ed153622f
24-
content/18: 263450bda03a8f3e199fd6f6f7f18df3
25-
content/19: 2612c038df28b262f30bd206c3e2bb92
26-
content/20: 532c64fa539ecfda6b819d79ffc978a5
27-
content/21: da09c2469f4b0071c4440e74c889f7eb
28-
content/22: 36e1c42c25ffc7553a7fc9f85fe153f3
29-
content/23: fbd131eeabc1ba1f12de14e44c60155b
30-
content/24: c2ba183b236c80dc82945312cff3a73a
31-
content/25: 30934cc98ee9bc0531e55076b78cbfb1
32-
content/26: d2f34271c2fb61407a3d97b73b399c4b
33-
content/27: 532c64fa539ecfda6b819d79ffc978a5
34-
content/28: 054a37a1e8b899ef4d50fefcd6a8c288
35-
content/29: 36e1c42c25ffc7553a7fc9f85fe153f3
36-
content/30: 19b55aecf778111519f6fc34f790b317
37-
content/31: 47559c448d86e0b8454be7edc8b9b1a5
38-
content/32: fbd131eeabc1ba1f12de14e44c60155b
39-
content/33: 1c66dcf6b3d552f266f255bf4bcf79a8
40-
content/34: ea7b33b2f720d0a0edb3898491f4460c
41-
content/35: e9e9cfa3981eb2000daa3a32ed6d67cb
42-
content/36: 42d1cbe8080ec442fac8d36c5c355250
43-
content/37: d7624486811d1ffac1e0271f9d490e62
44-
content/38: 22bee2c7876b4a0432388ce3c2c5581a
45-
content/39: a1fa3c9086f58b9634fd2f80a1059f7d
46-
content/40: 532c64fa539ecfda6b819d79ffc978a5
47-
content/41: e850178aecaca59ab569c4640ddcb82d
48-
content/42: 9c92bb299f2c90cb5e61584ddb965f11
49-
content/43: c23863a0bf30dca05d9673cd46882e5a
50-
content/44: 93e97b200e02f64d812b6f99a2ab27d7
51-
content/45: e4458dc85a36ff38ab59085fea95bd29
52-
content/46: 95c7dfe3ef2d9e8f1791aadb54964029
53-
content/47: b7cda597f2c572a5399b52381e1d22e5
54-
content/48: 43763947f32df467cd79fe7317b788e0
55-
content/49: fbd131eeabc1ba1f12de14e44c60155b
56-
content/50: f2adbf230d0cc2d692e0874d70eb3761
57-
content/51: 3a7ef3a9d8ac3324a2fbc0295dff316b
58-
content/52: ab22c2877d37961ad7081bac762ff40a
59-
content/53: 94511f66a74c07c008f4926046f118f3
60-
content/54: 07b70955bc8542fa69f68e5c9ac79fea
61-
content/55: 532c64fa539ecfda6b819d79ffc978a5
62-
content/56: 8198784dc73b24684412f2f064af7fae
63-
content/57: fbd131eeabc1ba1f12de14e44c60155b
64-
content/58: 8193a8c88b54c40f110fe91ac7991b2a
65-
content/59: e9e2b3c60c56bc817a203c4276e43f97
66-
content/60: 19c5246e25bd7e7ee7301c2ccb25649c
67-
content/61: b34ef3f974c3e496a4c8428cc7ec34ab
68-
content/62: 198efa2ace291a6e2341212e1fa13173
69-
content/63: 0c4ce0fc7100db6818cfd3b8f54ef7ab
70-
content/64: 532c64fa539ecfda6b819d79ffc978a5
71-
content/65: 4baf7c60f192458c2cf580d80bf45886
72-
content/66: b51c649ded1f5129607321e17cda50ac
73-
content/67: 5de887a8bb95f41420bc8471cd6ba237
74-
content/68: 6ab7c9811fb962d0cd6af1317cba58a6
75-
content/69: 587ab6a3de61d60e72157e0364cc450a
76-
content/70: 0312b2ae592aced8f69ecffd07f3a8c4
77-
content/71: fbd131eeabc1ba1f12de14e44c60155b
78-
content/72: 71cd921ee08deb528dc5ed88e734366d
79-
content/73: 748e148725bb7dce6aeb37583314022d
80-
content/74: cd0012f82026e5259c82a8a01f93548d
81-
content/75: b1044ce7c8c728161623de5149031da7
82-
content/76: 8afa48b66aafb543572ece965caa92b5
83-
content/77: 1be302529ca305e6dd9c43e0c4ce062c
84-
content/78: 532c64fa539ecfda6b819d79ffc978a5
85-
content/79: 8c308e80377a7228021a4c71b75f7e5b
86-
content/80: 8d7c6a1c7e6d58c40e36de640030f4fb
87-
content/81: aa86d22ba1174fcb6c2399a5367b7eb3
88-
content/82: 0147c1d2371526957c954e6ba3a4a497
89-
content/83: 0abc3050a3526cd3ef5036f98ab4da2f
90-
content/84: ff7e6a0f3f0d1a8e9188ba8a1ab5c83e
91-
content/85: 4f431510dd44bc50d78302de730b833a
92-
content/86: 46e649764e676132df3b2071c4352246
93-
content/87: fbd131eeabc1ba1f12de14e44c60155b
94-
content/88: 8c308e80377a7228021a4c71b75f7e5b
95-
content/89: db98db1b77b5701518cc989656be65b1
96-
content/90: aa86d22ba1174fcb6c2399a5367b7eb3
97-
content/91: 991ba980de06819b51b0a2afbf0ea4de
98-
content/92: 7a13302a245b587877a3a4adc06bfcdb
99-
content/93: 73142542d0cc3f22fe0bf13d752356bf
100-
content/94: 6adc8368e7524f1084f66c07392561c5
101-
content/95: 329db40c8de149e992cf7c8c86c85124
102-
content/96: 532c64fa539ecfda6b819d79ffc978a5
103-
content/97: 7be33d5f66246431debeb85c5d7977d2
104-
content/98: fbd131eeabc1ba1f12de14e44c60155b
105-
content/99: 92c44c1a7dd8f934dafd2ffe73f9ac4d
106-
content/100: ce3cdada9749f44b3da1b2e29accaf99
107-
content/101: c148f41b64a4e43bbce6e801edced8a5
108-
content/102: 0032e3b4b6f84958868add2c37bfa15b
109-
content/103: 4526009c1563356c22075e7b2f0f49f7
110-
content/104: 300aeb0033b21a2a014070c85f3cab61
111-
content/105: c955e9917dcfacf6cabf0877e50a97e7
112-
content/106: 532c64fa539ecfda6b819d79ffc978a5
113-
content/107: beb7a1ffdf5ac23ba68b0aa929d6d5b3
114-
content/108: f9f94ca530fee2d0e35170e3d3e795ee
115-
content/109: be14e07853f36ccf1c3ce513a98b2dd7
116-
content/110: a1aad7630c6a8d664bde98bd046dedc2
117-
content/111: 4b11e0bc3924ca1bfb6f6d080794379b
118-
content/112: e9a7066d60dff19e016c77ce51eb3c7d
119-
content/113: fbd131eeabc1ba1f12de14e44c60155b
120-
content/114: beb7a1ffdf5ac23ba68b0aa929d6d5b3
121-
content/115: 5239dbbeff70511b0f3444370e00ab3b
122-
content/116: be14e07853f36ccf1c3ce513a98b2dd7
123-
content/117: 4d934fa2f525170597802b91d609805e
124-
content/118: 4b11e0bc3924ca1bfb6f6d080794379b
125-
content/119: 75a6b27d6d1af7580d4f8819b87eceec
126-
content/120: 5764a4faf8072cd1e9c91a9a4a796226
127-
content/121: 8d60dc75cc12ec0c0e795c869fe9e39c
128-
content/122: 53f538dc288085fc4ca7e88f16061333
129-
content/123: b5829b740dfcb79f99d0e955f19aa635
130-
content/124: 33dd3556ad1f9d0cb21c872ea4419f59
131-
content/125: 5add80131019504c7a5c81a81855880c
132-
content/126: 532c64fa539ecfda6b819d79ffc978a5
133-
content/127: 2c75df9946cf436f268b1acbf7bb3c17
134-
content/128: fbd131eeabc1ba1f12de14e44c60155b
135-
content/129: 5690517c65f0f53b8be38e6cc14aa63d
136-
content/130: 251e1c4f7fbd5c0094b4939a0ba8d48e
137-
content/131: 00f3066eee15e5780f2ef0d1a4bc3769
138-
content/132: ad51f2de9681ef204db0f1c458eb9505
139-
content/133: 9b49af1601fbf7132fef6ebf400173d9
140-
content/134: c03859332fc4a6824bb2bc20ddb7c460
141-
content/135: 01b73b171c9d1420c6c0a37df0545c96
142-
content/136: 2ff78a7555656bee7bfa6e8f37e19144
143-
content/137: 89381d2f61834b55cb64bdddc3b88276
4+
meta/title: 0a2cc2035f59644733615dd8675b3618
5+
meta/summary: dd9c3e74401afb579e4668b11f11f2ab
6+
meta/author: 5cc899158b9a4b8e2a6abaf26c498786
7+
content/0: 4dfc7a0ee6a9dc089d8a76ad27d38754
8+
content/1: 133929451ee05c91d68b75a15bfe6596
9+
content/2: c89b46f8b2f582e06111a6c96b82e8bf
10+
content/3: 417995a6cdfb7ab127e5431b5b5ef720
11+
content/4: aa9c76dbf759c838e8bd62ae85825e52
12+
content/5: 5704f51f430cbaa8d6452b38c91ea485
13+
content/6: 8db8789e2a220825c9df6c3706bb8389
14+
content/7: 6278ebdd79f1ea718aabeb8e40b5f999
15+
content/8: 37ad0f04abb0e32b88e3bd6b79bb7110
16+
content/9: f3103fdf8e9bd164be82af6c84e17b81
17+
content/10: f030df31e8f24b9890bc9b7d7d387a69
18+
content/11: da348e7e947e0d6054f2b177abc6060b
19+
content/12: 83e15bc1599d243ca5efee3bb6da3152
20+
content/13: 3c176fdcdcc855b44cb42da632312e73
21+
content/14: cecd264ec97755c0100c8bc7d5b0bd70
22+
content/15: 426e9e0abc16c001e04cfb03c9611a6b
23+
content/16: a42f584c463c26a44c5c6d0f6cb8ace0
24+
content/17: e54125a6e2a6fea17309a2c8949e2490
25+
content/18: 79ef1a72bb4e09c347e3a0afae68c18d
26+
content/19: 3feea98e670a946eefdd2fc48d7b99b5
27+
content/20: 51adf33450cab2ef392e93147386647c
28+
content/21: 66ba09daf8e0ae94effa4b98f19ded22
29+
content/22: fed9e643c4a407e5fa118690285a85ed
30+
content/23: 5975348444539ca25e20d05e53b87105
31+
content/24: 7f019348c6dd5d97e746f32741241c55
32+
content/25: 5678250e0f9cff6a5b71f42ff222bd2d

packages/cli/src/cli/loaders/flat.spec.ts

Lines changed: 54 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,24 @@ describe("flat loader", () => {
2929
years: ["January 13, 2025", "February 14, 2025"],
3030
});
3131
});
32+
33+
it("handles date objects correctly", async () => {
34+
const loader = createFlatLoader();
35+
loader.setDefaultLocale("en");
36+
const date = new Date("2023-01-01T00:00:00Z");
37+
await loader.pull("en", {
38+
publishedAt: date,
39+
metadata: { createdAt: date },
40+
});
41+
const output = await loader.push("en", {
42+
publishedAt: date.toISOString(),
43+
"metadata/createdAt": date.toISOString(),
44+
});
45+
expect(output).toEqual({
46+
publishedAt: date.toISOString(),
47+
metadata: { createdAt: date.toISOString() },
48+
});
49+
});
3250
});
3351

3452
describe("helper functions", () => {
@@ -59,11 +77,21 @@ describe("flat loader", () => {
5977
messages: ["a", "b", "c"],
6078
});
6179
});
80+
81+
it("should preserve date objects", () => {
82+
const date = new Date();
83+
const input = { createdAt: date };
84+
const output = denormalizeObjectKeys(input);
85+
expect(output).toEqual({ createdAt: date });
86+
});
6287
});
6388

6489
describe("buildDenormalizedKeysMap", () => {
6590
it("should build normalized keys map", () => {
66-
const denormalized: Record<string, string> = flatten(denormalizeObjectKeys(inputObj), { delimiter: "/" });
91+
const denormalized: Record<string, string> = flatten(
92+
denormalizeObjectKeys(inputObj),
93+
{ delimiter: "/" },
94+
);
6795
const output = buildDenormalizedKeysMap(denormalized);
6896
expect(output).toEqual({
6997
"messages/1": `messages/${OBJECT_NUMERIC_KEY_PREFIX}1`,
@@ -72,7 +100,10 @@ describe("flat loader", () => {
72100
});
73101

74102
it("should build keys map array", () => {
75-
const denormalized: Record<string, string> = flatten(denormalizeObjectKeys(inputArray), { delimiter: "/" });
103+
const denormalized: Record<string, string> = flatten(
104+
denormalizeObjectKeys(inputArray),
105+
{ delimiter: "/" },
106+
);
76107
const output = buildDenormalizedKeysMap(denormalized);
77108
expect(output).toEqual({
78109
"messages/0": "messages/0",
@@ -92,21 +123,38 @@ describe("flat loader", () => {
92123
const output = normalizeObjectKeys(denormalizeObjectKeys(inputArray));
93124
expect(output).toEqual(inputArray);
94125
});
126+
127+
it("should preserve date objects", () => {
128+
const date = new Date();
129+
const input = { createdAt: date };
130+
const output = normalizeObjectKeys(input);
131+
expect(output).toEqual({ createdAt: date });
132+
});
95133
});
96134

97135
describe("mapDeormalizedKeys", () => {
98136
it("should map normalized keys", () => {
99-
const denormalized: Record<string, string> = flatten(denormalizeObjectKeys(inputObj), { delimiter: "/" });
137+
const denormalized: Record<string, string> = flatten(
138+
denormalizeObjectKeys(inputObj),
139+
{ delimiter: "/" },
140+
);
100141
const keyMap = buildDenormalizedKeysMap(denormalized);
101-
const flattened: Record<string, string> = flatten(inputObj, { delimiter: "/" });
142+
const flattened: Record<string, string> = flatten(inputObj, {
143+
delimiter: "/",
144+
});
102145
const mapped = mapDenormalizedKeys(flattened, keyMap);
103146
expect(mapped).toEqual(denormalized);
104147
});
105148

106149
it("should map array", () => {
107-
const denormalized: Record<string, string> = flatten(denormalizeObjectKeys(inputArray), { delimiter: "/" });
150+
const denormalized: Record<string, string> = flatten(
151+
denormalizeObjectKeys(inputArray),
152+
{ delimiter: "/" },
153+
);
108154
const keyMap = buildDenormalizedKeysMap(denormalized);
109-
const flattened: Record<string, string> = flatten(inputArray, { delimiter: "/" });
155+
const flattened: Record<string, string> = flatten(inputArray, {
156+
delimiter: "/",
157+
});
110158
const mapped = mapDenormalizedKeys(flattened, keyMap);
111159
expect(mapped).toEqual(denormalized);
112160
});

packages/cli/src/cli/loaders/flat.ts

Lines changed: 29 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,10 @@ type DenormalizeResult = {
1414
keysMap: Record<string, string>;
1515
};
1616

17-
function createDenormalizeLoader(): ILoader<Record<string, any>, DenormalizeResult> {
17+
function createDenormalizeLoader(): ILoader<
18+
Record<string, any>,
19+
DenormalizeResult
20+
> {
1821
return createLoader({
1922
pull: async (locale, input) => {
2023
const inputDenormalized = denormalizeObjectKeys(input || {});
@@ -34,7 +37,10 @@ function createDenormalizeLoader(): ILoader<Record<string, any>, DenormalizeResu
3437
});
3538
}
3639

37-
function createNormalizeLoader(): ILoader<DenormalizeResult, Record<string, string>> {
40+
function createNormalizeLoader(): ILoader<
41+
DenormalizeResult,
42+
Record<string, string>
43+
> {
3844
return createLoader({
3945
pull: async (locale, input) => {
4046
const normalized = normalizeObjectKeys(input.denormalized);
@@ -69,7 +75,10 @@ export function buildDenormalizedKeysMap(obj: Record<string, string>) {
6975
);
7076
}
7177

72-
export function mapDenormalizedKeys(obj: Record<string, any>, denormalizedKeysMap: Record<string, string>) {
78+
export function mapDenormalizedKeys(
79+
obj: Record<string, any>,
80+
denormalizedKeysMap: Record<string, string>,
81+
) {
7382
return Object.keys(obj).reduce(
7483
(acc, key) => {
7584
const denormalizedKey = denormalizedKeysMap[key] ?? key;
@@ -80,13 +89,20 @@ export function mapDenormalizedKeys(obj: Record<string, any>, denormalizedKeysMa
8089
);
8190
}
8291

83-
export function denormalizeObjectKeys(obj: Record<string, any>): Record<string, any> {
92+
export function denormalizeObjectKeys(
93+
obj: Record<string, any>,
94+
): Record<string, any> {
8495
if (_.isObject(obj) && !_.isArray(obj)) {
8596
return _.transform(
8697
obj,
8798
(result, value, key) => {
88-
const newKey = !isNaN(Number(key)) ? `${OBJECT_NUMERIC_KEY_PREFIX}${key}` : key;
89-
result[newKey] = _.isObject(value) ? denormalizeObjectKeys(value) : value;
99+
const newKey = !isNaN(Number(key))
100+
? `${OBJECT_NUMERIC_KEY_PREFIX}${key}`
101+
: key;
102+
result[newKey] =
103+
_.isObject(value) && !_.isDate(value)
104+
? denormalizeObjectKeys(value)
105+
: value;
90106
},
91107
{} as Record<string, any>,
92108
);
@@ -95,13 +111,18 @@ export function denormalizeObjectKeys(obj: Record<string, any>): Record<string,
95111
}
96112
}
97113

98-
export function normalizeObjectKeys(obj: Record<string, any>): Record<string, any> {
114+
export function normalizeObjectKeys(
115+
obj: Record<string, any>,
116+
): Record<string, any> {
99117
if (_.isObject(obj) && !_.isArray(obj)) {
100118
return _.transform(
101119
obj,
102120
(result, value, key) => {
103121
const newKey = `${key}`.replace(OBJECT_NUMERIC_KEY_PREFIX, "");
104-
result[newKey] = _.isObject(value) ? normalizeObjectKeys(value) : value;
122+
result[newKey] =
123+
_.isObject(value) && !_.isDate(value)
124+
? normalizeObjectKeys(value)
125+
: value;
105126
},
106127
{} as Record<string, any>,
107128
);

0 commit comments

Comments
 (0)