From 90c5ed948deed801adab609a81ea9a3328bf30f6 Mon Sep 17 00:00:00 2001 From: Simon Reinisch Date: Fri, 1 Nov 2024 09:32:12 +0100 Subject: [PATCH] feat: improve language file loading performance --- src/i18n/index.ts | 41 ++++++++++++++++++++++------------------ src/store/state/index.ts | 17 +++-------------- vite.config.ts | 3 +++ 3 files changed, 29 insertions(+), 32 deletions(-) diff --git a/src/i18n/index.ts b/src/i18n/index.ts index 5855907..a23848b 100644 --- a/src/i18n/index.ts +++ b/src/i18n/index.ts @@ -1,20 +1,22 @@ -import { watchEffect } from 'vue'; import { createI18n, IntlNumberFormat } from 'vue-i18n'; -import de from './locales/de.json'; -import en from './locales/en.json'; -import br from './locales/pt-br.json'; -import tr from './locales/tr.json'; -import cz from './locales/cz.json'; +import type en from './locales/en.json'; + +const imports: Record Promise<{ default: string }>> = { + cze: () => import('./locales/cze.json?raw'), + en: () => import('./locales/en.json?raw'), + de: () => import('./locales/de.json?raw'), + tr: () => import('./locales/tr.json?raw'), + 'pt-br': () => import('./locales/pt-br.json?raw') +} as const; export type MessageSchema = typeof en; const browserLocale = navigator.language.slice(0, 2).toLowerCase(); -const messages: Record = { en, de, br, tr, cz } as const; -export const availableLocales = Object.keys(messages); +export const availableLocales = Object.keys(imports); export const initialLocale = availableLocales.includes(browserLocale) ? browserLocale : 'en'; -export type AvailableLocale = keyof typeof messages; +export type AvailableLocale = keyof typeof imports; const numberFormats: IntlNumberFormat = { currency: { @@ -27,16 +29,19 @@ const numberFormats: IntlNumberFormat = { } }; -/* eslint-disable @typescript-eslint/no-explicit-any */ export const i18n = createI18n({ legacy: false, - fallbackLocale: 'en', - locale: initialLocale, - messages: messages as any, - numberFormats: Object.fromEntries(availableLocales.map((locale) => [locale, numberFormats])) + locale: initialLocale }); -// Synchronize the i18n locale with the browser locale -watchEffect(() => { - document.documentElement.lang = i18n.global.locale.value; -}); +export const changeLocale = async (locale: AvailableLocale, currency?: Intl.NumberFormatOptions) => { + const messages = JSON.parse((await imports[locale]()).default); + const numberFormat: IntlNumberFormat = { ...numberFormats, currency: { ...numberFormats.currency, ...currency } }; + + document.documentElement.lang = locale; + i18n.global.setLocaleMessage(locale, messages); + i18n.global.setNumberFormat(locale, numberFormat); + i18n.global.locale.value = locale; +}; + +await changeLocale(browserLocale); diff --git a/src/store/state/index.ts b/src/store/state/index.ts index d96daf2..b37beef 100644 --- a/src/store/state/index.ts +++ b/src/store/state/index.ts @@ -1,5 +1,5 @@ import { useStateHistory, useTime } from '@composables'; -import { AvailableLocale, i18n } from '@i18n/index'; +import { AvailableLocale, changeLocale, i18n } from '@i18n/index'; import { Storage } from '@storage/index'; import { moveInArrays, readFile, remove, uuid } from '@utils'; import { DeepReadonly, inject, reactive, readonly, ShallowRef, shallowRef, watch, watchEffect } from 'vue'; @@ -94,20 +94,9 @@ export const createDataStore = (storage?: Storage): Store => { return [...currentYear.expenses, ...currentYear.income]; }; - watchEffect(() => { - for (const locale of i18n.global.availableLocales) { - const formats = i18n.global.getNumberFormat(locale); - - i18n.global.setNumberFormat(locale, { - ...formats, - currency: { ...formats.currency, currency: state.currency } - }); - } - }); - watch( - () => state.locale, - (locale) => (i18n.global.locale.value = locale) + () => [state.locale, state.currency], + ([locale, currency]) => changeLocale(locale, { currency }) ); storage?.sync({ diff --git a/vite.config.ts b/vite.config.ts index 65f1ba1..9f9fbc0 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -30,6 +30,9 @@ export default defineConfig({ '@styles': '/src/styles' } }, + build: { + target: 'ES2022' + }, plugins: [ tsconfigPaths({ loose: true }), optimizeCssModules(),