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
Related
import React from "react";
import { createRoot } from 'react-dom/client';
import i18n from "i18next";
import { useTranslation, initReactI18next } from "react-i18next";
i18n
.use(initReactI18next) // passes i18n down to react-i18next
.init({
// the translations
// (tip move them in a JSON file and import them,
// or even better, manage them via a UI: https://react.i18next.com/guides/multiple-translation-files#manage-your-translations-with-a-management-gui)
resources: {
en: {
translation: {
"Welcome to React": "Welcome to React and react-i18next"
}
}
},
lng: "en", // if you're using a language detector, do not define the lng option
fallbackLng: "en",
interpolation: {
escapeValue: false // react already safes from xss => https://www.i18next.com/translation-function/interpolation#unescape
}
});
function App() {
const { t } = useTranslation();
return <h2>{t('Welcome to React')}</h2>;
}
// append app to dom
const root = createRoot(document.getElementById('root'));
root.render(
<App />
);
I just want best configure for localization.
I want to implement localization in my app. So i want to configure it as documentation. Is there any way i can manupulate my json file from admin panel.
I'm currently trying to translate my application with react-i18next and use multiple files for the translation because i want it to be clearly. That's why I wanted to use withNamespaces rather than withTranslation, but when I try to import withNamespaces from 'react-i18next' I get the following error message:
Attempted import error: 'withNamespaces' is not exported from 'react-i18next'.
This is my code:
import React, { Component } from 'react'
import {Link} from 'react-router-dom'
import { withNamespaces } from 'react-i18next'
class Navbar extends Component {
render(){
return (
<>
<ul>
{this.props.items.map(item => (
<li key={item.key}>
<Link to={item.route} className='jb-navbar_menu-item_link' >
{ this.props.t('header:'+item.name)}
</Link>
</li>
))}
</ul>
</>
)
}
}
export default withNamespaces('header')(Navbar)
What am I doing wrong? Am I importing this in a wrong way? Or is there something wrong with my config maybe?
This is my i18n.js:
import i18n from "i18next"
import { initReactI18next } from "react-i18next";
import translationEN from './locales/en/translation.json';
import translationDE from './locales/de/translation.json';
import headerDE from './locales/de/header.json';
import headerEN from './locales/en/header.json';
// the translations
const resources = {
de: {
translation: translationDE,
header: headerDE
},
en: {
translation: translationEN,
header: headerEN
}
};
i18n
.use(initReactI18next) // passes i18n down to react-i18next
.init({
ns:['translation', 'header'],
defaultNS: 'translation',
resources,
lng: "de",
fallbackLng: "de",
keySeparator: false, // we do not use keys in form messages.welcome
interpolation: {
escapeValue: false // react already safes from xss
}
}); // key in common namespace);
i18n.loadNamespaces('header')
export default i18n;
There is most probably a mismatch in your react-i18next version
withNamespaces has been deprecated in V10, you can use withTranslation
instead.
There is a good table in the react-i18next doc showing which components for which version:
https://react.i18next.com/latest/migrating-v9-to-v10
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
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`,
}
This is my configuration file. The consoloe log not shows any problem. At least nothing related with i18next.
import i18n from 'i18next';
import { initReactI18next } from 'react-i18next';
import detector from 'i18next-browser-languagedetector';
const xhrBackendOptions = {
loadPath: '/locales/{{lng}}/{{ns}}.json',
};
let XHR = require('i18next-xhr-backend').default;
let backend = XHR;
let options = {
fallbackLng: "en",
whitelist: ["en", "de", "es"],
ns:["user, claim", "translation"],
backend:xhrBackendOptions,
interpolation: {
escapeValue: false, // not needed for react as it escapes by default
}
};
console.info("Translation Activated");
i18n
.use(backend)
.use(detector)
.use(initReactI18next)
.init( options
);
export default i18n;
This is one f the .jsx files. The language is detected correctly, and nothing apears to fail but the function synply return the unchanged string
import React from 'react'
import {useSelector} from "react-redux";
import Auth from "ducks/auth";
import SparePart from "ducks/SparePart";
import ViewPort from "components/common/ViewPort";
import ListView from "components/crud/ListView";
import {useHistory} from "react-router";
import {useTranslation} from "react-i18next";
export default function (props) {
const { t,i18n } = useTranslation();
const history = useHistory();
debugger;
const isAdmin = useSelector(Auth.selectors.isAdmin);
const user = useSelector(Auth.selectors.user);
const elements = useSelector(SparePart.selectors.all);
return (
<ViewPort>
<ListView key="listView" title={t("spare parts")} model={SparePart} columns={columns} actions={actions}
navigable={!isAdmin} editable={isAdmin} />
</ViewPort>
);
}
Seems that the translation.json file had a extra comma