react-i18next giving a missingKey error in build only - reactjs

Below are my index.js and i18next.js(the config for i18n)
index.js
import React, { Suspense } from 'react'
import i18n from './i18next'
import './i18next'
import ReactDOM from 'react-dom'
import App from './App'
import * as serviceWorker from './serviceWorker'
import Loading from './components/Styled/Loading/Loading'
i18n.init().then(() =>
ReactDOM.render(
<React.StrictMode>
<Suspense fallback={<Loading />}>
<App />
</Suspense>
</React.StrictMode>,
document.getElementById('root')
)
)
i18next.js
import i18n from 'i18next'
import { initReactI18next } from 'react-i18next'
import Backend from 'i18next-http-backend'
import LanguageDetector from 'i18next-browser-languagedetector'
// not like to use this?
// have a look at the Quick start guide
// for passing in lng and translations on init
const Languages = ['en', 'fr']
i18n
.use(Backend)
.use(LanguageDetector)
.use(initReactI18next)
.init({
fallbackLng: 'en',
debug: true,
whitelist: Languages,
keySeparator: false,
defaultNS: 'translation',
ns: ['translation'],
backend: {
loadPath: `/locales/{{lng}}/{{ns}}.json`,
},
load: 'unspecific',
react: {
wait: true,
},
interpolation: {
escapeValue: false,
},
})
export default i18n
console
So, here's the gist. I use the useTranslation hook in my components and it works perfectly fine in localhost. However, I constantly keep getting the missingKey error on production where the build is deployed. Have tried all the feasible settings from other answers, without success. Apologies for the huge content, I just wanted to be thorough.

Figured out the solution. Because I'm serving the build in a sub-directory, I had to append it to loadPath.
.env
REACT_APP_VERSION=$npm_package_version
REACT_APP_PUBLIC_URL='/dy/'
i18next.js
backend: {
loadPath: `${process.env.PUBLIC_URL}/locales/{{lng}}/{{ns}}.json`,
}

Related

react-i18next the key name is displayed instead of it's value

I'm trying to use different languages for my react-creat-app project and I'm facing this problem where the key name is shown in DOM instead of its value.
index.js looks like this :
import React from "react";
import ReactDOM from "react-dom";
import "./index.scss";
import App from "./components/App/App";
import i18n from "i18next";
import { initReactI18next } from "react-i18next";
import LanguageDetector from "i18next-browser-languagedetector";
import HttpApi from "i18next-http-backend";
i18n
.use(initReactI18next)
.use(LanguageDetector)
.use(HttpApi)
.init({
debug: true,
fallbackLng: "ar",
detection: {
order: ["htmlTag", "cookie"],
caches: ["cookie"],
},
backend: {
loadPath: "../public/locales/{{lng}}/translation.json",
},
react: { useSuspense: false },
});
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById("root")
);
locales/ar/translation.json looks like this :
{
"meet_team": "تعرفوا على فريقنا"
}
locales/tr/translation.json looks like this :
{
"meet_team": "ekipimizle tanışın"
}
The component I want to translate looks like this :
import { useTranslation } from 'react-i18next';
const OurTeam = () => {
const { t } = useTranslation();
return <h1 className="foo">{t("meet_team")}</h1>;
};
what is displayed on the page is this :
meet_team
How can I resolve this issue?
The problem was at index.js :
loadPath: "../public/locales/{{lng}}/translation.json",
changing it to :
loadPath: "/locales/{{lng}}/translation.json",
has fixed the problem

Loading in i18n translations without showing translation ids

I've implemented i18next in my nextjs project, and I'm having the issue, that I can briefly see all the text-id's before the translations get fully loaded. Is there any way to avoid showing these text ID's as it causing a bit of flickering on load? It's especially obvious when refreshing the page quickly.
I have tried different ways with both useSuspense and wait in the config and App file. Currently this is what I have (translation files are located in public/locales/xx/translation.json):
i18n.jsx
import i18n from 'i18next';
import { initReactI18next } from 'react-i18next';
import Backend from 'i18next-http-backend';
i18n
.use(Backend)
.use(initReactI18next)
.init({
debug: true,
fallbackLng: 'en',
interpolation: {
escapeValue: false, // not needed for react as it escapes by default
},
react: {
useSuspense: true
}
});
export default i18n;
Usage:
import { useTranslation } from 'react-i18next';
export default function Text () {
const { t } = useTranslation();
return (<Text>{t('text.string.here')}</Text>)
App
import { Suspense } from 'react'
import i18n from 'components/i18n'
function MyApp({ Component, pageProps }) {
<Suspense fallback="loading">
<Component {...pageProps}/>
</Suspense>
}

What am I doing wrong with setting up i18next in React? Getting a "i18next::translator: missingKey" error

In my src folder, I made a folder called i18n, and it contains these three files
en.json
es.json
pl.json
This is what they look like:
{
"selectAction": "Select Action",
"workflow": "Workflow",
"details": "Details"
}
In src folder, I also added this file called i18n.js
import i18n from 'i18next'
import LanguageDetector from "i18next-browser-languagedetector"
import { initReactI18next } from 'react-i18next'
// import Backend from "i18next-xhr-backend";
// import XHR from 'i18next-xhr-backend'
import languageEn from './i18n/en.json'
import languageEs from './i18n/es.json'
import languagePl from './i18n/pl.json'
i18n
// .use(Backend)
// .use(XHR)
.use(LanguageDetector)
.use(initReactI18next)
.init({
resources: {
en: languageEn,
es: languageEs,
pl: languagePl
},
lng: "es",
fallbackLng: "en",
debug: true,
keySeparator: ".",
interpolation: {
escapeValue: false,
}
});
console.log(i18n.languages)
export default i18n;
My index.js file in the src root looks like this:
// import statements are omitted, but I am importing I18NextProvider and i18n
ReactDOM.render(
<I18nextProvider i18n={i18n}>
<App />
</I18nextProvider>
document.getElementById('root')
);
Lastly, somewhere in my App I have this:
// Other imports omitted
import { useTranslation } from 'react-i18next';
const DetailsPlaceholder = () => {
const { t } = useTranslation();
return (
<h4 className="zero-state-section-text">{t('selectAction')}</h4>
);
};
export default DetailsPlaceholder;
When I try to load the page, I see the key 'selectAction' as the text (instead of the real text), and this error gets logged:
i18next::translator: missingKey es translation selectAction selectAction
All resource files should store strings under translation key (like in quick start for react-i18next):
{
"translation": {
"selectAction": "Select Action",
"workflow": "Workflow",
"details": "Details"
}
}
Here is a repository with a reproduced error and fixed configuration:
https://github.com/terales/reproduce-react-i18next-missingkey-error

Deploying my React app with react i18n throws a 404 error on locales.json

I've deployed my React app (CRA) on Netlify but it gives me 404 error on all the translations.json files. It's working locally so I'm lost.
My i18n settings file looks like this:
import i18n from 'i18next'
import Backend from 'i18next-xhr-backend'
import LanguageDetector from 'i18next-browser-languagedetector'
import { initReactI18next } from 'react-i18next'
export const appLocales = ['en', 'ja', 'nl']
i18n.use(Backend)
.use(LanguageDetector)
.use(initReactI18next)
.init({
debug: false,
lng: 'en',
fallbackLng: 'en',
whitelist: appLocales,
interpolation: {
escapeValue: false
}
})
export default i18n
Although the translations seems to be working I'm wondering why it's throwing the 404 error in the first place. Can anybody help me with this?

React i18next - Don't show translations until request finished

I am getting language info from backend. I would like to make the request to get language info, and then signalize to i18next that it can show translations.
Currently, it shows the default language translations for a second, until the request finishes and I call i18next.changeLanguage().
How would I achieve this ?
This is my config:
import i18n from "i18next";
import { initReactI18next } from "react-i18next";
import XHR from "i18next-xhr-backend";
i18n
.use(initReactI18next)
.use(XHR)
.init({
fallbackLng: "en-GB",
keySeparator: false,
interpolation: {
escapeValue: false
},
backend: {
loadPath: "/locales/{{lng}}.json"
}
});
I am using the useTranslation hook to get the t function:
const { t } = useTranslation();
In case of react-i18next make sure useSuspense is enabled or handle the ready state in HOCs or hooks yourself.
You need to wrap your root component with Suspense component to determine what should be rendered while translations are loading.
import React, { Suspense } from 'react';
import RealApp from './App';
import Loading from './Loading';
import { I18nextProvider } from 'react-i18next';
import App from './App';
function Root(props) {
return (
<Suspense fallback={<Loading />}>
<I18nextProvider i18n={i18n}>
<Root />
</I18nextProvider>
</Suspense>
);
}
For more info.

Resources