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 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
|
||||
|
|
|
@ -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
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