React-i18next suspense - reactjs

I m using React-i18next just like the example
import React, { Suspense } from 'react';
import { useTranslation } from 'react-i18next';
function App() {
return (
<Suspense fallback="loading">
<MyComponent />
</Suspense>
);
}
But Suspense is breaking one of my other components, namely react-masonry-layout. Is it possible to not using Suspense?
Thanks.

react-i18nnext uses Suspense by default. If you don't want to use it, you have to specify that in your configuration. If you have a i18n config file, you can set the useSuspense flag to false in the react section of the init object.
//Example config
i18n
.use(Backend)
.use(LanguageDetector)
.use(initReactI18next)
.init({
fallbackLng: "en",
debug: true,
resources: {
},
interpolation: {
escapeValue: false,
},
react: {
wait: true,
useSuspense: false,
},
})
Or you can just set the flag in your component.
<MyComponent useSuspense={false} />
Just be aware that choosing not to use Suspense has its implications. You have to write checks to handle the 'not ready' state ie: have a loading component render when state is not ready and your component render when the state is ready.Not doing so will result in rendering your translations before they loaded.

Date: 02/09/2021
Versions
"next": "^11.0.1",
"next-i18next": "^8.5.1",
In NextJs with SSR Suspense is not supported yet. So if you need to remove that you need to disable it on next-i18next.config.js.
Issue
Error: ReactDOMServer does not yet support Suspense.
Fix next-i18next.config.js
const path = require('path');
module.exports = {
i18n: {
defaultLocale: 'en',
locales: ['en', 'de'],
},
localePath: path.resolve('./assets/locales'),
react: {
useSuspense: false,
},
};

Related

i18next missing key but other key was found

I dont understand nothing anymore.
I use i18next and want to access to my key but it does not work.
i18next::translator: missingKey de translation profile profile
i18next::translator: missingKey de translation profile profile
i18next::translator: missingKey de translation profile profile
this is my translation.json
{
"app_name": "Test (NEW DE)",
"profile": "ss"
}
this works:
<Text>{ t('app_name') }</Text>
this not working:
<Text>{ t('profile') }</Text>
can anyone explain me why its not working correctly ?
i18next
import i18next from "i18next";
import { initReactI18next } from "react-i18next";
import LanguageDetector from 'i18next-browser-languagedetector';
import HttpApi from 'i18next-http-backend';
i18next
.use(HttpApi)
.use(LanguageDetector)
.use(initReactI18next)
.init({
react: {
useSuspense: false
},
fallbackLng: 'en',
compatibilityJSON: 'v3',
lng: 'de',
debug: process.env.NODE_ENV === 'development',
backend: {
loadPath: `http://192.168.0.249:4000/public/locales/{{lng}}/translation.json`,
},
interpolation: {
escapeValue: false,
},
keySeparator: '.',
});
export default i18next;
I suspect, you're calling the t function too early and are not waiting for the translations to be fully loaded.
If you're not using suspense: useSuspense: false you need to make sure you check for the ready flag instead.
https://react.i18next.com/latest/usetranslation-hook#not-using-suspense
// additional ready will state if translations are loaded or not
const { t, i18n, ready } = useTranslation('ns1');
https://react.i18next.com/latest/withtranslation-hoc#not-using-suspense
// use tReady prop in MyComponent to check if translations
// are already loaded or not
const ExtendedComponent = withTranslation()(MyComponent);
<ExtendedComponent />

React-i18next does not load translations on page reload

I am using react-I18next in my nextjs application. I don't want to use next-I18next because I tried to use it but couldn't make it work. But react-i18next is working in my application for now and I am able to change language from english to german and back. However if I reload the page I get this error.
TypeError: i18n.changeLanguage is not a function
What could be the possibel cause of this error and how can I fix it?
P.S In my app.ts file I am not using Suspense because it gives me this error
ReactDOMServer does not yet support Suspense.
Here is my i18.ts file
/* eslint-disable no-duplicate-imports */
import i18n from 'i18next';
import LanguageDetector from 'i18next-browser-languagedetector';
import backend from 'i18next-xhr-backend';
import { initReactI18next } from 'react-i18next';
import loginDE from '../../public/locales/de/loginDE.json';
import loginEN from '../../public/locales/en/loginEN.json';
// the translations
// (tip move them in a JSON file and import them)
const resources = {
en: {
translation: loginEN,
},
de: {
translation: loginDE,
},
};
void i18n
.use(backend)
.use(LanguageDetector)
.use(initReactI18next) // passes i18n down to react-i18next
.init({
fallbackLng: 'en',
interpolation: {
escapeValue: false, // react already safes from xss
},
resources,
lng: 'en',
keySeparator: false, // we do not use keys in form messages.welcome
react: {
useSuspense: true,
},
});
export default i18n;
ReactDOMServer does not yet support Suspense.
Change your useSuspense value like that:
react: { useSuspense: false },
TypeError: i18n.changeLanguage is not a function
Make sure you wrapped a component with I18nextProvider

Error: Should have a queue. This is likely a bug in React. Please file an issue

I am using react-i18next. Sometime on init function component facing React issue. Any idea what may causing it?
My config
import i18n from "i18next";
import resources from "./locales";
import { initReactI18next } from "react-i18next";
const options = {
debug: false,
lng: "en",
resources: resources,
fallbacking: "en",
};
i18n.use(initReactI18next).init(options);
export default i18n;
My versions
"react": "^16.13.1",
"react-i18next": "^11.7.2",
stupid bug which was inited by myself. I was simple declaring before return dom component, like
const test = (props)=>{
if(props.test){
return <p>test</p>
}
const { t } = useTranslation("Test");//this must be on very top
return <p>Main {t('test_variable')}</p>
}
I wish if react could be more clear in logging bugs
you might try this configuration, it works with me perfectly
import i18n from "i18next";
import LanguageDetector from "i18next-browser-languagedetector";
import { initReactI18next, Trans } from "react-i18next";
import lang from "assets/lang";
i18n.use(LanguageDetector)
.use(initReactI18next)
.init({
// we init with resources
resources: lang,
fallbackLng: "en",
debug: true,
// have a common namespace used around the full app
ns: ["basic"],
defaultNS: "basic",
keySeparator: false, // we use content as keys
interpolation: {
escapeValue: false,
},
});
window.document.body.dir = i18n.t("dir");
export default i18n;
const Tr = (props) => (
<Trans i18nKey={props.tr} {...props}>
{props.children}
</Trans>
);
Tr.tr = (key, ...rest) => i18n.t(key, ...rest);
export { Tr };
I've also had such a problem and finally I found that the main reason of this problem is using hooks in wrong place, you need to use your hook in parent component and not the child one. For example, you have a todo list and todo component, you have to use it in todo list and not in todo.

Gatsby - SSR i18n translation are loaded on client

I have a multilingual gatsby website, I try to improve the lighthouse performance score, so i followed this guide to generate my page with the translation in the html. Here is my gatsby-ssr.js file
import { renderToString } from 'react-dom/server'
import Backend from 'i18next-sync-fs-backend'
import i18n from "./src/locales/i18n"
const namespaces = [...my ns...];
export const replaceRenderer = ({ bodyComponent, replaceBodyHTMLString }) => {
i18n
.use(Backend)
.init({
initImmediate: false,
backend: {
loadPath: 'src/locales/{{lng}}/{{ns}}.json',
},
})
// load the common namespace
.loadNamespaces(namespaces, (err) => {
replaceBodyHTMLString(renderToString(bodyComponent))
})
}
My i18n.js file :
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({
fallbackLng: "fr",
ns: ['translation'],
defaultNS: 'translation',
load: 'languageOnly',
debug: false,
interpolation: {
escapeValue: false, // not needed for react!!
},
react: {
wait: true,
},
});
export default i18n;
I use the HOC withNamespaces from react-i18next (v8) in my page like that export default withNamespaces('home')(IndexPage);
This works well because the generated HTML has all the text translated but when I access to my page the client will load a second time the translation and re-render the page, this cause a flickering on the page and big layout shift so lighthouse really not like it. I believe this is in relation with i18next-xhr-backend but I'm stuck.
I expect my page to not load the translation on page load, because the html has already the text translated so I don't need to load translation again

How to fix 'no fallback UI was specified' in react i18next using hooks

I am trying to implement i18next in my react component using the useTranslation hook, but it keeps saying:
Uncaught Error: Test suspended while rendering, but no fallback UI was specified.
Add a <Suspense fallback=...> component higher in the tree to provide a loading indicator or placeholder to display.
How can I add the <Suspense> any higher than what I've got? What am I doing wrong? How do I fix this? It seems to work OK when I use the <Translation> component. Naturally, it also seems to work OK if I turn Suspense off and try to handle it myself, but that sort of defeats the purpose, I think. How can I make this actually work? Do I have the Fetch backend misconfigured?
Test.js
import React, { Suspense, useState, useEffect, lazy } from "react";
import PropTypes from "prop-types";
import i18n from './i18n';
import { useTranslation } from 'react-i18next';
export default function Test( props ){
const { t, i18n } = useTranslation( 'bingo_game' );
return (
<Suspense fallback={<div>Loading...</div>}>
<div>
Pant leg
</div>
</Suspense>
)
}
Test.propTypes = {
token: PropTypes.string.isRequired,
};
and
i18n.js
import i18n from "i18next";
import LngDetector from "i18next-browser-languagedetector";
import { initReactI18next } from "react-i18next";
import Fetch from "i18next-fetch-backend";
i18n
.use(LngDetector) //language detector
.use(Fetch)
.use(initReactI18next)
.init({
backend: {
loadPath: "/infra/locales/{{ns}}.json",
// path to post missing resources
addPath: "locales/add/{{ns}}",
// define how to stringify the data when adding missing resources
stringify: JSON.stringify
},
defaultNS: "base",
fallbackLng: "en",
debug: true,
initImmediate: false
});
export default i18n;
I've gone over the docs that I could find as well as this SO post that is not my issue.
in your i18n file add this, it will do the magic :)
.init({
react: {
useSuspense: false,
...
});
It's not best way but I can recommend you to turn off suspense by adding this lines to your's config
i18n
.init({
...
// react i18next special options (optional)
react: {
useSuspense: false,
wait: false,
},
});
Using useSuspense: false is ok but you need to use ready state in this case as well, otherwise your translation keys appear at interface until i18next is ready... Similar to this:
const { t, i18n, ready } = useTranslation()
and in the render section:
{ready && (<SampleComponent />)}
You can set useSuspense: false in useTranslation options.
const { t } = useTranslation("your-namespace", {useSuspense: false});
https://react.i18next.com/latest/usetranslation-hook#not-using-suspense

Resources