mirror of
https://github.com/blakeblackshear/frigate.git
synced 2026-07-26 13:48:59 +03:00
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>
This commit is contained in:
co-authored by
Josh Hawkins
parent
db541abed4
commit
d34533981f
@@ -0,0 +1,77 @@
|
||||
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;
|
||||
};
|
||||
@@ -5,6 +5,7 @@ import { ApiProvider } from "@/api";
|
||||
import { IconContext } from "react-icons";
|
||||
import { TooltipProvider } from "@/components/ui/tooltip";
|
||||
import { StatusBarMessagesProvider } from "@/context/statusbar-provider";
|
||||
import { LanguageProvider } from "./language-provider";
|
||||
import { StreamingSettingsProvider } from "./streaming-settings-provider";
|
||||
import { AuthProvider } from "./auth-context";
|
||||
|
||||
@@ -18,15 +19,17 @@ function providers({ children }: TProvidersProps) {
|
||||
<AuthProvider>
|
||||
<ApiProvider>
|
||||
<ThemeProvider defaultTheme="system" storageKey="frigate-ui-theme">
|
||||
<TooltipProvider>
|
||||
<IconContext.Provider value={{ size: "20" }}>
|
||||
<StatusBarMessagesProvider>
|
||||
<StreamingSettingsProvider>
|
||||
{children}
|
||||
</StreamingSettingsProvider>
|
||||
</StatusBarMessagesProvider>
|
||||
</IconContext.Provider>
|
||||
</TooltipProvider>
|
||||
<LanguageProvider>
|
||||
<TooltipProvider>
|
||||
<IconContext.Provider value={{ size: "20" }}>
|
||||
<StatusBarMessagesProvider>
|
||||
<StreamingSettingsProvider>
|
||||
{children}
|
||||
</StreamingSettingsProvider>
|
||||
</StatusBarMessagesProvider>
|
||||
</IconContext.Provider>
|
||||
</TooltipProvider>
|
||||
</LanguageProvider>
|
||||
</ThemeProvider>
|
||||
</ApiProvider>
|
||||
</AuthProvider>
|
||||
|
||||
@@ -23,9 +23,7 @@ export const colorSchemes: ColorScheme[] = [
|
||||
// eslint-disable-next-line react-refresh/only-export-components
|
||||
export const friendlyColorSchemeName = (className: string): string => {
|
||||
const words = className.split("-").slice(1); // Exclude the first word (e.g., 'theme')
|
||||
return words
|
||||
.map((word) => word.charAt(0).toUpperCase() + word.slice(1))
|
||||
.join(" ");
|
||||
return "menu.theme." + words.join(".");
|
||||
};
|
||||
|
||||
type ThemeProviderProps = {
|
||||
|
||||
Reference in New Issue
Block a user