No error is thrown if the translation file download fails
See original GitHub issue🐛 Bug Report
I installed this library to download the translation files as needed (lazy loading), inside my project. If the file is not in the server or the server is offline for some reason, I want to get whatever error happened and show it nicely to the user.
The main problem happens when the file is not in the server or the server is offline for some reason. This library simply throw some warnings on the console.log and change the language anyway (even if the file was not downloaded), like so:
As a default behavior, I’d expect the i18n.changeLanguage Promise to throw an error so I can treat it inside a try/catch block function. Or maybe an extra configuration key called “ifFileNotDownloadedChangeLanguageAnyway” so we can prevent the language to be changed if the download fails.
To Reproduce
The installation:
npx create-react-app pig --template typescript
cd pig
Then install the libraries:
npm i react-i18next i18next i18next-http-backend @material-ui/core
My i18n.ts
file:
import i18n from "i18next";
import { initReactI18next } from "react-i18next";
import Backend from 'i18next-http-backend'
i18n
.use(initReactI18next)
.use(Backend)
.init({
backend:{
loadPath: '/translations/{{lng}}.json'
},
react:{useSuspense:false},
debug: true,
lng: "en",
keySeparator: false,
interpolation: {
escapeValue: false
}
});
export default i18n;
My index.tsx
:
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import './i18n';
import App from './App';
import reportWebVitals from './reportWebVitals';
ReactDOM.render(
<App />,
document.getElementById('root')
);
reportWebVitals();
My huge App.tsx
:
import { Backdrop, CircularProgress, Button } from "@material-ui/core"
import { makeStyles } from '@material-ui/core/styles';
import './App.css';
import { useTranslation } from 'react-i18next';
import { useState } from "react"
const useStyles = makeStyles((theme) => ({
backdrop: {
zIndex: theme.zIndex.drawer + 1,
color: '#fff',
},
}));
function App() {
const [lang, setLang] = useState("en");
const [block, setBlock] = useState(false);
const { t, i18n, ready } = useTranslation();
const handle = async () => {
try{
setBlock(true)
const newLang = lang==="en"?"pt":"en"
await i18n.changeLanguage(newLang)
setLang(newLang)
setBlock(false)
}catch(e){
console.log("this is never called", e)
}
}
const classes = useStyles();
return (
<div className="App">
<Backdrop className={classes.backdrop} open={block || !ready}>
<CircularProgress/>
</Backdrop>
{ready && (
<>
<h1 onClick={handle}>{t("pig")}</h1>
<Button onClick={handle} >Click me</Button>
</>
)}
</div>
);
}
export default App;
My folder structure/translation files:
Then you can simply exclude the pt.json
file or block the requests to this file in the chrome dev tools > Network tab and click the “Click me” button.
My Environment
- runtime version: node v10.24.0, npm v6.14.11,
- i18next version: ^20.2.1
- os: Windows
Issue Analytics
- State:
- Created 2 years ago
- Comments:8 (4 by maintainers)
Thanks for the reply guys! As @jamuhl and @adrai pointed, I was able to make it work after spending a while discovering how those events and callbacks behave.
The code got a little big since we don’t have a library that throws an error when an error occurs, but now it works!
@nunocastromartins I’ll paste the code here with some comments, in case it helps you:
The
i18n.ts
file:The
App.tsx
file:And then I created an empty json inside my dev.json file, in the translations folder.
because
either it is loading -> suspense is thrown or it loaded / or gave up after retries
if your webapp and translations are running on the same server nothing will run anyway. if you run multiple instances / microservices reload mechanism in i18next should be enough.
but feel free to add a PR