reactjslocaleserver-side-renderingnext.js13app-router

How to get locale in non-page server-side components on Nextjs 14 app router?


I am developing a new Nextjs 14 app router project, using next-i18n-router & react-i18next to handle localization. I followed nextjs documentation and the provided tutorials in localization setup:

I can access locale for client-side components via useTranslation Hook, however in server-side components I get locale in params object only in page components, then I have to make prop-drilling until I reach the target component to access current locale in nested server-side components.

Is there any way to avoid prop-drilling in server-side components to access current locale?

here is an example of page server-side component:

import styles from './page.module.css';
import ExampleClientComponent from '@/components/ExampleClientComponent';
import initTranslations from '../i18n';

export default async function Home({ params: { locale } }) {
  const { t } = await initTranslations(locale, ['home']);

  return (
    <main className={styles.main}>
      <h1>{t('header')}</h1>
      <ExampleClientComponent />
      <ExampleServerComponent locale={locale}/>
    </main>
  );
}

That's what I want:

import styles from './page.module.css';
import ExampleClientComponent from '@/components/ExampleClientComponent';
import initTranslations from '../i18n';

export default async function Home({ params: { locale } }) {
  const { t } = await initTranslations(locale, ['home']);

  return (
    <main className={styles.main}>
      <h1>{t('header')}</h1>
      <ExampleClientComponent />
      <ExampleServerComponent /> // To have a way to get access to locale without passing it as prop
    </main>
  );
}

Solution

  • I have solved prop-drilling by extracting locale from request headers

    Here is the example server-side component without passing local as prop:

    import initTranslations from '../i18n';
    import { headers } from "next/headers";
    
    export default async function ExampleServerComponent() {
      const reqHeaders = headers();
      const cookie = reqHeaders.get("Cookie");
      
      local = cookie?.split("NEXT_LOCALE=").at(1)?.substring(0, 2); // "en" | "ar";
      const { t } = await initTranslations(locale, ['home']);
    
      return (
          <h1>{t('title')}</h1>
      );
    }