feat: implement i18n lazy loading optimization

🚀 Performance improvements:
- Replace static language imports with dynamic imports
- Load only current language on startup instead of all 13 languages
- Implement on-demand loading when switching languages

📦 Bundle optimization:
- Reduce initial bundle size by avoiding preloading all language files
- Add resource caching to prevent reloading same language
- Support all 13 languages: en, ru, zh, fa, tt, id, ar, ko, tr, de, es, jp, zhtw

🔧 Technical changes:
- Convert i18n.ts to use dynamic import() for language resources
- Add async initializeLanguage() for app startup
- Create useI18n hook for language management with loading states
- Update main.tsx for async language initialization
- Fix language display labels in settings dropdown
- Maintain backward compatibility with existing language system

 Fixed issues:
- Resolve infinite loop in React components
- Fix missing language labels in settings UI
- Prevent circular dependencies in language loading
- Add proper error handling and fallback mechanisms
This commit is contained in:
Tunglies
2025-09-06 14:05:36 +08:00
parent f70b8b1213
commit 0daa8720cd
5 changed files with 142 additions and 43 deletions

View File

@@ -1,29 +1,59 @@
import i18n from "i18next";
import { initReactI18next } from "react-i18next";
import en from "@/locales/en.json";
import ru from "@/locales/ru.json";
import zh from "@/locales/zh.json";
import fa from "@/locales/fa.json";
import tt from "@/locales/tt.json";
import id from "@/locales/id.json";
import ar from "@/locales/ar.json";
import ko from "@/locales/ko.json";
import tr from "@/locales/tr.json";
export const languages = { en, ru, zh, fa, tt, id, ar, ko, tr };
export const supportedLanguages = [
"en",
"ru",
"zh",
"fa",
"tt",
"id",
"ar",
"ko",
"tr",
"de",
"es",
"jp",
"zhtw",
];
const resources = Object.fromEntries(
Object.entries(languages).map(([key, value]) => [
key,
{ translation: value },
]),
export const languages: Record<string, any> = supportedLanguages.reduce(
(acc, lang) => {
acc[lang] = {};
return acc;
},
{} as Record<string, any>,
);
export const loadLanguage = async (language: string) => {
try {
const module = await import(`@/locales/${language}.json`);
return module.default;
} catch (error) {
console.warn(`Failed to load language ${language}, fallback to zh`);
const fallback = await import("@/locales/zh.json");
return fallback.default;
}
};
i18n.use(initReactI18next).init({
resources,
resources: {},
lng: "zh",
fallbackLng: "zh",
interpolation: {
escapeValue: false,
},
});
export const changeLanguage = async (language: string) => {
if (!i18n.hasResourceBundle(language, "translation")) {
const resources = await loadLanguage(language);
i18n.addResourceBundle(language, "translation", resources);
}
await i18n.changeLanguage(language);
};
export const initializeLanguage = async (initialLanguage: string = "zh") => {
await changeLanguage(initialLanguage);
};