frigate/web/src/context/language-provider.tsx

78 lines
2.0 KiB
TypeScript
Raw Normal View History

feat: add i18n (translation/localization) (#16877) * Translation module init * Add more i18n keys * fix: fix string wrong * refactor: use namespace translation file * chore: add more translation key * fix: fix some page name error * refactor: change Trans tag for t function * chore: fix some key not work * chore: fix SearchFilterDialog i18n key error Co-authored-by: Josh Hawkins <32435876+hawkeye217@users.noreply.github.com> * chore: fix en i18n file filter missing some keys * chore: add some i18n keys * chore: add more i18n keys again * feat: add search page i18n * feat: add explore model i18n keys * Update web/src/components/menu/GeneralSettings.tsx Co-authored-by: Josh Hawkins <32435876+hawkeye217@users.noreply.github.com> * Update web/src/components/menu/GeneralSettings.tsx Co-authored-by: Josh Hawkins <32435876+hawkeye217@users.noreply.github.com> * Update web/src/components/menu/GeneralSettings.tsx Co-authored-by: Josh Hawkins <32435876+hawkeye217@users.noreply.github.com> * feat: add more live i18n keys * feat: add more search setting i18n keys * fix: remove some comment * fix: fix some setting page url error * Update web/src/views/settings/SearchSettingsView.tsx Co-authored-by: Josh Hawkins <32435876+hawkeye217@users.noreply.github.com> * fix: add system missing keys * fix: update password update i18n keys * chore: remove outdate translation.json file * fix: fix exploreSettings error * chore: add object setting i18n keys * Update web/src/views/recording/RecordingView.tsx Co-authored-by: Josh Hawkins <32435876+hawkeye217@users.noreply.github.com> * Update web/public/locales/en/components/filter.json Co-authored-by: Josh Hawkins <32435876+hawkeye217@users.noreply.github.com> * Update web/src/components/overlay/ExportDialog.tsx Co-authored-by: Josh Hawkins <32435876+hawkeye217@users.noreply.github.com> * feat: add more i18n keys * fix: fix motionDetectionTuner html node * feat: add more page i18n keys * fix: cameraStream i18n keys error * feat: add Player i18n keys * feat: add more toast i18n keys * feat: change explore setting name * feat: add more document title i18n keys * feat: add more search i18n keys * fix: fix accessDenied i18n keys error * chore: add objectType i18n * chore: add inputWithTags i18n * chore: add SearchFilterDialog i18n * Update web/src/views/settings/ObjectSettingsView.tsx Co-authored-by: Josh Hawkins <32435876+hawkeye217@users.noreply.github.com> * Update web/src/views/settings/ObjectSettingsView.tsx Co-authored-by: Josh Hawkins <32435876+hawkeye217@users.noreply.github.com> * Update web/src/views/settings/ObjectSettingsView.tsx Co-authored-by: Josh Hawkins <32435876+hawkeye217@users.noreply.github.com> * Update web/src/views/settings/ObjectSettingsView.tsx Co-authored-by: Josh Hawkins <32435876+hawkeye217@users.noreply.github.com> * Update web/src/views/settings/ObjectSettingsView.tsx Co-authored-by: Josh Hawkins <32435876+hawkeye217@users.noreply.github.com> * chore: add some missing i18n keys * chore: remove most import { t } from "i18next"; --------- Co-authored-by: Josh Hawkins <32435876+hawkeye217@users.noreply.github.com>
2025-03-16 18:36:20 +03:00
import { createContext, useContext, useState, useEffect, useMemo } from "react";
import i18next from "i18next";
type LanguageProviderState = {
language: string;
systemLanguage: string;
setLanguage: (language: string) => void;
};
const initialState: LanguageProviderState = {
language: i18next.language || "en",
systemLanguage: "en",
setLanguage: () => null,
};
const LanguageProviderContext =
createContext<LanguageProviderState>(initialState);
export function LanguageProvider({
children,
defaultLanguage = "en",
storageKey = "frigate-ui-language",
...props
}: {
children: React.ReactNode;
defaultLanguage?: string;
storageKey?: string;
}) {
const [language, setLanguage] = useState<string>(() => {
try {
const storedData = localStorage.getItem(storageKey);
const newLanguage = storedData || defaultLanguage;
i18next.changeLanguage(newLanguage);
return newLanguage;
} catch (error) {
// eslint-disable-next-line no-console
console.error("Error retrieving language data from storage:", error);
return defaultLanguage;
}
});
const systemLanguage = useMemo<string>(() => {
if (typeof window === "undefined") return "en";
return window.navigator.language;
}, []);
useEffect(() => {
if (language === systemLanguage) return;
i18next.changeLanguage(language);
}, [language, systemLanguage]);
const value = {
language,
systemLanguage,
setLanguage: (language: string) => {
localStorage.setItem(storageKey, language);
setLanguage(language);
window.location.reload();
},
};
return (
<LanguageProviderContext.Provider {...props} value={value}>
{children}
</LanguageProviderContext.Provider>
);
}
// eslint-disable-next-line react-refresh/only-export-components
export const useLanguage = () => {
const context = useContext(LanguageProviderContext);
if (context === undefined)
throw new Error("useLanguage must be used within a LanguageProvider");
return context;
};