web/i18n: dynamically determine languages from i18n folder contents
This commit is contained in:
parent
3e9296ac1e
commit
8fd2c66441
3 changed files with 50 additions and 114 deletions
|
@ -1,125 +1,48 @@
|
||||||
import i18n from 'sveltekit-i18n';
|
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';
|
import languages from '$i18n/languages.json';
|
||||||
|
|
||||||
export const defaultLocale = 'en';
|
const locFiles = import.meta.glob('$i18n/*/**/*.json');
|
||||||
|
const parsedLocfiles: StructuredLocfileInfo = {};
|
||||||
|
|
||||||
export const config: Config = {
|
for (const [ path, loader ] of Object.entries(locFiles)) {
|
||||||
translations: {
|
const [,, lang, ...keyComponents ] = path.split('/');
|
||||||
en: { languages },
|
const key = keyComponents.map(k => k.replace('.json', '')).join('.');
|
||||||
ru: { languages },
|
parsedLocfiles[lang] = {
|
||||||
},
|
...parsedLocfiles[lang],
|
||||||
loaders: [
|
[key]: loader as GenericImport
|
||||||
{
|
};
|
||||||
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,
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
const defaultLocale = 'en';
|
||||||
locale: 'ru',
|
const config: Config = {
|
||||||
key: 'tabs',
|
translations: Object.keys(parsedLocfiles).reduce((obj, lang) => {
|
||||||
loader: async () => (
|
return {
|
||||||
await import(`$i18n/ru/tabs.json`)
|
...obj,
|
||||||
).default,
|
[lang]: { languages }
|
||||||
},
|
}
|
||||||
{
|
}, {}),
|
||||||
locale: 'ru',
|
loaders: Object.entries(parsedLocfiles).map(([ lang, keys ]) => {
|
||||||
key: 'a11y.tabs',
|
return Object.entries(keys).map(([ key, importer ]) => {
|
||||||
loader: async () => (
|
return {
|
||||||
await import(`$i18n/ru/a11y/tabs.json`)
|
locale: lang,
|
||||||
).default,
|
key,
|
||||||
},
|
loader: () => importer().then(
|
||||||
{
|
l => l.default as LocalizationContent
|
||||||
locale: 'ru',
|
)
|
||||||
key: 'save',
|
}
|
||||||
loader: async () => (
|
});
|
||||||
await import(`$i18n/ru/save.json`)
|
}).flat()
|
||||||
).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,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export { defaultLocale };
|
||||||
export const {
|
export const {
|
||||||
t, loading, locales, locale, translations,
|
t, loading, locales, locale, translations,
|
||||||
loadTranslations, addTranslations, setLocale, setRoute
|
loadTranslations, addTranslations, setLocale, setRoute
|
||||||
|
|
|
@ -6,3 +6,5 @@ export type RecursivePartial<Type> = {
|
||||||
Type[Key] extends object | undefined ? RecursivePartial<Type[Key]> :
|
Type[Key] extends object | undefined ? RecursivePartial<Type[Key]> :
|
||||||
Type[Key];
|
Type[Key];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type DefaultImport<T> = () => Promise<{ default: T }>;
|
||||||
|
|
11
web/src/lib/types/i18n.ts
Normal file
11
web/src/lib/types/i18n.ts
Normal 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>
|
||||||
|
>;
|
Loading…
Reference in a new issue