i18next / react-i18next

Internationalization for react done right. Using the i18next i18n ecosystem.
https://react.i18next.com
MIT License
9.2k stars 1.02k forks source link

Next.js 14 RSC: createContext is not a function #1759

Closed molily closed 2 months ago

molily commented 2 months ago

Hello, first of all, thank you for this project!

🐛 Bug Report

Importing react-i18next in a Next.js server component causes a createContext is not a function error.

I have created a fresh Next.js 14 project with create-next-app featuring the app dir: https://github.com/molily/next-js-rsc-react-i18next

I've been following this tutorial to integrate translations with i18next: https://locize.com/blog/next-app-dir-i18n/

While this tutorial implements a many things, I tried to implement the minimal translation logic for React Server Components first: https://github.com/molily/next-js-rsc-react-i18next/blob/main/src/app/i18n/useTranslation.ts

import { createInstance } from 'i18next';
import { initReactI18next } from 'react-i18next';

const fallbackLng = 'en';
const supportedLngs = [ fallbackLng, 'de' ] as const;

const useTranslation = async (lng?: string) => {
  const finalLng = lng || fallbackLng;

  const i18nInstance = createInstance();

  await i18nInstance.
    use(initReactI18next).
    init({
      // debug: true,
      supportedLngs,
      fallbackLng,
      lng,
      resources: {
        en: { hello: 'Hello world!' }
      }
    });

  return {
    t: i18nInstance.getFixedT(finalLng),
    i18n: i18nInstance
  };
};

export { supportedLngs, useTranslation };

The page: https://github.com/molily/next-js-rsc-react-i18next/blob/main/src/app/page.tsx

import { useTranslation } from "./i18n/useTranslation";

export default async function Home() {
  const { t } = await useTranslation();

  return (
    <main>
      {t('hello')}
    </main>
  );
}

Note that this page does not have 'use client', so it should be handled as a server component. (Which is fine for now – I'd like to get RSCs working first before adding the client-side logic, like the tutorial suggests.)

Opening this page gives me the error:

 ⨯ TypeError: (0 , react__WEBPACK_IMPORTED_MODULE_0__.createContext) is not a function
    at eval (webpack-internal:///(rsc)/./node_modules/react-i18next/dist/es/context.js:22:73)
    at (rsc)/./node_modules/react-i18next/dist/es/context.js (/Users/molily/projects/next14-fresh/.next/server/vendor-chunks/react-i18next.js:60:1)

There's no createContext in RSCs, so that error seems logical – but shouldn't this approach be catered to RSC specifically? Am I doing something wrong?

Note: Compared to the tutorial, I've changed

import { initReactI18next } from 'react-i18next/initReactI18next'

to

import { initReactI18next } from 'react-i18next'

because Next complained that there is no module at 'react-i18next/initReactI18next'.

Reproducing

Your Environment

Thanks a lot for looking into this, much appreciated.

adrai commented 2 months ago

that initReactI18Next part is important to be like this: import { initReactI18next } from 'react-i18next/initReactI18next' else client only code will be loaded....

Here is the export in the package.json https://github.com/i18next/react-i18next/blob/master/package.json#L42

so tldr;

keep import { initReactI18next } from 'react-i18next/initReactI18next'

molily commented 2 months ago

Thanks! I got a "Module not found" error in my real app, but I could pin this down to the custom Webpack setup and I was able to fix the error.