Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions app/localization/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@ Due to the fact that the server does not care about loading in additional resour
pass in `resources` to the `i18next` instance. This provides all the languages to your server which allows it to render
the correct language on the server.

The server side also first checks the search param for the `lng` param and uses that as the language, otherwise it checks
the cookie and if it has the users preferred language set. If the cookie is not set it defaults to the fallback language.

This is useful if the user navigates to a page without the query param set, the server will still be able to render the page in the correct language.

## Client-side

The client-side is a bit more complicated. We do not want to load in all the languages on the client side as it would
Expand Down
11 changes: 11 additions & 0 deletions app/localization/cookie.server.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { createCookie } from "react-router";

Check failure on line 1 in app/localization/cookie.server.ts

View workflow job for this annotation

GitHub Actions / ⬣ Biome lint

format

File content differs from formatting output
import { getServerEnv } from "~/env.server";

const env = getServerEnv()

export const localeCookie = createCookie("lng", {
path: "/",
sameSite: "lax",
secure: env.NODE_ENV === "production",
httpOnly: true,
});
3 changes: 3 additions & 0 deletions app/localization/i18n.server.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
import { RemixI18Next } from "remix-i18next/server"

Check failure on line 1 in app/localization/i18n.server.ts

View workflow job for this annotation

GitHub Actions / ⬣ Biome lint

format

File content differs from formatting output
import i18n from "~/localization/i18n" // your i18n configuration file
import { localeCookie } from "./cookie.server"
import { resources } from "./resource"

const i18next = new RemixI18Next({
detection: {
supportedLanguages: i18n.supportedLngs,
fallbackLanguage: i18n.fallbackLng,
cookie: localeCookie,
order: ["searchParams", "cookie"]
},
// This is the configuration for i18next used
// when translating messages server-side only
Expand Down
21 changes: 19 additions & 2 deletions app/root.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,33 @@
import { useTranslation } from "react-i18next"
import { Links, Meta, Outlet, Scripts, ScrollRestoration, isRouteErrorResponse, useRouteError } from "react-router"
import {
Links,
Meta,
Outlet,
Scripts,
ScrollRestoration,
data,
isRouteErrorResponse,
useRouteError,
} from "react-router"
import type { LinksFunction } from "react-router"
import { useChangeLanguage } from "remix-i18next/react"
import type { Route } from "./+types/root"
import { LanguageSwitcher } from "./library/language-switcher"
import { localeCookie } from "./localization/cookie.server"
import { ClientHintCheck, getHints } from "./services/client-hints"
import tailwindcss from "./tailwind.css?url"

export async function loader({ context, request }: Route.LoaderArgs) {
const { lang, clientEnv } = context
const hints = getHints(request)
return { lang, clientEnv, hints }
return data(
{ lang, clientEnv, hints },
{
headers: {
"Set-Cookie": await localeCookie.serialize(lang),
},
}
)
}

export const links: LinksFunction = () => [{ rel: "stylesheet", href: tailwindcss }]
Expand Down
Loading