next-i18next: react-i18next:: i18n.languages were undefined or empty undefined

Describe the bug

I get the the following error:

[ wait ]  compiling ...
react-i18next:: i18n.languages were undefined or empty undefined

which appears only on the server (I mean in the output of the terminal, it doesn’t appear on the browser console).

Occurs in next-i18next version

“next”: “^8.1.0”, “i18next”: “^17.0.6”, “next-i18next”: “^0.44.0”,

Steps to reproduce

I followed every step described in the readme except keySeparator (because I have keys like Status.ONGOING)

Below is my configuration:

import NextI18Next from 'next-i18next'

const instance = new NextI18Next({
  defaultLanguage: 'en',
  otherLanguages: ['ru'],
  keySeparator: false
})

export default instance

Expected behaviour

This doesn’t look like a critical error, though I’m wondering the cause.

Screenshots

OS (please complete the following information)

  • Device: MacBook Pro (Retina, 13-inch, Late 2013)
  • Browser: Chrome Canary Version 77.0.3838.0 (Official Build) canary (64-bit)

Additional context

  • I’m working on a monorepo (yarn workspaces)
  • I use TypeScript

About this issue

  • Original URL
  • State: closed
  • Created 5 years ago
  • Reactions: 51
  • Comments: 74 (35 by maintainers)

Commits related to this issue

Most upvoted comments

Finally took some time to dig into this. The issue of awaiting the initialisation of the i18next instance is a very trivial one, and I can provide an easy, non-breaking way for users to do that if they want to. However, I think that that race condition is causing a very low percentage of the error reports we are seeing here.

The main problem is indeed with 404s, primarily in development. This is because a browser makes a request for a dev resource which used to exist, but now has been cleared by HMR. Eg:

http://localhost:3000/_next/static/webpack/f15dd305991bb90f87e1.hot-update.json

This request goes through the next-i18next middleware first, and as far as we are concerned, this is a request for a static resource and has a statusCode of 200 (has not been modified yet). The default behaviour here is to exclude static resources from i18next-express-middleware, thus req.i18n shouldn’t exist on this request.

The request then gets passed to NextJs:

const handle = app.getRequestHandler()
server.get('*', (req, res) => handle(req, res))

At this point the request is determined to be a 404, and the status code is changed. At that point in time, NextJs wants to render an error page, but does so without a redirect (naturally), so the next-i18next middleware never gets called again, and we do not have a chance to populate the i18n instance.

That NextJs logic can be found here.

(It’s noteworthy that this code path is different than “normal”, non-resource, 404s which next-i18next handles just fine.)

The curious part is how react-i18next ever gets to the point of calling hasLoadedNamespace, as i18n.isInitialized is a precondition of that call, and i18n shouldn’t exist on that req at all. Still not sure about this, but it’s relatively unimportant.

In general this is a bit of a chicken-and-egg problem to solve. The easy thing to do is to remove the passing of ignoreRoutes to i18next-express-middleware, seen here.

The actual redirect logic is protected by isI18nRoute which uses the exact same ignoreRoutes array, so we actually don’t have to worry about static resources being redirected when users have enabled localeSubpaths.

However, this solution would mean that we are processing all our static resource requests through the i18next middleware, just on the off chance that one of them results in a 404. Perhaps this is actually the right thing to do? No idea if this has perf implications, but it probably does.

On a side note, I have no idea why the NextJs team have decided to return an HTML doc for a 404 on a JSON resource - that doesn’t seem right to me. Not sure if that’s configurable.

Apologies for a long post, but that’s the entire story. We have all the information necessary to work on this, it’s just a matter of discussing amongst ourselves what makes the most sense.

Open for discussion.

I had the same issue on first page load efter every npm start. Added the following in i18n.ts:

NextI18NextInstance.i18n.languages = ['en', 'tr', 'fr'];

Seems like it suppressed the warning.

@isaachinman still the same after upgrading

Does anyone have a reproducible example?

I’m getting this warning when just running simple example (build & start)

“next”: “^8.1.0”, “i18next”: “^17.0.6”, “next-i18next”: “^0.45.0”

I get this problem when I use public/static path instead of static/locales. Removing public folder and setting up localePath to default value fixes the problem

My locales folder:

.
└── public
    └── static
        └── locales
            ├── ru
            |   └── common.json
            └── kk
                └── common.json

Instance:

const NextI18NextInstance = new NextI18Next({
  localePath: 'public/static/locales',
  preload: ['ru'],
  defaultLanguage: 'ru',
  otherLanguages: ['kk'],
  localeSubpaths: {
    ru: 'ru',
    kk: 'kk'
  }
});

Not sure if I’m helping but I caught this error from my side too and I temporary fix it by adding languages propriety to i18n object.

const languages = ['fr-FR', 'en-GB'];

const options = {
  defaultLanguage: 'fr-FR',
  otherLanguages: ['en-GB'],
  ...
};

const NextI18NextInstance = new NextI18Next(options);

NextI18NextInstance.i18n.languages = languages;

module.exports = NextI18NextInstance;

i think it can be fix by adding the preload key to the options object

module.exports = new NextI18Next({
  preload: ['fr'],
  otherLanguages: ['fr','en', 'es'],
  browserLanguageDetection: true,
  fallbackLng: 'fr',
  debug: true
})

options documentation

I had fix this issues, you can add lng: ‘en’ in file i18n.js.

import NextI18Next from ‘next-i18next’

const NextI18NextInstance = new NextI18Next({ defaultLanguage: ‘en’, lng: ‘en’, otherLanguages: [‘de’] });

/* Optionally, export class methods as named exports */ export const { appWithTranslation, withTranslation, i18n } = NextI18NextInstance

export default NextI18NextInstance

There is no “quick-fix” in user land, it needs to happen within the source code.

Correct me if I’m wrong but if the root issue is really the way how we bootstrap i18n then we should release a breaking change to fix that correctly.

Setting ignoreRoutes to an empty array is not a solution. That config option is there for a reason. For any users that use localeSubpaths, their static and _next traffic would be erroneously redirected, breaking the entire app.

For anyone wishing to help on this issue: please take a deep dive before bumping or offering suggestions!

@gtolarc The middleware is mandatory. Support for serverless is being tracked with #274. Let’s keep this on topic, please.

I also have this error in a ts project with a custom server, but only in this case:

  1. dev server started with a watch service to reload on code changes to .ts files, with hot reload for .tsx files
  2. a page is open in the browser
  3. save a change to a .tsx file which triggers a recompile
  4. during the recompile, a request for the hot reload module comes in (at least it looks like it does, not entirely sure how that works), results in a 404, which triggers the compilation of the _error page (makes no difference if it’s a custom or default.one)
  5. the missing lang message is shown, and common.missing.json gets generated with the error page translations in it (the custom error page is exported and used with the translation wrapper function, and works in 6 below)
  6. when producing a real 404 error by visiting a non-existing page in the browser (both with SSR, and client side navigation), everything works normally

Sometimes, the recompile finishes before the hot module request, and the error page doesn’t get generated, and everything is ok, but that might be a 1 out of 10 occurrence.

Using next 8.1.0 and ni18n 0.44.0

@deemaagog I cannot reproduce that either. Can you zip your directory, including node_modules, and send it to me?