frigate/web/src/context/language-provider.tsx
Josh Hawkins 44d44f87ac
i18n tweaks (#17865)
* Add plural variant to i18n selected key

Weblate needs both keys to populate other languages

* move smart capitalization logic into language provider

* fix key
2025-04-23 06:19:20 -06:00

81 lines
2.1 KiB
TypeScript

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(() => {
// set document lang for smart capitalization
document.documentElement.lang = language;
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;
};