web/i18n: dynamically determine languages from i18n folder contents

This commit is contained in:
dumbmoron 2024-07-03 19:28:44 +00:00
parent 3e9296ac1e
commit 8fd2c66441
No known key found for this signature in database
3 changed files with 50 additions and 114 deletions

View file

@ -1,125 +1,48 @@
import i18n from 'sveltekit-i18n';
import type { Config } from 'sveltekit-i18n';
import type { Config } from 'sveltekit-i18n'
import type {
GenericImport,
StructuredLocfileInfo,
LocalizationContent
} from '$lib/types/i18n';
import languages from '$i18n/languages.json';
export const defaultLocale = 'en';
const locFiles = import.meta.glob('$i18n/*/**/*.json');
const parsedLocfiles: StructuredLocfileInfo = {};
export const config: Config = {
translations: {
en: { languages },
ru: { languages },
},
loaders: [
{
locale: 'en',
key: 'tabs',
loader: async () => (
await import(`$i18n/en/tabs.json`)
).default,
},
{
locale: 'en',
key: 'a11y.tabs',
loader: async () => (
await import(`$i18n/en/a11y/tabs.json`)
).default,
},
{
locale: 'en',
key: 'save',
loader: async () => (
await import(`$i18n/en/save.json`)
).default,
},
{
locale: 'en',
key: 'a11y.save',
loader: async () => (
await import(`$i18n/en/a11y/save.json`)
).default,
},
{
locale: 'en',
key: 'a11y.meowbalt',
loader: async () => (
await import(`$i18n/en/a11y/meowbalt.json`)
).default,
},
{
locale: 'en',
key: 'settings',
loader: async () => (
await import(`$i18n/en/settings.json`)
).default,
},
{
locale: 'en',
key: 'general',
loader: async () => (
await import(`$i18n/en/general.json`)
).default,
},
{
locale: 'en',
key: 'a11y.general',
loader: async () => (
await import(`$i18n/en/a11y/general.json`)
).default,
},
for (const [ path, loader ] of Object.entries(locFiles)) {
const [,, lang, ...keyComponents ] = path.split('/');
const key = keyComponents.map(k => k.replace('.json', '')).join('.');
parsedLocfiles[lang] = {
...parsedLocfiles[lang],
[key]: loader as GenericImport
};
}
{
locale: 'ru',
key: 'tabs',
loader: async () => (
await import(`$i18n/ru/tabs.json`)
).default,
},
{
locale: 'ru',
key: 'a11y.tabs',
loader: async () => (
await import(`$i18n/ru/a11y/tabs.json`)
).default,
},
{
locale: 'ru',
key: 'save',
loader: async () => (
await import(`$i18n/ru/save.json`)
).default,
},
{
locale: 'ru',
key: 'a11y.save',
loader: async () => (
await import(`$i18n/ru/a11y/save.json`)
).default,
},
{
locale: 'ru',
key: 'a11y.meowbalt',
loader: async () => (
await import(`$i18n/ru/a11y/meowbalt.json`)
).default,
},
{
locale: 'ru',
key: 'general',
loader: async () => (
await import(`$i18n/ru/general.json`)
).default,
},
{
locale: 'ru',
key: 'a11y.general',
loader: async () => (
await import(`$i18n/ru/a11y/general.json`)
).default,
},
],
const defaultLocale = 'en';
const config: Config = {
translations: Object.keys(parsedLocfiles).reduce((obj, lang) => {
return {
...obj,
[lang]: { languages }
}
}, {}),
loaders: Object.entries(parsedLocfiles).map(([ lang, keys ]) => {
return Object.entries(keys).map(([ key, importer ]) => {
return {
locale: lang,
key,
loader: () => importer().then(
l => l.default as LocalizationContent
)
}
});
}).flat()
};
export { defaultLocale };
export const {
t, loading, locales, locale, translations,
loadTranslations, addTranslations, setLocale, setRoute

View file

@ -6,3 +6,5 @@ export type RecursivePartial<Type> = {
Type[Key] extends object | undefined ? RecursivePartial<Type[Key]> :
Type[Key];
};
export type DefaultImport<T> = () => Promise<{ default: T }>;

11
web/src/lib/types/i18n.ts Normal file
View file

@ -0,0 +1,11 @@
import type { DefaultImport } from '$lib/types/generic';
type LanguageCode = string;
type KeyPath = string;
export type GenericImport = DefaultImport<unknown>;
export type LocalizationContent = Record<string, string>;
export type StructuredLocfileInfo = Record<
LanguageCode,
Record<KeyPath, GenericImport>
>;