1
0
Fork 0
mirror of https://github.com/immich-app/immich.git synced 2025-01-09 21:36:46 +01:00
immich/web/src/lib/i18n.spec.ts
2024-07-04 22:56:54 -05:00

82 lines
3.2 KiB
TypeScript

import { langs } from '$lib/constants';
import messages from '$lib/i18n/en.json';
import { getClosestAvailableLocale } from '$lib/utils/i18n';
import { exec as execCallback } from 'node:child_process';
import { readFileSync, readdirSync } from 'node:fs';
import { promisify } from 'node:util';
type Messages = { [key: string]: string | Messages };
const exec = promisify(execCallback);
function setEmptyMessages(messages: Messages) {
const copy = { ...messages };
for (const key in copy) {
const message = copy[key];
if (typeof message === 'string') {
copy[key] = '';
} else if (typeof message === 'object') {
setEmptyMessages(message);
}
}
return copy;
}
describe('i18n', () => {
test('no missing messages', async () => {
const { stdout } = await exec('npx svelte-i18n extract -c svelte.config.js "src/**/*"');
const extractedMessages: Messages = JSON.parse(stdout);
const existingMessages = setEmptyMessages(messages);
// Only translations directly using the store seem to get extracted
expect({ ...extractedMessages, ...existingMessages }).toEqual(existingMessages);
});
describe('loaders', () => {
const languageFiles = readdirSync('src/lib/i18n').sort();
for (const filename of languageFiles) {
test(`${filename} should have a loader`, async () => {
const code = filename.replaceAll('.json', '');
const item = langs.find((lang) => lang.weblateCode === code || lang.code === code);
expect(item, `${filename} has no loader`).toBeDefined();
if (!item) {
return;
}
// verify it loads the right file
const module: { default?: unknown } = await item.loader();
const translations = JSON.stringify(module.default, null, 2).trim();
const content = readFileSync(`src/lib/i18n/${filename}`).toString().trim();
expect(translations === content, `${item.name} did not load ${filename}`).toEqual(true);
});
}
});
describe('getClosestAvailableLocale', () => {
const allLocales = ['ar', 'bg', 'en', 'en-US', 'en-DE', 'zh-Hans', 'zh-Hans-HK'];
it('returns undefined on mismatch', () => {
expect(getClosestAvailableLocale([], allLocales)).toBeUndefined();
expect(getClosestAvailableLocale(['invalid'], allLocales)).toBeUndefined();
});
it('returns the first matching locale', () => {
expect(getClosestAvailableLocale(['invalid', 'ar', 'bg'], allLocales)).toBe('ar');
expect(getClosestAvailableLocale(['bg'], allLocales)).toBe('bg');
expect(getClosestAvailableLocale(['bg', 'invalid', 'ar'], allLocales)).toBe('bg');
});
it('returns the locale for a less specific match', () => {
expect(getClosestAvailableLocale(['ar-AE'], allLocales)).toBe('ar-AE');
expect(getClosestAvailableLocale(['ar-AE', 'en'], allLocales)).toBe('ar-AE');
expect(getClosestAvailableLocale(['zh-Hans-HK', 'zh-Hans'], allLocales)).toBe('zh-Hans-HK');
});
it('ignores the locale for a more specific match', () => {
expect(getClosestAvailableLocale(['zh'], allLocales)).toBeUndefined();
expect(getClosestAvailableLocale(['de', 'zh', 'en-US'], allLocales)).toBe('en-US');
});
});
});