Improve system language handling in settings

This commit is contained in:
Zoe Roux 2024-05-23 14:46:58 +02:00
parent 61e25f8b95
commit 12742162ff
No known key found for this signature in database
5 changed files with 20 additions and 12 deletions

View File

@ -68,15 +68,18 @@ const clientStorage = {
export const clientPersister = createSyncStoragePersister({ storage: clientStorage }); export const clientPersister = createSyncStoragePersister({ storage: clientStorage });
const sysLang = getLocales()[0].languageCode ?? "en";
i18next.use(initReactI18next).init({ i18next.use(initReactI18next).init({
interpolation: { interpolation: {
escapeValue: false, escapeValue: false,
}, },
returnEmptyString: false, returnEmptyString: false,
fallbackLng: "en", fallbackLng: "en",
lng: storage.getString("language") ?? getLocales()[0].languageCode ?? "en", lng: storage.getString("language") ?? sysLang,
resources, resources,
}); });
// @ts-expect-error Manually added value
i18next.systemLanguage = sysLang;
const NavigationThemeProvider = ({ children }: { children: ReactNode }) => { const NavigationThemeProvider = ({ children }: { children: ReactNode }) => {
const theme = useTheme(); const theme = useTheme();

View File

@ -18,12 +18,12 @@
* along with Kyoo. If not, see <https://www.gnu.org/licenses/>. * along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
*/ */
import { readCookie } from "@kyoo/models/src/account-internal";
import i18next, { type InitOptions } from "i18next"; import i18next, { type InitOptions } from "i18next";
import type { AppContext, AppInitialProps, AppProps } from "next/app"; import type { AppContext, AppInitialProps, AppProps } from "next/app";
import { type ComponentType, useState } from "react"; import { type ComponentType, useState } from "react";
import { I18nextProvider } from "react-i18next"; import { I18nextProvider } from "react-i18next";
import resources from "../../../translations"; import resources from "../../../translations";
import { readCookie } from "@kyoo/models/src/account-internal";
export const withTranslations = ( export const withTranslations = (
AppToTranslate: ComponentType<AppProps> & { AppToTranslate: ComponentType<AppProps> & {
@ -47,6 +47,7 @@ export const withTranslations = (
...commonOptions, ...commonOptions,
lng: props.pageProps.__lang, lng: props.pageProps.__lang,
}); });
i18next.systemLanguage = props.pageProps.__sysLang;
return i18next; return i18next;
}); });
@ -58,16 +59,15 @@ export const withTranslations = (
}; };
AppWithTranslations.getInitialProps = async (ctx: AppContext) => { AppWithTranslations.getInitialProps = async (ctx: AppContext) => {
const props: AppInitialProps = await AppToTranslate.getInitialProps(ctx); const props: AppInitialProps = await AppToTranslate.getInitialProps(ctx);
const lng = const sysLng = ctx.router.locale || ctx.router.defaultLocale || "en";
readCookie(ctx.ctx.req?.headers.cookie, "language") || const lng = readCookie(ctx.ctx.req?.headers.cookie, "language") || sysLng;
ctx.router.locale ||
ctx.router.defaultLocale ||
"en";
await i18n.init({ await i18n.init({
...commonOptions, ...commonOptions,
lng, lng,
}); });
i18n.systemLanguage = sysLng;
props.pageProps.__lang = lng; props.pageProps.__lang = lng;
props.pageProps.__sysLang = sysLng;
return props; return props;
}; };

View File

@ -19,6 +19,6 @@
"~/*": ["src/*"] "~/*": ["src/*"]
} }
}, },
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"], "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", "../../packages/ui/src/i18n-d.d.ts"],
"exclude": ["node_modules"] "exclude": ["node_modules"]
} }

View File

@ -26,4 +26,8 @@ declare module "i18next" {
returnNull: false; returnNull: false;
resources: { translation: typeof en }; resources: { translation: typeof en };
} }
interface i18n {
systemLanguage: string;
}
} }

View File

@ -18,7 +18,7 @@
* along with Kyoo. If not, see <https://www.gnu.org/licenses/>. * along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
*/ */
import { setUserTheme, storeData, useUserTheme } from "@kyoo/models"; import { deleteData, setUserTheme, storeData, useUserTheme } from "@kyoo/models";
import { Link, Select } from "@kyoo/primitives"; import { Link, Select } from "@kyoo/primitives";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { Preference, SettingsContainer } from "./base"; import { Preference, SettingsContainer } from "./base";
@ -37,8 +37,9 @@ export const GeneralSettings = () => {
const changeLanguage = (lang: string) => { const changeLanguage = (lang: string) => {
if (lang === "system") { if (lang === "system") {
i18n.changeLanguage(i18n.options.lng as string); i18n.changeLanguage(i18n.systemLanguage);
return deleteData("language");
return;
} }
storeData("language", lang); storeData("language", lang);
i18n.changeLanguage(lang); i18n.changeLanguage(lang);
@ -66,7 +67,7 @@ export const GeneralSettings = () => {
> >
<Select <Select
label={t("settings.general.language.label")} label={t("settings.general.language.label")}
value={i18n.resolvedLanguage!} value={i18n.resolvedLanguage! === i18n.systemLanguage ? "system" : i18n.resolvedLanguage!}
onValueChange={(value) => changeLanguage(value)} onValueChange={(value) => changeLanguage(value)}
values={["system", ...Object.keys(i18n.options.resources!)]} values={["system", ...Object.keys(i18n.options.resources!)]}
getLabel={(key) => getLabel={(key) =>