From 3129822c49b9e9dde41fcf51f79506e37dbc8ce3 Mon Sep 17 00:00:00 2001 From: Kalle <38327916+Sendouc@users.noreply.github.com> Date: Sun, 25 Sep 2022 15:55:22 +0300 Subject: [PATCH] Remember selected language Closes #921 --- app/components/layout/LanguageChanger.tsx | 8 ++--- app/modules/i18n/i18next.server.ts | 10 ++++++ app/modules/i18n/index.ts | 2 +- app/root.tsx | 40 ++++++++++++++--------- 4 files changed, 40 insertions(+), 20 deletions(-) diff --git a/app/components/layout/LanguageChanger.tsx b/app/components/layout/LanguageChanger.tsx index 360def10c..7afa3c3ed 100644 --- a/app/components/layout/LanguageChanger.tsx +++ b/app/components/layout/LanguageChanger.tsx @@ -1,6 +1,6 @@ import { useTranslation } from "react-i18next"; import { languages } from "~/modules/i18n"; -import { Button } from "../Button"; +import { LinkButton } from "../Button"; import { GlobeIcon } from "../icons/Globe"; import { Popover } from "../Popover"; @@ -14,17 +14,17 @@ export function LanguageChanger() { >
{languages.map((lang) => ( - + ))}
diff --git a/app/modules/i18n/i18next.server.ts b/app/modules/i18n/i18next.server.ts index aa04d710f..b591e1d3b 100644 --- a/app/modules/i18n/i18next.server.ts +++ b/app/modules/i18n/i18next.server.ts @@ -1,10 +1,20 @@ +import { createCookie } from "@remix-run/node"; import Backend from "i18next-fs-backend"; import { resolve } from "node:path"; import { RemixI18Next } from "remix-i18next"; import { config } from "./config"; +const TEN_YEARS_IN_SECONDS = 31_536_000 * 10; + +export const i18nCookie = createCookie("i18n", { + sameSite: "lax", + path: "/", + maxAge: TEN_YEARS_IN_SECONDS, +}); + export const i18next = new RemixI18Next({ detection: { + cookie: i18nCookie, supportedLanguages: config.supportedLngs, fallbackLanguage: config.fallbackLng, }, diff --git a/app/modules/i18n/index.ts b/app/modules/i18n/index.ts index 49426891f..d46768a1f 100644 --- a/app/modules/i18n/index.ts +++ b/app/modules/i18n/index.ts @@ -1,4 +1,4 @@ export { i18nLoader } from "./loader"; export { i18Instance } from "./loader.server"; -export { i18next } from "./i18next.server"; +export { i18next, i18nCookie } from "./i18next.server"; export { DEFAULT_LANGUAGE, languages } from "./config"; diff --git a/app/root.tsx b/app/root.tsx index e3cf27bd1..a68a4e44c 100644 --- a/app/root.tsx +++ b/app/root.tsx @@ -25,7 +25,7 @@ import { db } from "./db"; import type { FindAllPatrons } from "./db/models/users/queries.server"; import type { UserWithPlusTier } from "./db/types"; import { getUser } from "./modules/auth"; -import { DEFAULT_LANGUAGE, i18next } from "./modules/i18n"; +import { DEFAULT_LANGUAGE, i18nCookie, i18next } from "./modules/i18n"; import { useChangeLanguage } from "remix-i18next"; import { useTranslation } from "react-i18next"; import { Theme, ThemeHead, useTheme, ThemeProvider } from "./modules/theme"; @@ -33,7 +33,12 @@ import { getThemeSession } from "./modules/theme/session.server"; import { COMMON_PREVIEW_IMAGE } from "./utils/urls"; import { ConditionalScrollRestoration } from "./components/ConditionalScrollRestoration"; -export const unstable_shouldReload: ShouldReloadFunction = () => false; +export const unstable_shouldReload: ShouldReloadFunction = ({ url }) => { + // reload on language change so the selected language gets set into the cookie + const lang = url.searchParams.get("lng"); + + return Boolean(lang); +}; export const links: LinksFunction = () => { return [ @@ -68,19 +73,24 @@ export const loader: LoaderFunction = async ({ request }) => { const locale = await i18next.getLocale(request); const themeSession = await getThemeSession(request); - return json({ - locale, - theme: themeSession.getTheme(), - patrons: db.users.findAllPatrons(), - user: user - ? { - discordAvatar: user.discordAvatar, - discordId: user.discordId, - id: user.id, - plusTier: user.plusTier, - } - : undefined, - }); + return json( + { + locale, + theme: themeSession.getTheme(), + patrons: db.users.findAllPatrons(), + user: user + ? { + discordAvatar: user.discordAvatar, + discordId: user.discordId, + id: user.id, + plusTier: user.plusTier, + } + : undefined, + }, + { + headers: { "Set-Cookie": await i18nCookie.serialize(locale) }, + } + ); }; export const handle = {