Skip to content

Commit 788fce0

Browse files
authored
feat(locales): add mergeLocales utility (#1707)
1 parent 47b2cfc commit 788fce0

2 files changed

Lines changed: 96 additions & 0 deletions

File tree

src/utils/merge-locales.ts

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import type { LocaleDefinition } from '..';
2+
3+
/**
4+
* Merges the given locales into one locale.
5+
* The locales are merged in the order they are given.
6+
* The first locale that provides an entry for a category will be used for that.
7+
* Mutating the category entries in the returned locale will also mutate the entries in the respective source locale.
8+
*
9+
* @param locales The locales to merge.
10+
* @returns The newly merged locale.
11+
*
12+
* @example
13+
* const de_CH_with_fallbacks = mergeLocales([ de_CH, de, en ]);
14+
*/
15+
export function mergeLocales(locales: LocaleDefinition[]): LocaleDefinition {
16+
const merged: LocaleDefinition = {} as LocaleDefinition;
17+
18+
for (const locale of locales) {
19+
for (const key in locale) {
20+
if (merged[key] === undefined) {
21+
if (typeof locale[key] === 'object') {
22+
merged[key] = { ...locale[key] };
23+
} else {
24+
merged[key] = locale[key];
25+
}
26+
} else {
27+
if (typeof locale[key] === 'object') {
28+
merged[key] = { ...locale[key], ...merged[key] };
29+
} else {
30+
// Primitive values cannot be merged
31+
}
32+
}
33+
}
34+
}
35+
36+
return merged;
37+
}

test/utils/merge-locales.spec.ts

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import { describe, expect, it } from 'vitest';
2+
import type { LocaleDefinition } from '../../src';
3+
import { mergeLocales } from '../../src/utils/merge-locales';
4+
5+
describe('mergeLocales', () => {
6+
it('should not overwrite entries', () => {
7+
const locale1: LocaleDefinition = {
8+
title: 'a',
9+
person: { firstName: ['a'] },
10+
finance: { credit_card: { visa: ['a'] } },
11+
};
12+
const locale2: LocaleDefinition = {
13+
title: 'b',
14+
person: { firstName: ['b'] },
15+
finance: { credit_card: { mastercard: ['b'] } },
16+
};
17+
const locale3: LocaleDefinition = {
18+
title: 'c',
19+
person: { firstName: ['c'] },
20+
finance: { credit_card: {} },
21+
};
22+
23+
const merged = mergeLocales([locale1, locale2, locale3]);
24+
25+
expect(merged).toEqual({
26+
title: 'a',
27+
person: { firstName: ['a'] },
28+
finance: { credit_card: { visa: ['a'] } },
29+
});
30+
});
31+
32+
it('should extend categories', () => {
33+
const locale1: LocaleDefinition = {
34+
title: 'a',
35+
location: { city: ['a'] },
36+
person: { first_name: ['a'] },
37+
};
38+
const locale2: LocaleDefinition = {
39+
title: 'b',
40+
animal: { cat: ['b'] },
41+
person: { last_name: ['b'] },
42+
};
43+
const locale3: LocaleDefinition = {
44+
title: 'c',
45+
color: { human: ['c'] },
46+
person: {},
47+
};
48+
49+
const merged = mergeLocales([locale1, locale2, locale3]);
50+
51+
expect(merged).toEqual({
52+
title: 'a',
53+
animal: { cat: ['b'] },
54+
color: { human: ['c'] },
55+
location: { city: ['a'] },
56+
person: { first_name: ['a'], last_name: ['b'] },
57+
});
58+
});
59+
});

0 commit comments

Comments
 (0)