diff --git a/beszel/site/src/components/lang-toggle.tsx b/beszel/site/src/components/lang-toggle.tsx index b90dc0e..2120491 100644 --- a/beszel/site/src/components/lang-toggle.tsx +++ b/beszel/site/src/components/lang-toggle.tsx @@ -6,6 +6,7 @@ import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigge import { useTranslation } from "react-i18next" import languages from "../lib/languages.json" import { cn } from "@/lib/utils" +import { setLang } from "@/lib/i18n" export function LangToggle() { const { i18n } = useTranslation() @@ -27,7 +28,7 @@ export function LangToggle() { i18n.changeLanguage(lang)} + onClick={() => setLang(lang)} > {label} diff --git a/beszel/site/src/components/navbar.tsx b/beszel/site/src/components/navbar.tsx index 5c72c41..4f08491 100644 --- a/beszel/site/src/components/navbar.tsx +++ b/beszel/site/src/components/navbar.tsx @@ -29,7 +29,7 @@ import { import { AddSystemButton } from "./add-system" import { useTranslation } from "react-i18next" -const CommandPalette = lazy(() => import("./command-palette.tsx")) +const CommandPalette = lazy(() => import("./command-palette")) const isMac = navigator.platform.toUpperCase().indexOf("MAC") >= 0 @@ -38,7 +38,7 @@ export default function Navbar() { return (
- + diff --git a/beszel/site/src/components/routes/settings/general.tsx b/beszel/site/src/components/routes/settings/general.tsx index 8f1371f..6dd0df5 100644 --- a/beszel/site/src/components/routes/settings/general.tsx +++ b/beszel/site/src/components/routes/settings/general.tsx @@ -10,6 +10,7 @@ import { useState, useEffect } from "react" // import { Input } from '@/components/ui/input' import { useTranslation } from "react-i18next" import languages from "../../../lib/languages.json" +import { setLang } from "@/lib/i18n" export default function SettingsProfilePage({ userSettings }: { userSettings: UserSettings }) { const { t, i18n } = useTranslation() @@ -54,7 +55,7 @@ export default function SettingsProfilePage({ userSettings }: { userSettings: Us - setLang(lang)}> diff --git a/beszel/site/src/lib/i18n.ts b/beszel/site/src/lib/i18n.ts index a1864fa..2bf47ce 100644 --- a/beszel/site/src/lib/i18n.ts +++ b/beszel/site/src/lib/i18n.ts @@ -1,37 +1,24 @@ import i18n from "i18next" import { initReactI18next } from "react-i18next" -import en from "../locales/en/translation.json" -import es from "../locales/es/translation.json" -import fr from "../locales/fr/translation.json" -import de from "../locales/de/translation.json" -import ru from "../locales/ru/translation.json" -import zhHans from "../locales/zh-CN/translation.json" -import zhHant from "../locales/zh-HK/translation.json" - // Custom language detector to use localStorage const languageDetector: any = { type: "languageDetector", async: true, detect: (callback: (lng: string) => void) => { const savedLanguage = localStorage.getItem("i18nextLng") - const fallbackLanguage = (() => { - switch (navigator.language) { - case "zh-CN": - case "zh-SG": - case "zh-MY": - case "zh": - case "zh-Hans": - return "zh-CN" - case "zh-HK": - case "zh-TW": - case "zh-MO": - case "zh-Hant": - return "zh-HK" - default: - return navigator.language - } - })() + const zhVariantMap: Record = { + "zh-CN": "zh-CN", + "zh-SG": "zh-CN", + "zh-MY": "zh-CN", + zh: "zh-CN", + "zh-Hans": "zh-CN", + "zh-HK": "zh-HK", + "zh-TW": "zh-HK", + "zh-MO": "zh-HK", + "zh-Hant": "zh-HK", + } + const fallbackLanguage = zhVariantMap[navigator.language] || navigator.language callback(savedLanguage || fallbackLanguage) }, init: () => {}, @@ -40,25 +27,39 @@ const languageDetector: any = { }, } +// Function to dynamically load translation files +async function loadMessages(locale: string) { + try { + const translation = await import(`../locales/${locale}/translation.json`) + return translation.default + } catch (error) { + console.error(`Error loading ${locale}`, error) + // Fallback to English if translation fails to load + const enTranslation = await import(`../locales/en/translation.json`) + return enTranslation.default + } +} + i18n .use(languageDetector) .use(initReactI18next) .init({ - resources: { - en: { translation: en }, - es: { translation: es }, - fr: { translation: fr }, - de: { translation: de }, - ru: { translation: ru }, - // Chinese (Simplified) - "zh-CN": { translation: zhHans }, - // Chinese (Traditional) - "zh-HK": { translation: zhHant }, - }, + resources: {}, // Start with empty resources fallbackLng: "en", interpolation: { escapeValue: false, }, }) +// Function to dynamically activate a language +export async function setLang(locale: string) { + const messages = await loadMessages(locale) + i18n.addResourceBundle(locale, "translation", messages) + await i18n.changeLanguage(locale) +} + +// Initialize with detected/saved language +const initialLanguage = localStorage.getItem("i18nextLng") || navigator.language +setLang(initialLanguage) + export { i18n } diff --git a/beszel/site/src/main.tsx b/beszel/site/src/main.tsx index 8ad2346..1822dfd 100644 --- a/beszel/site/src/main.tsx +++ b/beszel/site/src/main.tsx @@ -1,5 +1,6 @@ import "./index.css" -import { Suspense, lazy, useEffect, StrictMode } from "react" +// import { Suspense, lazy, useEffect, StrictMode } from "react" +import { Suspense, lazy, useEffect } from "react" import ReactDOM from "react-dom/client" import Home from "./components/routes/home.tsx" import { ThemeProvider } from "./components/theme-provider.tsx" @@ -87,7 +88,9 @@ const Layout = () => { return ( <> -
{Navbar()}
+
+ +
{copyContent && (