i18next / next-i18next

The easiest way to translate your NextJs apps.
https://next.i18next.com
MIT License
5.53k stars 762 forks source link

react-i18next:: You will need to pass in an i18next instance by using initReactI18next when running build when there is translation in top level layout #1917

Closed bryanltobing closed 1 year ago

bryanltobing commented 2 years ago

πŸ› Bug Report

image

This is only happening when I run build script and my layout call useTranslation hook

To Reproduce

A small repo to reproduce

This is the only place I call useTranslation hook

// My _app.tsx
import "../styles/globals.css";
import type { AppProps } from "next/app";
import { appWithTranslation, useTranslation } from "next-i18next";
import React from "react";

function MyApp({ Component, pageProps }: AppProps) {
  return (
    <Layout>
      <Component {...pageProps} />
    </Layout>
  );
}

const Layout: React.FC<{ children: React.ReactNode }> = ({ children }) => {
  const { t } = useTranslation();

  return (
    <div>
      <div>{t("hello-world")}</div>
      {children}
    </div>
  );
};

export default appWithTranslation(MyApp);

my only page is pages/index.tsx

and I already called the serverSideTranslation

export async function getStaticProps({ locale }: any) {
  return {
    props: {
      ...(await serverSideTranslations(locale, ["common"])),
    },
  };
}

the translation is working, and I believe as mentioned here https://github.com/i18next/next-i18next/issues/1840#issuecomment-1145614232 image

the only issue is that there are warnings happen when running build

Expected behavior

There's no warning that says react-i18next:: You will need to pass in an i18next instance by using initReactI18next when running build script

Your Environment

belgattitude commented 1 year ago

@statico My comment about peer-dependencies relies on the fact that the package manager will dedupe versions (yarn does).

If you don't have a reproduction, I would be grateful if you could run this in your project root directory:

npx envinfo
pnpm why -r next-i18next i18next

And

npx -y pnpm-deduplicate --list

That would be super helpful. Thx in advance.

PS:

belgattitude commented 1 year ago

@statico there's also some insights here https://github.com/pnpm/pnpm/issues/5351#issuecomment-1304295362

stale[bot] commented 1 year ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

spyhere commented 1 year ago

Not stale. I didn't get it, so is it possible to get rid of this warning or not?

rikkit commented 1 year ago

If the error is caused by your use of Yarn 2+ PnP or pnpm package managers, then this will be fixed in the v13 release, fixed in #1966

If it's not that, then there is a problem with your code where you're instantiating react-i18next separately to next-i18next and this workaround might help you.

spyhere commented 1 year ago

@rikkit I use yarn, but not sure what causes problem in my case, I think I tried every solution that internet could give me, but to no avail...

I'm instantiating react-i18next according to doc and then import it in __app.tsx, not sure that problem is with my code.

Screenshot 2022-11-17 at 15 51 15

As @adrai said at the beginning of this thread the problem is that i18next is not yet initialised - you can see it in the screenshot that I applied, however I tried this:

import i18next from "i18next"

function myApp({ Component, pageProps }) {
   ...
   if (!i18next.isInitialized) { // this is not helping
    return null
  }

  return (
  ...
  )
}

React.Suspense mentioned in the docs are not solving the issue either.

I have a index.tsx in pages that uses another component inside that uses t, everything is made regarding documentation (serverSideTranslations in index.tsx page) and I still have this stupid warning. Also I have this warning while trying to make tests with jest & react-testing-library. This is super annoying.

belgattitude commented 1 year ago

Do you have custom 404 or 500 nextjs pages ?

I've written some ideas to debug here:

It will make more sense in the upcoming release (V13.0.0), but some things can be applied.

Could you try this:

yarn why i18next
yarn why react-i18next

That said I suggest you to try to not rely on automatic next-i18next.config.js loading. Can you try with

// _app.tsx
import type { AppProps } from 'next/app'
import { appWithTranslation } from 'next-i18next'
import nextI18NextConfig from '../next-i18next.config.js'
const MyApp = ({ Component, pageProps }: AppProps) => (
  <Component {...pageProps} />
)
export default appWithTranslation(MyApp, nextI18NextConfig)

And create a wrapper like +/- this:

// ie: ./lib/i18n/getServerTranslations.ts
import type { SSRConfig, UserConfig } from 'next-i18next';
import { serverSideTranslations } from 'next-i18next/serverSideTranslations';
import nextI18nextConfig from '../../next-i18next.config';

export const getServerTranslations = async (
  locale: string,
  namespacesRequired?: string[] | undefined,
  configOverride?: UserConfig
): Promise<SSRConfig> => {
  const config = configOverride ?? nextI18nextConfig;
  return serverSideTranslations(locale, namespacesRequired, config);
};

And replace calls to serverSideTranslations in your getServerProps by it

?

PS: Be sure you don't have duplicates as well (https://github.com/i18next/next-i18next/issues/1917#issuecomment-1302418939). BTW tested with pnpm, yarn, monorepo or not. (not npm though).

belgattitude commented 1 year ago

Also I have this warning while trying to make tests with jest & react-testing-library. This is super annoying.

About this, I had luck by mocking the provider:

PS: I mean it's a choice and the links are opinionated... I prefer to test on keys rather than translations (lighter too)

spyhere commented 1 year ago

That said I suggest you to try to not rely on automatic next-i18next.config.js loading. Can you try with

// _app.tsx
import type { AppProps } from 'next/app'
import { appWithTranslation } from 'next-i18next'
import nextI18NextConfig from '../next-i18next.config.js'
const MyApp = ({ Component, pageProps }: AppProps) => (
  <Component {...pageProps} />
)
export default appWithTranslation(MyApp, nextI18NextConfig)

Bless you! Explicit import removed the warning. And there were no package duplicates when I checked.

Though I didn't manage to follow your mock examples. For some reason I was having You are passing an undefined module error and I couldn't fix it, so tried this instead:


// setupTest.js

jest.mock("next-i18next", () => ({
  useTranslation: () => {
    return {
      t: (str) => str,
      i18n: {
        // eslint-disable-next-line @typescript-eslint/no-empty-function
        changeLanguage: () => new Promise(() => {}),
      },
    };
  },
  initReactI18next: {
    type: "3rdParty",
    init: jest.fn(),
  },
}));
belgattitude commented 1 year ago

Bless you! Explicit import removed the warning. And there were no package duplicates when I checked.

Thanks for confirmation. I'll plan to adapt the examples https://github.com/i18next/next-i18next/pull/2013 and bring more clarity around this. v13.0.0 is around the corner (will contribute to help with duplicates as well).

belgattitude commented 1 year ago

Update: v13.0.0 is released and might partially fix this issue by moving i18next, react-i18next to peer-deps.

There's a new TROUBLESHOOT document to help with installation, specifically: You will need to pass in an i18next instance

If you experienced issues before, could you try v13.0.0 and let me know ?

PS: I'm planning to tackle the dual packaging hazards in the upcoming weeks.

spyhere commented 1 year ago

@belgattitude I can confirm that v13.0.0 works great, and it shows no warnings even without passing configs explicitly inside _app.

megacherry commented 1 year ago

If anyone else also has the problem, for me it was the sideEffects: false option in package.json.

I have adjusted it as follows:

"sideEffects": [ "./src/locales/i18n.ts" ]

@belgattitude : If you want, you can include that in the troubleshooting section.

belgattitude commented 1 year ago

@megacherry Thx. Can you clarify the sideEffects ? Nextjs version or do you publish a specific package with your locales ? what's in i18n.ts ?

megacherry commented 1 year ago

@belgattitude: sorry, it's a local file, and it looks like:

import LanguageDetector from 'i18next-browser-languagedetector'
import {initReactI18next} from 'react-i18next'
import {defaultLang} from '../config'
import {deLocales, deForm, deMail, deCookie} from './de'
import {enLocales, enForm, enMail, enCookie} from './en'

let lng = defaultLang.value

if (typeof window !== 'undefined') {
  lng = localStorage.getItem('i18nextLng') || defaultLang.value
}

const resources = {
  de: {translations: deLocales, form: deForm, mail: deMail, cookie: deCookie},
  en: {translations: enLocales, form: enForm, mail: enMail, cookie: enCookie},
}

i18n
  .use(LanguageDetector)
  .use(initReactI18next)
  .init({
    resources,
    lng,
    fallbackLng: defaultLang.value,
    debug: false,
    ns: ['translations'],
    defaultNS: 'translations',
    interpolation: {
      escapeValue: false,
    },
  })

export default i18n
belgattitude commented 1 year ago

I see, as you import react-i18next in this file the "sideEffect" might possibly change the way webpack will tree-shake this. But I'm really not sure. Few questions to help me understand (sorry if it looks a bit extra, but without I'm not sure)

Or anything that you feel useful, I have hard time to figure out how can it be related :smile:

megacherry commented 1 year ago
GuiMoraesDev commented 1 year ago

I'm facing this error but in dev mode.

A workaround to fix this is fixing the react-i18next version to 12.0.0.

My stack: { "dependencies": { "i18next": "^22.0.4", "next": "13.0.1", "next-language-detector": "^1.0.2", "ni18n": "^1.0.5", "react": "18.2.0", "react-dom": "18.2.0", "react-i18next": "12.0.0", }, "devDependencies": { ... "@types/react": "18.0.24", ... "typescript": "4.8.4" } }

mylesshie commented 1 year ago

I have the same error for a new next app. my package.json file: { "dependencies": { "@types/node": "18.11.12", "@types/react": "18.0.26", "@types/react-dom": "18.0.9", "ahooks": "^3.7.2", "antd": "4", "eslint": "8.29.0", "eslint-config-next": "13.0.6", "i18next": "^22.2.0", "next": "13.0.6", "next-i18next": "^13.0.0", "next-plugin-antd-less": "^1.8.0", "react": "18.2.0", "react-dom": "18.2.0", "react-i18next": "^12.1.1", "sass": "^1.56.2", "typescript": "4.9.4" }, }

GuiMoraesDev commented 1 year ago

I have the same error for a new next app. my package.json file: { "dependencies": { "@types/node": "18.11.12", "@types/react": "18.0.26", "@types/react-dom": "18.0.9", "ahooks": "^3.7.2", "antd": "4", "eslint": "8.29.0", "eslint-config-next": "13.0.6", "i18next": "^22.2.0", "next": "13.0.6", "next-i18next": "^13.0.0", "next-plugin-antd-less": "^1.8.0", "react": "18.2.0", "react-dom": "18.2.0", "react-i18next": "^12.1.1", "sass": "^1.56.2", "typescript": "4.9.4" }, }

Try to downgrade the react-i18next to version 12.0.0

belgattitude commented 1 year ago

Can't figure out how to reproduce the issue with latest v13. Our e2e tests passes and I've migrated 4 repos to latest version (ie: nextjs-monorepo-example)

Mmm, frustrating :smiling_face_with_tear:

So there's something to discover.

Anyone could send me a reprod repo ?

PS: whenever I have a reprod I can easily work on it, ie: https://github.com/i18next/next-i18next/issues/1917#issuecomment-1285401978 / https://github.com/bryantobing12/layout-reproduce-i18next/pull/1

cantutar commented 1 year ago

I have the same error for a new next app. my package.json file: { "dependencies": { "@types/node": "18.11.12", "@types/react": "18.0.26", "@types/react-dom": "18.0.9", "ahooks": "^3.7.2", "antd": "4", "eslint": "8.29.0", "eslint-config-next": "13.0.6", "i18next": "^22.2.0", "next": "13.0.6", "next-i18next": "^13.0.0", "next-plugin-antd-less": "^1.8.0", "react": "18.2.0", "react-dom": "18.2.0", "react-i18next": "^12.1.1", "sass": "^1.56.2", "typescript": "4.9.4" }, }

Try to downgrade the react-i18next to version 12.0.0

i tried that on my project it wont work 😒 using next 13.0.6

cantutar commented 1 year ago

My error is its not projecting files correctly and throws that warning that only caused with getStaticProps with getStaticPaths added image the other sites without its working normally + weirdly its default(en) is working normally

Naman-Garaaz commented 1 year ago

image getting this issue in my react native project. "i18next": "^22.0.6", "react-i18next": "^12.0.0", "react-native-translation": "^1.1.0",

Using the same versions in another react native project both has same react native version. But issue persist in one not another.

adrai commented 1 year ago

image getting this issue in my react native project. "i18next": "^22.0.6", "react-i18next": "^12.0.0", "react-native-translation": "^1.1.0",

Using the same versions in another react native project both has same react native version. But issue persist in one not another.

@Namangaraaz check your i18next initialization, make sure you pass the initReactI18Next via use function... This is the next-i18next repo, not the react-i18next repo... Please create a minimal reproducible example and open a new issue at https://github.com/i18next/react-i18next

DominicGBauer commented 1 year ago

For anyone that gets here and is using .page.{ts,tsx} to load pages, just double check you're running

export async function getStaticProps({ locale }) {
  return {
    props: {
      ...(await serverSideTranslations(locale, ['common'])),
    },
  }
}

in the appropriate file! I am using index.page.ts to import the page component and forgot to move getStaticProps to the index file -_- which resulted in me seeing the same issue as mentioned above.

guillaumeLamanda commented 1 year ago

I had the same issue not in layout, but in a page. I was following the installation instructions. It seems to be a version incompatibility.
I had to downgrade react-i18next from ^12 to ^11.18.0, and i18next from ^22 to ^21.

notpeelz commented 1 year ago

Explicitly passing the config is the only thing that worked for me: https://github.com/i18next/next-i18next/blob/master/TROUBLESHOOT.md#how-to-explicitly-pass-the-config

Versions:

dfeokti commented 1 year ago

I had the same error, and I realized that I had a bunch of

import { useTranslation } from 'react-i18next' mixed in my project. As soon as I changed them all to import { useTranslation } from 'next-i18next', everything worked just fine!

Hope this helps someone.

raflyfahrezi commented 1 year ago

I had the same error, and I realized that I had a bunch of

import { useTranslation } from 'react-i18next' mixed in my project. As soon as I changed them all to import { useTranslation } from 'next-i18next', everything worked just fine!

Hope this helps someone.

Thank you a lot. It works and is very helpful in my case which is NextJS told me that "Text content did not match. Server: "menu.dashboard" Client: "Dashboard" when I refresh the page.

AO19 commented 1 year ago

I had the same error, and I realized that I had a bunch of import { useTranslation } from 'react-i18next' mixed in my project. As soon as I changed them all to import { useTranslation } from 'next-i18next', everything worked just fine! Hope this helps someone.

Thank you a lot. It works and is very helpful in my case which is NextJS told me that "Text content did not match. Server: "menu.dashboard" Client: "Dashboard" when I refresh the page.

Thank you! Had the exact same problem :)

IvanKuzyshyn commented 1 year ago

I had the same error, and I realized that I had a bunch of

import { useTranslation } from 'react-i18next' mixed in my project. As soon as I changed them all to import { useTranslation } from 'next-i18next', everything worked just fine!

Hope this helps someone.

It works for me as well. Easy thing to miss!

Yhozen commented 1 year ago

I wish I read this comment before :sob:

mderrick commented 1 year ago

I had the same error, and I realized that I had a bunch of

import { useTranslation } from 'react-i18next' mixed in my project. As soon as I changed them all to import { useTranslation } from 'next-i18next', everything worked just fine!

Hope this helps someone.

I'm constantly auto importing the wrong thing, is there a way to nicely config react-i18next so it behaves the same way as next-i18next so we can use both interchangeably? Are there negative side effects in doing so?

adrai commented 1 year ago

You need to import from next-i18next only... If someone know how to tell the IDE which import to use let us know... maybe some special property in the package.json?

GabenGar commented 1 year ago

It is a feature in typescript, and therefore vscode: Exclude Specific Files from Auto-Imports

GabenGar commented 1 year ago

But it doesn't work in this case. Since the symbol from react-i18next is the same as next-i18next, thus making typescript optimize it straight to react-i18next instead. I don't even see the import for next-i18next in the tooltip, only react-i18next.

ArielBenichou commented 1 year ago

For anyone that gets here and is using .page.{ts,tsx} to load pages, just double check you're running

export async function getStaticProps({ locale }) {
  return {
    props: {
      ...(await serverSideTranslations(locale, ['common'])),
    },
  }
}

in the appropriate file! I am using index.page.ts to import the page component and forgot to move getStaticProps to the index file -_- which resulted in me seeing the same issue as mentioned above.

I've the pageExtensions: ["page.tsx", "api.ts"] config, and I didn't change my _app.tsx to _app.page.tsx doing that resolved the "pass in an i18next instance by using initReactI18next" issue

aaimio commented 1 year ago

Posted this is another closed issue (#2080):


While not super ideal, in our project, we've added an ESLint rule to disallow imports from react-i18next to ensure we don't import the wrong useTranslation:

"no-restricted-imports": [
  "error",
  {
    "paths": [
      {
        "name": "react-i18next",
        "importNames": ["useTranslation"],
        "message": "Import useTranslation from next-i18next instead."
      }
    ]
  }
]

Alternatively, you could look into autoImportFileExcludePatterns, although it'll be isolated to a single developer's machine.

MadaShindeInai commented 1 year ago

Importing type UseTranslationOptions from react-i18next also causes this warning

sibelius commented 1 year ago

is there a way to await i18next before rendering to ssg/static files?

stale[bot] commented 1 year ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

belgattitude commented 1 year ago

Just dropping a note for pnpm users.

In theory you might face You will need to pass in an i18next instance... if multiple versions of react-i18next are present in your install. (Ensure the context is initialized by the same lib)

From pnpm v7.29.0, pnpm allows deduping peer dependents via config (default in v8)

As a side note yarn 2+ does it already, see an example where the direct import of react-i18ext rather than next-i18next works https://github.com/belgattitude/nextjs-monorepo-example/pull/3558).

On pnpm 7.30.3 this config works pretty well.

# .npmrc / https://pnpm.io/next/npmrc 
strict-peer-dependencies=false
auto-install-peers=false

# Will be default in v8.0.0
use-lockfile-v6=true
dedupe-peer-dependents=true
resolve-peers-from-workspace-root=true

PS Most will be the default for the upcoming 8.0.0 (in rc.1 as of today).

That said a re-install if often needed (ie: nuke node modules + optionally remove pnpm-lock.yaml or run pnpm dedupe builtin from 7.23.0).

This should make the solution with imports optional (ie: https://github.com/i18next/next-i18next/issues/1917#issuecomment-1442740913). This matters for 2 reasons

I would appreciate if someone could confirm. Theory vs in practice :smile:

PS: added some obscure notes here https://github.com/i18next/next-i18next/blob/master/TROUBLESHOOT.md#how-to-debug-installation

stale[bot] commented 1 year ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

vitoropereira commented 1 year ago

react-i18next:: You will need to pass in an i18next instance by using initReactI18next

I got the same error and still can't fix it.

belgattitude commented 1 year ago

Package manager and version ? Your package.json can help also. Even just with i18next related deps. Thanks

vitoropereira commented 1 year ago

Package manager and version ? Your package.json can help also. Even just with i18next related deps. Thanks

image

If you want more details just let me know.

belgattitude commented 1 year ago

The package manager you use ? Pnpm, yarn, npm ? And version ?

ricoxor commented 1 year ago

Hello I have the same issue when I build.

I'm using next-i18next & next 13

Here is my dependencies :

"eslint": "8.40.0",
"eslint-config-next": "13.4.2",
"next": "13.4.3",
"next-i18next": "^13.2.2",
"postcss": "8.4.23",
"qs": "^6.11.2",
"react": "18.2.0",
"react-dom": "18.2.0",
"react-icons": "^4.8.0",
"react-player": "^2.12.0",
"react-slick": "^0.29.0",

The issue occur on my page /src/pages/game/[name].jsx On the top of the page I added this :

const path = useRouter().asPath;
const { t, ready } = useTranslation()
console.log(ready, t('play'), path)

Here is the console logs when I build :

[    ] - info Generating static pages (0/14)react-i18next:: You will need to pass in an i18next instance by using initReactI18next
false play /game/[name]
[ERROR MESSAGR]
true JOUER /game/game1
true JOUER /game/game2
true JOUER /game/game3 
...

Eveything is working in dev.

How can I fix this issue please? Thank you in advance

vitoropereira commented 1 year ago

The package manager you use ? Pnpm, yarn, npm ? And version ?

I'm using npm version 8.19.2. In production it is working ok. I went to update another area of ​​the system and I can no longer deploy because of this error. The website is https://www.smartmeet.digital