Closed wijdench closed 6 years ago
looks like render gets called before i18n.init
i18next is initialized in the parent page and this is my i18next.js file import i18next from 'i18next'; import LanguageDetector from 'i18next-browser-languagedetector'; import XHR from 'i18next-xhr-backend';
i18next .use(XHR) .use(LanguageDetector) .init({ debug: true, backend: { loadPath: '/locales/resources.json?lng={{lng}}&ns={{ns}}', allowMultiLoading: true, }, fallbackLng: { 'en-US': ['en'], 'fr-FR': ['fr'], default: ['en'], }, ns: ['common', 'search'], interpolation: { escapeValue: false, // not needed for react!! },
react: { wait: true, },
});
export default i18next;
nothing to do with i18next config...do you "require/import" i18n file before calling ReactDOM.render
Best might be providing a webpackbin like https://www.webpackbin.com/bins/-KvzvUPFsBVI_74Jll99 so i could have a look.
@wijdench I had the same problem once and my app translate before backend connector loads the resource bundle. I could see the output in console. The best solution would be to wrap it with an I18nextProvider
and that takes care of it.
I'm using I18nextProvider but this does not solve my problem
not wrapped your component with the translate hoc? not seeing from your config alone why it should not work...?!?
https://www.webpackbin.com/bins/-KvzvUPFsBVI_74Jll99 works in the bin...so must be something in your app
could you please do a bin to reproduce?
any update on this?
Hi @jamuhl , I got similar issue when trying using i18n.t('key')
My config:
import i18n from 'i18next'
import Backend from 'i18next-xhr-backend'
import LanguageDetector from 'i18next-browser-languagedetector'
import { reactI18nextModule } from 'react-i18next'
i18n
.use(Backend)
.use(LanguageDetector)
.use(reactI18nextModule)
.init({
preload: ['vi-VN', 'en-US'],
load: 'currentOnly',
fallbackLng: 'en-US',
ns: ['translations'],
defaultNS: 'translations',
debug: true,
interpolation: {
escapeValue: false, // not needed for react!!
},
react: {
wait: true,
bindI18n: 'languageChanged loaded',
}
}, (err, t) => {
console.log(t("header.signup"))
})
export default i18n
console.log(i18n.t("header.signup"))
And the log is
It works well with react stuff but when I trying to use function i18n.t('key')
in some cases, the missing error is i18next::translator: missingKey undefined translations
How do I fix ?
Thanks for help.
you get missing key header.signup
because you call t before i18next has loaded the translations ---- loading is an xhr request, which per definition is asynchronous.
i18next.init(options);
i18next.t('key'); // not loaded -> error
i18next.init(options, () => { i18next.t('key'); // loaded -> no error});
that's why you have the translate hoc or the i18n render prop - those assert everything is loaded (if wait is set to true) before rendering
clear, @jamuhl , it should be async, I have a bit struggling to add translate function into my constraints validation messages object (https://validatejs.org), any hint?
delay building the constraints -> use https://www.i18next.com/api.html#oninitialized or onLoaded
Thanks @jamuhl so much, I'll try this, have a nice day!
I solved by a simple function like const callLang = () => i18n.on("load")
, then call it in validator function. Awesome.
Same issue. I was following the tutorial and everything was working but once I replaced the jsons with the backend I get Missing Key. *i18n is loaded first in my App,js I have to use the src folder due to react-app constraint. So I changed the default below
import i18n from "i18next";
import detector from "i18next-browser-languagedetector";
import backend from "i18next-xhr-backend";
import { reactI18nextModule } from "react-i18next";
// translations are already at
// '../public/locales/en/translation.json'
// which is the default for the xhr backend to load from
i18n
.use(detector)
.use(backend)
.use(reactI18nextModule) // passes i18n down to react-i18next
.init({
backend: {
loadPath: "./locales/{{lng}}/translation.json"
},
lng: "en",
fallbackLng: "en", // use en if detected lng is not available
keySeparator: false, // we do not use keys in form messages.welcome
interpolation: {
escapeValue: false // react already safes from xss
},
react: {
wait: true
}
});
export default i18n;
@developdeez is your application based on create-react-app? if so the public folder should be accessible during development (and added into the production build). https://github.com/i18next/react-i18next/tree/master/example/react/public
@jamuhl I am using create react app. I get this error when doing it that way: ./src/i18n.js Module not found: You attempted to import ../public/locales/de/translation.json which falls outside of the project src/ directory. Relative imports outside of src/ are not supported.
Is there a way for it to use the src folder? Seems the backend may be checking the wrong place or something.
Module not found: You attempted to import ../public/locales/de/translation.json which falls outside of the project src/ directory. Relative imports outside of src/ are not supported.
This states you try to import those files - you not have to import them using the xhr backend.
I see that error lead me to move the files causing more errors. Thanks Unrealted: but does detector work automatically. I changed my browser to German and it still says its English. Also is add missing automatic? I removed a definition from the json in German and refreshed. It showed in english but no add folder was created showing it missing.
detector per default once detected sets your lng in localstorage -> means if you programmatically use changelanguage that would be stored too -> next visit is always based on the previous set or last detection. Deleting that localstorage entry or incognito should show the expected result.
Missing depends on your backend able to handle this...and on how it is configured (https://www.i18next.com/overview/configuration-options#missing-keys) but anyway will only trigger if it does not find that new key (not in fallback - so you got that key to your source language -> from there a translation management like eg. our https://locize.com should take care of having all keys in all target langauges)
Hey, @jamuhl, first of all thanks for great work. I have this issue when I need two namespaces in a component the t function is searching in the first ns only. How to make it look for all namespaces I provided inside withNamespaces(['ns1', 'ns2'])? My init is:
i18n
.use(XHR)
.init({
debug: process.env.NODE_ENV === 'development',
ns: ['common'],
defaultNS: 'common',
nonExplicitWhitelist: true,
lng: 'ru', // 'kz' | 'en' | 'ru'
fallbackLng: 'ru',
backend: {
loadPath: process.env.NODE_ENV === 'development'
? '/locales/{{lng}}/{{ns}}.json'
: `/${process.env.REACT_APP_APP_NAME}/client/locales/{{lng}}/{{ns}}.json`
},
react: {
wait: true
}
});
withNamespaces(['ns1', 'ns2'])
only tells the code to load this two namespaces (or assert that they got loaded). ns1
will be used as primary namespace, so:
t('key')
will return translations from ns1
t('ns2:key)
will return translation from ns2
https://www.i18next.com/translation-function/essentials#accessing-keys-in-different-namespaces
Alternative you can set: nsMode: 'fallback' -> https://react.i18next.com/components/namespacesconsumer#namespacesconsumer-props
@jamuhl This is now very clear. Thanks!
If you like this module don’t forget to star this repo. Make a tweet, share the word or have a look at our https://locize.com to support the devs of this project -> there are many ways to help this project :pray:
i18next::translator: missingKey undefined translation nav.help nav.help
undefined is the language
looks like a component renders and access that key before i18next did init -> Guess that component does not use the HOC or hook
Hi! React React i18next. In the console appears the error: i18next::translator: missingKey undefined translation settings.title settings.title. My config:
import i18n from 'i18next'; import XHR from 'i18next-xhr-backend'; import { initReactI18next } from 'react-i18next'; i18n .use(XHR) .use(initReactI18next) // bind react-i18next to the instance .init({ fallbackLng: false, debug: true, interpolation: { escapeValue: false, // not needed for react!! }, lng: 'ru', // 'en' | 'es'
backend: { loadPath: './locales/{{lng}}/translation.json', }, react: { wait: true, }, }); export default i18n; index.js: import as React from 'react'; import as ReactDOM from 'react-dom'; import { I18nextProvider } from 'react-i18next'; import i18n from '@app/core/i18n'; import { App } from './App'; ReactDOM.render(
same like above
Facing the same issue. Some keys sometimes dont load. The keys are specific but whether they load or no is random. The error is something like: 'i18next::translator: missingKey', 'pt-BR', 'app', 'theMissingKey'.
Using react-native with react-i18next:10.6.2 and i18next: 15.0.10.
` import i18next from "i18next"; import { initReactI18next } from "react-i18next"; import DeviceInfo from "react-native-device-info"; import Locize from "./locize"; export const DEFAULT_LANGUAGE = "pt-BR"; import { version } from "../../package.json";
i18next .use(Locize) .use(initReactI18next) .use({ type: 'languageDetector', detect: () => DeviceInfo.getDeviceLocale(), init: () => {}, cacheUserLanguage: () => {}, }) .init({ debug: true, initImmediate: false, saveMissing: true, fallbackLng: DEFAULT_LANGUAGE, ns: ['app'], interpolation: { escapeValue: false, },
react: {
useSuspense: false,
},
backend: {
private: __DEV__,
version: __DEV__ ? 'develop' : version,
projectId: '695e6211-ac07-4d1f-aa21-754bc8d86693',
apiKey: 'b9ab9f51-c271-4eec-84c0-4ce31cd4ecc2',
referenceLng: DEFAULT_LANGUAGE,
setContentTypeJSON: true,
},
});
export default i18next;
`
@jramalho you're loading the translations asynchronously from our locize service and set useSuspense: false,
so as long you do not handle ready
https://react.i18next.com/latest/usetranslation-hook#not-using-suspense
const { t, i18n, ready } = useTranslation('ns1', { useSuspense: false });
--> if ready false you will get missing...timings are random - but if you do not get that ready: false and missings that's more or less luck...
So either useSuspense or do not render your content before that value is ready: true
@jamuhl Thanks for the response, we are using the withTranslation HOC. It gives me a tReady prop, we put that on the shouldComponentUpdate and now it works fine. By the way, the prop tReady is not on the documentation. We discovered it opening the lib. But thanks again. That solved our problem.
@jramalho yes it's only in the code commented here: https://react.i18next.com/latest/withtranslation-hoc#not-using-suspense --> will update the documentation for the "not suspense" case making it more clear - absolutely agree with you this is too important when disabling suspense.
I am using the Translation
component only and I am getting the same error. In my App:
<Translation>
{t => (
<Home
routeName="home"
aria-label={t('home.title')}
>
<StyledIconVC />
</Home>
)}
</Translation>
Then on my server I set it up like so:
i18next
.use(initReactI18next)
.use(nodeFsBackend)
.init({
ns: ['common'],
fallbackLng: lang,
debug: true,
lng: lang,
keySeparator: '__KEY__',
defaultNS: 'common',
interpolation: {
escapeValue: false,
},
react: {
useSuspense: false,
wait: true,
},
})
Then when I render:
try {
await i18next.loadLanguages(lang)
} catch (e) {
// eslint-disable-next-line no-console
console.error('[renderApp:loadLanguages]', e)
}
const withI18n = React.createElement(
I18nextProvider,
{ i18n },
App,
)
I get the same error as reported here:
i18next::backendConnector: loaded namespace common for language nl { 'home.title': 'Home', 'my_profile.title': 'My Profile', 'recipes.title': 'Recepten', 'menuplanner.title': 'Planner', 'shopping.title': 'Boodschappen' } i18next: languageChanged nl i18next: initialized { debug: true, initImmediate: true, ns: [ 'common' ], defaultNS: 'common', fallbackLng: [ 'nl' ], fallbackNS: false, whitelist: false, nonExplicitWhitelist: false, load: 'all', preload: false, simplifyPluralSuffix: true, keySeparator: 'KEY', nsSeparator: ':', pluralSeparator: '', contextSeparator: '_', partialBundledLanguages: false, saveMissing: false, updateMissing: false, saveMissingTo: 'fallback', saveMissingPlurals: true, missingKeyHandler: false, missingInterpolationHandler: false, postProcess: false, returnNull: true, returnEmptyString: true, returnObjects: false, joinArrays: false, returnedObjectHandler: false, parseMissingKeyHandler: false, appendNamespaceToMissingKey: false, appendNamespaceToCIMode: false, overloadTranslationOptionHandler: [Function: handle], interpolation: { escapeValue: false }, lng: 'nl', react: { useSuspense: false, wait: true } } ---- render happens ---- i18next::translator: missingKey undefined common my_profile.title my_profile.title i18next::translator: missingKey undefined common home.title home.title i18next::translator: missingKey undefined common home.title home.title i18next: languageChanged nl i18next: initialized { debug: true / .. / }
Yet I only get the keys rendered from the server. It seems like I am missing something really obvious..
@bitttttten yes...you miss something very obvious...there is no wait option -> https://react.i18next.com/latest/withtranslation-hoc#not-using-suspense
I appreciate the link but it doesn't mention in there anything about the wait
option. Do you mean the one that I have set in the react-i18next options?
Also I am using Suspense in my app, but this is just for SSR. So it should not be triggering the Suspense loader.
@bitttttten no mention of wait
might say it does not exist...and for SSR (adding all namespaces to the ns array and setting preload option to all languages might be a good idea...so you neither run into a not ready nor trigger a suspense)
I saw it in one of your github comments and I assumed it's still there because it's still in the typings (ReactOptions.wait?: boolean
). But, no problem! I can remove it.
Thanks for sticking it out with me thus far... currently, I only have one namespace and it's being loaded into i18n successfully, it's also the default namespace. I called it 'common'. So now on the server, I am doing:
await i18next.loadLanguages(lang)
await i18next.loadNamespaces('common')
(side note: although if I do omit fallbackLng
from the init options then it attempts to load the 'dev' langauge, even though I am setting lng: 'nl'
to load the language... I am not sure if this is an issue or not :))
I feel totally at a loss right now! I even copy and pasted the setup from a working example 🤔
Here is my current config at the moment...
i18next
// pass the i18n instance to react-i18next
.use(initReactI18next)
// use node-fs instead of xhr backend
.use(webpackContextBackend)
.init({
ns: ['common'],
debug: true,
lng: 'nl',
load: 'all',
fallbackLng: 'nl',
keySeparator: '__KEY__',
defaultNS: 'common',
interpolation: {
escapeValue: false,
},
react: {
useSuspense: false,
},
})
that comment was november 18 and for the old v9!!! regarding the typings...in that case those are wrong...as I do not maintain them myself you might provide a PR and ping @rosskevin for a review.
Really the only option on client is using either Suspense or render an alternative UI if not ready as loading translations from the server is done async.
If you need to do SSR have a look at https://github.com/isaachinman/next-i18next how they solved it (passing translations from server to client and pass them to i18next before rendering by using https://react.i18next.com/latest/ssr)
Okay, thanks. I will open a PR to fix the typings.
I think I have the passing down translations correctly. It is that on the server, it does not pick up any translations. When the client renders, it then fetches the translations and renders correctly. Although you see a flash of i18n keys, and then the text appearing. So my issue is actually on the server 🤔
For example, on the server render:
<p>shopping.title</p>
When client renders:
<p>Boodschappen</p>
But thanks, I will check out the nextjs example!
did you use the i18next-node-fs-backend
?!? might be just the path to your translations is wrong?
On the server I am actually using a custom backend, which does work in another project. I added logging in there and it does send back data correctly.
It's a very simple custom backend, just reads from a big object of this.storage[language][namespace]
. I can share it later once I am at a desktop and not on my phone :)
interface ILocales {
[key: string]: {
[key: string]: object
}
}
const context = require.context('../../src/i18n/locales/', true, /\.json$/)
const locales: ILocales = {}
context.keys().forEach(key => {
const [, lang, file] = key.split('/')
locales[lang] = locales[lang] || {}
const [namespace] = file.split('.')
locales[lang][namespace] = context(key)
})
class WebpackContextBackend {
public static type: string
public services: any
public storage: ILocales
public constructor(services: any) {
this.services = services
this.storage = locales
this.type = 'backend'
}
public read(
language: string,
namespace: string,
callback: (error: string | null, response: any) => any,
) {
try {
const resource = this.storage[language][namespace]
callback(null, resource)
} catch (e) {
console.log('[i18next-webpack-context:read]', e)
return callback(e, false)
}
}
public save(language: string, namespace: string, data: object) {
/* .. */
}
}
WebpackContextBackend.type = 'backend'
export default WebpackContextBackend
Hm....are you using i18next-express-middleware on serverside? Or how do you pass the i18next instance (per request - asserting the language is bound to the request - requests user language)...
No, I am just wrapping the app with the provider. It worked very well like this in another project.
Currently I am just using 'nl' for the language, just to get it working. I will then work on languages after that :p
const chunkCapture = React.createElement(
Loadable.Capture,
{ report: moduleName => modules.push(moduleName) },
React.createElement(App, { rootStore }),
)
const withI18n = React.createElement(
I18nextProvider,
{ i18n },
chunkCapture,
)
const html = ReactDOMServer.renderToString(withI18n)
Hm...i hope you thought about how this works...but if you got any async operation inside this - it will work - is just a - it will work on my machine. Can't work in production (or only work as long you only got one language) - requests are async - any operation async can end in the event loop giving another request the opportunity to change the language on i18next and you end up with mixed languages...=> so you end in concurrency issues
That's the reason why i18next-express-middleware creates a i18next instance per user to be save on parallel requests from multiple users with different languages (using a singleton will bring funny results).
Further eg. next-i18next inject that req.i18n into the provider for SSR...
Right, so I should clone the instance on each request? Something like:
const i18n = i18next.cloneInstance()
i18n.changeLanguage(lang)
await i18n.loadLanguages(i18n.language)
yes -> but yet that won't solve your issue -> as you some where still do render before loading is done...at least looking at:
--- render happens ----
i18next::translator: missingKey undefined common my_profile.title my_profile.title
i18next::translator: missingKey undefined common home.title home.title
i18next::translator: missingKey undefined common home.title home.title
i18next: languageChanged nl
i18next: initialized { debug: true /* .. */ }
Not having a reproducible stripped-down example it's hard to help...my guess await i18n.loadLanguages(i18n.language)
is called somewhere but not inside the request or not inside an async function - but I'm not to deep into serverside usage of async await
Hey error is next-i18next::translator: missingKey undefined translations How do I fix ?
@ebs12345 by making sure you do not call any t
before i18next.init is done. Make sure you use either withTranslation or useTranslation and have the language detector or set lng on init
I check tReady before rendering the component.
From: Priyanka notifications@github.com Sent: Thursday, November 14, 2019 11:48 PM To: i18next/react-i18next react-i18next@noreply.github.com Cc: developdeez cecilcjcarter@gmail.com; Mention mention@noreply.github.com Subject: Re: [i18next/react-i18next] missingKey issue (#322)
Hey error is next-i18next::translator: missingKey undefined translations How do I fix ?
— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/i18next/react-i18next/issues/322?email_source=notifications&email_token=ADDULRJ72WWIDVZ66TYBTW3QTZH2PA5CNFSM4D6W2322YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEEETK4Q#issuecomment-554251634 , or unsubscribe https://github.com/notifications/unsubscribe-auth/ADDULRM3S6IWXZXLWW6A7FLQTZH2PANCNFSM4D6W232Q . https://github.com/notifications/beacon/ADDULRNJ2WOGKBCDQRF6MF3QTZH2PA5CNFSM4D6W2322YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEEETK4Q.gif
still: the info says there is a missing key (not loaded, not initialized)
missingKey undefined translations ---> missingKey currentLng currentNamespace
so there is somewhere something wrong in your code - I can't find magically issues in your code...
Hey @jamuhl i have implemented next-i18next package for multi-language. But I have the issue that when the default value is selected the language key is not loaded or key value are printed .I have used s3 amazone server for the uploaded json file. So can you help me please.
Hi, i get this console error in any interaction with my view 'i18next::translator: missingKey fr backoffice'
even i tried ti put react: { wait: true, }
but this did not work
Help!