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).
"next": "^8.1.0",
"i18next": "^17.0.6",
"next-i18next": "^0.44.0",
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
This doesn’t look like a critical error, though I’m wondering the cause.
Are you sure keySeparator: false is a valid config option? Regardless, if I add that single line to the simple example, I do not see this error.
Please provide reproducible repo.
I believe I'm getting the same error when using i18n.language for a select value. The value is undefined on the server and correct on the client, so it flickers on load.
Does anyone have a reproducible example?
I have the same problem,Have you solved it?
@isaachinman Here is the repo.
You’ll see a warning initially
You have not declared a namespacesRequired array on your page-level component: ErrorPage. This will cause all namespaces to be sent down to the client, possibly negatively impacting the performance of your app. For more info, see: https://github.com/isaachinman/next-i18next#4-declaring-namespace-dependencies
And then
react-i18next:: i18n.languages were undefined or empty undefined
I also added pages/—ERROR—, which when you rename to _error.tsx, will create a custom error page. ~When it exists, the error goes away.~
In my actually project, I have error page and namespacesRequired is set in getInitialProps in every pages, yet error is still there.
@mehmetnyarar I have cloned your repo and run it. I do see the namespacesRequired warning, but that is expected.
I do not see the i18n.languages were undefined warning.
Does anyone have a reproducible example?
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"
@deemaagog I cannot reproduce that either. Can you zip your directory, including node_modules, and send it to me?
I also have this error in a ts project with a custom server, but only in this case:
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
@mslepcevic Thanks for that information.
@mehmetnyarar Is this a dev-only error, or are you experiencing problems in production? Sounds like this could be a userland dev setup issue.
@isaachinman
Just to add that everything worked ok with my setup with next-i18next v0.41.0.
And the HMR request comes in because of the page that's opened in the browser and wants to reload upon saving a file.
I'm also experiencing the same issue, even in production.
It happens on server and browser.
I haven't had the time yet to create a reproducible repository tho.
I found this: https://github.com/i18next/i18next/issues/948
I can recall that i've only seen the warning when using the following setup to determine the language:
const currentLanguage = typeof req === "undefined" ? i18n.language : req.language; (in _app.js && _document.js).
Could it be that it's sometimes not waiting for the response and thus triggers the warning?
@deemaagog I cannot reproduce that either. Can you zip your directory, including
node_modules, and send it to me?
Here is a zip
Thanks @deemaagog I've finally seen this reproduced. It's coming from react-i18next's hasLoadedNamespace function.
I will dig into this now, but it looks like a harmless warning, unless I'm mistaken.
So although I saw the error one time, I cannot reproduce it reliably and have not seen it since then. If this is a race condition, I'm not sure where it is.
It seems like this would be caused by a call to useTranslation before the i18next express middleware has set up i18n.languages.
@isaachinman first of all, thanks for the plugin :)
I had the same problem described here, here is the repo
Hope it helps to debug
@urielscola Multiple problems with your repo which are unrelated:
next start instead of a custom server, which is a requirementsrc dirThat said, even if I run yarn dev, the server never comes online.
@isaachinman thanks, you were absolutely right. I fixed those problems and now it is working
I got the same issue because I just use footer:description only, but I called both common and footer,
<Typography variant="h5" align="center" color="textSecondary" paragraph>
{t('footer:description')}
</Typography>
export default withTranslation(['footer', 'common'])(Landing);
I tried to remove 'common. But the issue still happen. I'm not sure why the 'common' translation is a must.
So I added another text with translation:common in my page.
<Typography component="h1" variant="h2" align="center" color="textPrimary" gutterBottom>
{t('common:h1')}
</Typography>
Then the issue is resolved.
@ilhammeidi Can you please provide a reproducible repository?
@ilhammeidi Can you please provide a reproducible repository?
Here's my file and repo https://github.com/ilhammeidi/luxi-react-starter/blob/master/pages/index.js
I'm still testing about "react-i18next:: i18n.languages were undefined or empty undefined" message that sometime show in console. After ctrl+shit+r in chrome and restart server, it's gone already.
Okay, please let me know if you discover a reliable way to reproduce it.
Hi,
Same error for me. I don't understand why :/. Zip : http://s000.tinyupload.com/index.php?file_id=28449173765932552030
I see 2 possible issues
@ricardo-cantu Thanks for your input. Indeed it'd be good if we can await the promise returned by init, but that could end up being a bit tricky - I would appreciate any/all suggestions in regards to that.
Can you explain your second point in more detail? The mysterious i18n.languages were undefined error is coming specifically from react-i18next.
@isaachinman Thanks for the awesome work you've done with this library. I wrote my own implementation in typescript based on your work (I left out several things I didn't need)
nextApp.prepare().then(async () => {
const server = express()
...
await i18n.initServerInstance()
server.use(i18nextMiddleware(i18n.i18nextInstance))
...
nextApp.prepare()
I'm hesitant to go down this road, as we are really trying to get closer to serverless support.
As for the second point, req.i18n is actually a _clone_ of your main i18n instance. This is the expected pattern with the i18next express middleware.
You can simply show an example of wrapping the application with a top level function. There's already an example of index.ts -> server.ts somewhere in next.js examples.
import {application} from './app.ts'
application();
app.ts
async () => {
}
When you say serverless, do you mean no node server like express?
@isaachinman I have the same problem.
The current flow seems to have the problem that defaultLanguage is not assigned to initialLanguage in the first appWithTranslation-getInitialProps server rendering.
I have confirmed that warning is not generated in react-i18next when hard-coding the initialLanguage value.
@gtolarc That's very helpful, thank you! If I set initialLanguage to null manually, I see this error on the client side, however I do not see it in SSR. Do you have a way of reproducing on the server side?
Ah, if I comment out this line, I can reliably reproduce this server side.
So, that seems to point to an issue with the lng-from-req util.
@isaachinman It seems like there was a my misunderstanding. I thought this library was not designed with the nextI18NextMiddleware middleware as mandatory. So I used your library without a custom server, and the lack of an i18n instance in req occured.. It seems to be the main reason for all of those problems, at least in my case..
Whatever, I think you can change to support ssr without middleware. I think it is necessary since the latest version of nextjs has been able to do dynamic routing without a custom server and admitted that the design as a custom server is not good, many people will use nextjs in the future without a custom server.
@gtolarc The middleware is mandatory. Support for serverless is being tracked with #274. Let's keep this on topic, please.
@isaachinman I know that serverless support will need more ideas because there is a problem to service static resources. but it seems possible to remove middleware without serverless support.
If the above is implemented, there should be a logic change in the part that judges the initial setting, and the problem of the current thread will also be related.
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.
current thread will also be related
Current bugs are _not related_ to proposed features which haven't been implemented yet.
Perhaps @jamuhl might be able might be able to share some of his wisdom on why the i18n instance isn't initialising properly, and/or why there might be a race condition here?
@isaachinman from reading my guess is the warning comes from the .init call of the "main" i18next instance --> language is detected per request, therefore the detector fails on the main instance as it can't pass req to the detection function resulting in an undefined lookup (but should set it to fallbackLng normally...not sure why this does not happen here).
Or any direct call to i18n.t before init was done...eg. by not using the t function passed from I18nextProvider (in case of serverside)
I had this problem and was caused on a bump from 0.37.0 to 0.51.1.
The issue was that on the options when isntantiating the NextI18Next object, I had a backend node that did not explicitly differentiated the server (static path) from the client (request).
Maybe this is useful?
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
@truongtx9 That will most likely break language detection.
@isaachinman Here is the repo with reproducable state: see branch bug/i18n-languages-empty in https://github.com/keethu24/next-getting-started/tree/bug/i18n-languages-empty
Install deps and then run npm run dev.
This server-side error is due to next-i18next that does not pass a callback to i18next.init.
https://github.com/isaachinman/next-i18next/blob/680a55be85ff757610ea28b144f103578f432b23/src/create-i18next-client.ts#L28
So it don't wait for a complete i18next initializtion and i18next may not be fully initialized when first used.
A temporary fix is to set initImmediate to false which cause a sync loading of i18next (see https://github.com/i18next/i18next/blob/527003960b5f3b83162df2f9492353be7cae5fd6/index.d.ts#L384):
const i18nInstance = new NextI18Next({
defaultLanguage: 'en',
[...]
initImmediate: false,
});
@nathan818fr Thanks, that sounds right. We've talked about this before in other issues. It's a race condition, but should only affect people running ASGs where traffic hits a service immediately after coming online.
I don't think we should expect users to await the class constructor or have to pass a callback. It seems like shifting this initImmediate approach into the next-i18next would be an appropriate fix.
Fix released with v1.1.0. Please upgrade and let me know if you still experience the bug. Thanks everyone for your patience!
@isaachinman still the same after upgrading
@shakesBeardZ What version are you on, and do you have steps to reproduce?
It happens to me less often than before, but yes sometimes it happens again :/
In i18next, even when initImmediate is set to false, I18n.changeLanguage is called... and it seem async...
https://github.com/i18next/i18next/blob/df4d486dec997fb785e71e2b3965c128f75834f0/src/i18next.js#L125
@isaachinman Even with the latest version, problems always occur during development mode HMR.
This may not be a real problem in production, but if you get error messages frequently during development, it's likely that developers may misunderstand this library is not stable. I hope you solve this problem :)
For me I have fix this error with this :
/* eslint-disable object-curly-newline */
import NextI18Next from 'next-i18next';
const nextI18nOptions = {
defaultLanguage: 'en',
otherLanguages: ['fr'],
};
const languages = nextI18nOptions.otherLanguages;
languages.push(nextI18nOptions.defaultLanguage);
const NextI18NextInstance = new NextI18Next({ ...nextI18nOptions });
if (NextI18NextInstance && NextI18NextInstance.i18n && !NextI18NextInstance.i18n.languages) {
NextI18NextInstance.i18n.languages = languages;
}
export default NextI18NextInstance;
const actualLanguage = NextI18NextInstance.i18n.language || nextI18nOptions.defaultLanguage;
/* Optionally, export class methods as named exports */
export const { appWithTranslation, withTranslation, i18n, Link, Router } = NextI18NextInstance;
export { languages, actualLanguage };
I also faced with the issue regularly but I can't reproduce it. I would reopen the issue.
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
})
@oteka21 Please see the source.
Same issue here with latest versions. Site seems to render with:
lng: 'en',
as @truongtx9 proposed above. What's this ? Is this a bug or a non documented feature ?
@rdewolff As stated previously, that will break language detection.
Facing the same issue, there is a way to solve this without breaking the language detection?
+1
there is a way to solve this without breaking the language detection?
Yes, either await the promise returned by the i18next init call, or use the callback.
@isaachinman
Yes, either await the promise returned by the i18next init call, or use the callback.
so do you know a solution or what is the state here? How can I help?
@StarpTech The working assumption is that it's a race condition on startup. The only way we can arrive at a non-breaking-change solution is if we can find a way to initialise an i18next instance synchronously.
If that helps, let me describe my solution to the problem.
In my case I've seen such errors when there were requests to non existing URLS(404) on /static/.
And here's the logic:
next-i18next/middlewarenext-i18next/middleware adds another middleware i18next-express-middlewarei18next-express-middleware checks ignoreRoutes option/static/ is ignored, so i18next-express-middleware is not running at all - it just calls next() function argument, so express.js server continuesi18next-express-middleware didn't provide anything because /static/ is ignored route.So here is solution in my case - change ignoreRoutes to empty array:
const NextI18Next = require('next-i18next').default;
const { localeSubpaths } = require('next/config').default().publicRuntimeConfig;
const localeSubpathVariations = {
none: {},
foreign: {
fr: 'fr',
en: 'en',
},
all: {
en: 'en',
fr: 'fr',
},
};
module.exports = new NextI18Next({
defaultLanguage: 'ru',
otherLanguages: ['fr', 'en'],
localeSubpaths: localeSubpathVariations[localeSubpaths],
debug: true,
// initImmediate: true,
// load: 'all',
ignoreRoutes: [],
});
@isaachinman not sure if there's any race condition in i18next-express-middleware(cuz there's no async and loadLanguages calls next() only on callback), but please check my solution if it closes this issue
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!
@isaachinman Not sure if it is of any help, but for me the problem seems to occur when I'm having a custom route, e.g.:
custom route:
router.get('/password-renew/:passwordResetSlug', helmet.noCache(), (req, res) => {
const actualPage = '/password-renew';
const queryParams = { ...req.query, passwordResetSlug: req.params.passwordResetSlug }
return app.render(req, res, actualPage, queryParams);
})
page:
class RenewPasswordPage extends Component {
static async getInitialProps(ctx) {
const namespacesRequired = ['public']
const passwordResetSlug = ctx.query.passwordResetSlug
return { namespacesRequired, passwordResetSlug }
}
render() {
// ...
}
}
export default withTranslation('public')(RenewPasswordPage)
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;
Using @jonathangiamp worked after adding the fallbackLng config property.
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.
@StarpTech If and when it is determined that we cannot initialise an i18next instance synchronously, then yes, we'd need to release a breaking change.
This is a very good example of a use case where we definitely want to init an instance synchronously, as our application cannot serve any requests until it's ready.
@jamuhl Any ideas about what we might be doing wrong here? Any opinion about construction/initialisation? Funny that this issue has become so popular.
@isaachinman please add "bug" label
@isaachinman would be happy to help with this...but I do not get the issue
but why is that a problem in production...a server starts up and things will be ready on first request...or even delay start of server and start it inside the init callback...
for serverless add a middleware that asserts init is done before calling next should do the trick (just use the initialized event and flag on i18next.)
Looks like this might happen more often when you have a custom _error that uses t() or the hoc. Next will compile a _error page with no req, thus no i18n object that has the correct lang detected. I removed the custom _error in another project I’m working on and I have not seen the warning again.
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.
Thanks to OP and @isaachinman for taking time to check this issue.
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.
What would be the quick-fix?
Thanks
There is no "quick-fix" in user land, it needs to happen within the source code.
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'
}
});
@GraxMonzo
localePath: typeof window === 'undefined' ? 'public/static/locales' : 'static/locales'
Most helpful comment
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:
This request goes through the
next-i18nextmiddleware first, and as far as we are concerned, this is a request for a static resource and has astatusCodeof 200 (has not been modified yet). The default behaviour here is to exclude static resources fromi18next-express-middleware, thusreq.i18nshouldn't exist on this request.The request then gets passed to NextJs:
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-i18nextmiddleware 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-i18nexthandles just fine.)The curious part is how
react-i18nextever gets to the point of callinghasLoadedNamespace, asi18n.isInitializedis a precondition of that call, andi18nshouldn't exist on thatreqat 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
ignoreRoutestoi18next-express-middleware, seen here.The actual redirect logic is protected by
isI18nRoutewhich uses the exact sameignoreRoutesarray, so we actually don't have to worry about static resources being redirected when users have enabledlocaleSubpaths.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.