Reputation: 1238
I am getting 'missingKey' error messages from i18next even though the translations appear to be loading (can see console logging). What am I doing wrong here?
Here is my i18n.js file:
import i18n from 'i18next'
import i18nhttp from 'i18next-http-backend'
import Backend from 'i18next-chained-backend'
import LanguageDetector from 'i18next-browser-languagedetector'
import { initReactI18next } from 'react-i18next'
const options = {
backends: [
i18nhttp
],
backendOptions: [
{ loadPath: '/api/constants/{{lng}}/{{ns}}.lang.json' }
]
}
i18n.use(Backend).use(LanguageDetector).use(initReactI18next).init({
backend: options,
ns: ['fin'],
defaultNS: 'fin',
fallbackNS: 'fin',
fallbackLng: 'en',
keySeparator: false,
debug: true,
detection: {
order: ['queryString', 'cookie'],
cache: ['cookie'],
lookupCookie:'website#lang',
},
interpolation: {
escapeValue: false
},
react: {
useSuspense: true
}
}, (err, t) => {
if (err) return console.log('something went wrong loading', err);
t('pinDescription')
})
export default i18n
And here is my React component file:
import React, { Suspense } from 'react'
import ReactDOM from 'react-dom'
import '../../../scripts/i18n'
import { useTranslation } from 'react-i18next'
const Translation = () => {
const { t, i18n } = useTranslation()
return (
<div className="translation-sample">
<h2>Translation Sample - from files</h2>
<p>{t('accountNumberDescription')}</p>
</div>
)
}
const domElement = document.getElementById('translation-sample')
if (domElement) {
ReactDOM.render(
<React.StrictMode>
<Suspense fallback={<div>Loading ... </div>}>
<Translation />
</Suspense>
</React.StrictMode>,
domElement
);
}
For the translation that I'm trying to render in the init callback (t('pinDescription')) I'm getting this error:
i18next::translator: key "pinDescription" for languages "en" won't get resolved as namespace "fin" was not yet loaded This means something IS WRONG in your setup. You access the t function before i18next.init / i18next.loadNamespace / i18next.changeLanguage was done. Wait for the callback or Promise to resolve before accessing it!!!
Which is strange since the react-i81n docs indicates that this callback runs after the translations have loaded.
For this and for the key I'm trying to render in the component I also get 'missing Key' error:
i18next::translator: missingKey en fin pinDescription pinDescription
i18next::translator: missingKey en fin accountDescription accountDescription
I have tried several things including:
Additionally, if I use a Suspense wrapper component I see that the translations have loaded in the console (however I still get missing key errors). When I remove 'Suspense' and opt out of it in the i81n.js config, then I never see any indication in the console that the translations have loaded.
I feel like I'm missing something fundamental here. What is the best way to await the init / translation loading process before using 't' in the component?
The main difference between what I am doing and what most of the examples in the documentation show is that they show i18n.js being loaded in the index.js file of a React application. I don't have any index.js file or React application - I am working with a single React component that will later be injected into an existing non-React application.
Additionally, there are no network errors, I can access the language json files directly in the browser without a problem and I can see the translations loading in the console.
Output from the browser console (I'm using a different namespace here, but the code is the same):
Thanks in advance for any tips or for pointing out where I am going wrong!
Upvotes: 1
Views: 2691
Reputation: 35563
You missed the i18next provider
import React, { Suspense } from 'react';
import ReactDOM from 'react-dom';
import i18n from '../../../scripts/i18n';
import { useTranslation, I18nextProvider } from 'react-i18next';
const Translation = () => {
const { t } = useTranslation();
return (
<div className="translation-sample">
<h2>Translation Sample - from files</h2>
<p>{t('accountNumberDescription')}</p>
</div>
);
};
const domElement = document.getElementById('translation-sample');
if (domElement) {
ReactDOM.render(
<React.StrictMode>
<I18nextProvider i18n={i18n}> // <----
<Suspense fallback={<div>Loading ... </div>}>
<Translation />
</Suspense>
</I18nextProvider>
</React.StrictMode>,
domElement
);
}
Upvotes: 0