Hello,
I’m currently working on a multi-tenant aoo where the user has the option to select the default locale from a list of available locales (ar, en). for now, the app supports only one language at a time, either ar or en, and I need to dynamically set next-i18next default locale to the one that the user has selected.
Here's how I've implemented it so far:
- In
getServerSideProps, I am fetching the tenant settings and getting the tenant locale. - To set the
langattribute in the HTMLdocumentElement, I set theNEXT_LOCALEcookie andContent-Languageheader to the tenant locale. - pass the locale to
serverSideTranslationsto fetch the correct translations. - In my custom
_document.tsx, I read the locale fromNEXT_LOCALEto set thelanganddirattributes dynamically based on the user's chosen locale.
here is how my code looks like:
index.tsx
import { GetServerSideProps } from "next";
import { serverSideTranslations } from "next-i18next/serverSideTranslations";
import i18nextConfig from "@/next-i18next.config.js";
export const getServerSideProps: GetServerSideProps = async ({ locale, res }) => {
//fetch tenant settings
const data = await fetch("some-url");
const tenant = await data.json();
//get tenant locale
const tenant_locale = tenant?.locale;
const appLocale = tenant_locale ?? locale ?? i18nextConfig.i18n.defaultLocale;
//set the locale in the cookies, so I can access it in `_document.tsx`
res.setHeader("Set-Cookie", `NEXT_LOCALE=${appLocale}`);
res.setHeader("Content-Language", appLocale);
return {
props: {
//pass appLocale to the func to fetch the right locales
...(await serverSideTranslations(appLocale, ["common", "chapter_contents", "validation"], i18nextConfig))
}
};
};
_document.tsx:
import Document, { DocumentContext, DocumentProps, Head, Html, Main, NextScript } from "next/document";
type Props = DocumentProps & {
// add custom document props
};
class MyDocument extends Document<Props> {
static async getInitialProps(ctx: DocumentContext) {
const initialProps = await Document.getInitialProps(ctx);
let locale = ctx.locale;
if (ctx.req && ctx.req.headers.cookie) {
//get app locale from header cookies
locale = ctx.req.headers.cookie
.split(";")
.find((c) => c.trim().startsWith("NEXT_LOCALE="))
?.split("=")[1];
}
return { ...initialProps, locale };
}
render() {
const currentLocale = this.props.locale;
const dir = currentLocale === "ar" ? "rtl" : "ltr";
return (
<Html
lang={currentLocale}
dir={dir}
>
<Head />
<body>
<Main />
<NextScript />
</body>
</Html>
);
}
}
export default MyDocument;
However, I’ve noticed that on the first page render, while the lang attribute of the document element is correctly set, it reverts back to the default locale from my configuration whenever the route changes.
my questions and issues are:
- How can I dynamically change the
defaultLocalein both i18next and Next.js based on user selection? - Is setting the
NEXT_LOCALEcookie and accessing it in_document.tsxa correct approach for setting the rightlanganddir? Are there better alternatives? - Is there a more efficient or recommended approach to achieving dynamic default locale selection based on user preferences?
- Why does Next.js reset the
langattribute to the default locale in the config on each route change, and and how can I prevent this? - When I log the locale using
useRouter, it returns the default locale, it does not change until I add the language prefix to the URL (e.g.,/en/path). How can I change the locale without changing the URL?
any help or guidance would be greatly appreciated. Thank you!