#How to set the default locale based on the user's selected locale in the admin dashboard

1 messages · Page 1 of 1 (latest)

lean furnace
#

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:

  1. In getServerSideProps, I am fetching the tenant settings and getting the tenant locale.
  2. To set the lang attribute in the HTML documentElement, I set the NEXT_LOCALE cookie and Content-Language header to the tenant locale.
  3. pass the locale to serverSideTranslations to fetch the correct translations.
  4. In my custom _document.tsx, I read the locale from NEXT_LOCALE to set the lang and dir attributes 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:

  1. How can I dynamically change the defaultLocale in both i18next and Next.js based on user selection?
  2. Is setting the NEXT_LOCALE cookie and accessing it in _document.tsx a correct approach for setting the right lang and dir? Are there better alternatives?
  3. Is there a more efficient or recommended approach to achieving dynamic default locale selection based on user preferences?
  4. Why does Next.js reset the lang attribute to the default locale in the config on each route change, and and how can I prevent this?
  5. 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!

gritty relicBOT
#

Hi @lean furnace. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave:

#

Based on the information provided in the extracts, here are some insights that might help you:

  1. Dynamically changing the defaultLocale in both i18next and Next.js based on user selection: The extracts do not provide a direct way to dynamically change the defaultLocale in the next.config.js file. However, you can leverage the NEXT_LOCALE cookie to override the accept-language header. This cookie can be set using a language switcher and when a user comes back to the site, it will leverage the locale specified in the cookie when redirecting from / to the correct locale location. source (https://nextjs.org/docs/pages/building-your-application/routing/internationalization)

  2. Setting the NEXT_LOCALE cookie and accessing it in _document.tsx: This seems to be a valid approach based on the information provided in the extracts. The NEXT_LOCALE cookie is used by Next.js to override the accept-language header and redirect to the correct locale location. source (https://nextjs.org/docs/pages/building-your-application/routing/internationalization)

  3. More efficient or recommended approach to achieving dynamic default locale selection: The extracts suggest using the NEXT_LOCALE cookie for locale selection. Additionally, you can use the localeDetection option in the i18n configuration to disable automatic locale detection. When localeDetection is set to false, Next.js will no longer automatically redirect based on the user's preferred locale and will only provide locale information detected from either the locale-based domain or locale path. source (https://nextjs.org/docs/pages/building-your-application/routing/internationalization)

#
  1. Why Next.js resets the lang attribute to the default locale on each route change: The extracts do not provide specific information on why this happens. However, it might be related to how Next.js handles routing with internationalization. Each source in the headers is automatically prefixed to handle the configured locales unless you add locale: false to the header. If locale: false is used, you must prefix the source with a locale for it to be matched correctly. source (https://nextjs.org/docs/pages/api-reference/next-config-js/headers)

  2. Changing the locale without changing the URL: The extracts do not provide a direct solution to this. However, you might be able to achieve this by using a custom middleware to add custom routing rules. You can use the NextRequest and NextResponse objects from 'next/server' to handle the request and response. source (https://nextjs.org/docs/pages/building-your-application/routing/internationalization)

Please note that these are suggestions based on the information provided in the extracts and might not fully solve your issues. You might need to refer to the Next.js documentation or seek help from the Next.js community for more specific solutions.

Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: