diff --git a/app/entry.server.tsx b/app/entry.server.tsx index f09a7b9db..f5fea6893 100644 --- a/app/entry.server.tsx +++ b/app/entry.server.tsx @@ -23,7 +23,7 @@ export default async function handleRequest( const instance = createInstance() const lng = appContext.lang // biome-ignore lint/suspicious/noExplicitAny: - const ns = i18nextOpts.getRouteNamespaces(context as any) + const ns = i18nextOpts(lng).getRouteNamespaces(context as any) await instance .use(initReactI18next) // Tell our instance to use react-i18next diff --git a/app/localization/i18n.server.ts b/app/localization/i18n.server.ts index f92e0b7d5..4ab19285d 100644 --- a/app/localization/i18n.server.ts +++ b/app/localization/i18n.server.ts @@ -2,17 +2,18 @@ import { RemixI18Next } from "remix-i18next/server" import i18n from "~/localization/i18n" // your i18n configuration file import { resources } from "./resource" -const i18next = new RemixI18Next({ - detection: { - supportedLanguages: i18n.supportedLngs, - fallbackLanguage: i18n.fallbackLng, - }, - // This is the configuration for i18next used - // when translating messages server-side only - i18next: { - ...i18n, - resources, - }, -}) +const i18next = (fallbackLanguage?: string) => + new RemixI18Next({ + detection: { + supportedLanguages: i18n.supportedLngs, + fallbackLanguage: fallbackLanguage || "en", + }, + // This is the configuration for i18next used + // when translating messages server-side only + i18next: { + ...i18n, + resources, + }, + }) export default i18next diff --git a/app/localization/i18n.ts b/app/localization/i18n.ts index e42f33007..8171d8ab0 100644 --- a/app/localization/i18n.ts +++ b/app/localization/i18n.ts @@ -6,7 +6,7 @@ export default { supportedLngs: supportedLanguages, // This is the language you want to use in case // if the user language is not in the supportedLngs - fallbackLng: "en", + fallbackLng: false, // The default namespace of i18next is "translation", but you can customize it here defaultNS: "common", } satisfies Omit diff --git a/app/localization/resource.ts b/app/localization/resource.ts index 39301aee6..11e2526b9 100644 --- a/app/localization/resource.ts +++ b/app/localization/resource.ts @@ -1,7 +1,8 @@ import bosnian from "../../resources/locales/bs/common.json" import english from "../../resources/locales/en/common.json" +import french from "../../resources/locales/fr/common.json" -const languages = ["en", "bs"] as const +const languages = ["en", "bs", "fr"] as const export const supportedLanguages = [...languages] export type Language = (typeof languages)[number] @@ -18,6 +19,9 @@ export const resources: Record = { bs: { common: bosnian, }, + fr: { + common: french, + }, } declare module "i18next" { diff --git a/app/server/context.ts b/app/server/context.ts index ddf43b2b8..30d85d86a 100644 --- a/app/server/context.ts +++ b/app/server/context.ts @@ -1,6 +1,8 @@ import type { Context } from "hono" import { i18next } from "remix-hono/i18next" import { getClientEnv, getServerEnv } from "~/env.server" +import i18n from "~/localization/i18n" +import type { Language } from "~/localization/resource" export const getLoadContext = async (c: Context) => { // get the locale from the context @@ -11,7 +13,7 @@ export const getLoadContext = async (c: Context) => { const env = getServerEnv() return { - lang: locale, + lang: i18n.supportedLngs.includes(locale as Language) ? locale : "en", t, isProductionDeployment: env.APP_ENV === "production", env, diff --git a/app/server/index.ts b/app/server/index.ts index a81ff3d2a..871e52bf7 100644 --- a/app/server/index.ts +++ b/app/server/index.ts @@ -5,7 +5,7 @@ import { getLoadContext } from "./context" export default await createHonoServer({ configure(server) { - server.use("*", i18next(i18nextOpts)) + server.use("*", i18next(i18nextOpts())) }, defaultLogger: false, getLoadContext, diff --git a/resources/locales/fr/common.json b/resources/locales/fr/common.json new file mode 100644 index 000000000..b09ac4697 --- /dev/null +++ b/resources/locales/fr/common.json @@ -0,0 +1,25 @@ +{ + "hi": "React Router est cool!", + "navigation": { + "back": "Go back", + "home": "Back to home" + }, + "error": { + "500": { + "title": "Something went wrong!", + "description": "Looks like something unexpected happened on the server." + }, + "404": { + "title": "Page Not found!", + "description": "Oops! The page you're looking for seems to have vanished into thin air." + }, + "403": { + "title": "Unauthorized!", + "description": "Looks like you can't access this page." + }, + "200": { + "title": "Something went wrong!", + "description": "Looks like something unexpected happened on the server." + } + } +}