Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(locales): add mergeLocales utility #1707

Merged
merged 13 commits into from
Jan 13, 2023
37 changes: 37 additions & 0 deletions src/utils/merge-locales.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import type { LocaleDefinition } from '..';

/**
* Merges the given locales into one locale.
* The locales are merged in the order they are given.
* The first locale that provides an entry for a category will be used for that.
* Mutating the category entries in the returned locale will also mutate the entries in the respective source locale.
*
* @param locales The locales to merge.
* @returns The newly merged locale.
*
* @example
* const de_CH_with_fallbacks = mergeLocales([ de_CH, de, en ]);
*/
export function mergeLocales(locales: LocaleDefinition[]): LocaleDefinition {
ST-DDT marked this conversation as resolved.
Show resolved Hide resolved
const merged: LocaleDefinition = {} as LocaleDefinition;

for (const locale of locales) {
for (const key in locale) {
if (merged[key] === undefined) {
if (typeof locale[key] === 'object') {
ST-DDT marked this conversation as resolved.
Show resolved Hide resolved
merged[key] = { ...locale[key] };
} else {
merged[key] = locale[key];
}
} else {
if (typeof locale[key] === 'object') {
merged[key] = { ...locale[key], ...merged[key] };
} else {
// Do nothing
ST-DDT marked this conversation as resolved.
Show resolved Hide resolved
}
}
}
}

return merged;
}
59 changes: 59 additions & 0 deletions test/utils/merge-locales.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import { describe, expect, it } from 'vitest';
import type { LocaleDefinition } from '../../src';
import { mergeLocales } from '../../src/utils/merge-locales';

describe('mergeLocales', () => {
it('should overwrite locales', () => {
const locale1: LocaleDefinition = {
title: 'a',
person: { firstName: ['a'] },
finance: { credit_card: { visa: ['a'] } },
};
const locale2: LocaleDefinition = {
title: 'b',
person: { firstName: ['b'] },
finance: { credit_card: { mastercard: ['b'] } },
Shinigami92 marked this conversation as resolved.
Show resolved Hide resolved
};
const locale3: LocaleDefinition = {
title: 'c',
person: { firstName: ['c'] },
finance: { credit_card: {} },
};

const merged = mergeLocales([locale1, locale2, locale3]);

expect(merged).toEqual({
title: 'a',
person: { firstName: ['a'] },
finance: { credit_card: { visa: ['a'] } },
xDivisionByZerox marked this conversation as resolved.
Show resolved Hide resolved
});
});

it('should extend locales', () => {
const locale1: LocaleDefinition = {
title: 'a',
location: { city: ['a'] },
person: { first_name: ['a'] },
};
const locale2: LocaleDefinition = {
title: 'b',
animal: { cat: ['b'] },
person: { last_name: ['b'] },
};
const locale3: LocaleDefinition = {
title: 'c',
color: { human: ['c'] },
person: {},
};

const merged = mergeLocales([locale1, locale2, locale3]);

expect(merged).toEqual({
title: 'a',
animal: { cat: ['b'] },
color: { human: ['c'] },
location: { city: ['a'] },
person: { first_name: ['a'], last_name: ['b'] },
});
});
});
ST-DDT marked this conversation as resolved.
Show resolved Hide resolved