React i18next fails to load translation.json as json. everything is functioning well before I use the build folder
I'm using React / Django.
i18n.js :
import i18n from 'i18next';
import { initReactI18next } from 'react-i18next';
import Backend from 'i18next-http-backend';
import LanguageDetector from 'i18next-browser-languagedetector';
// don't want to use this?
// have a look at the Quick start guide
// for passing in lng and translations on init
const Languages = ['ar', 'en', 'fr']
i18n
.use(Backend)
.use(LanguageDetector)
.use(initReactI18next) // passes i18n down to react-i18next
.init({
lng: 'en',
react: {
useSuspense: true,
},
// 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)
supported: ["en", "fr", "ar"],
fallbackLng: "en",
detection: {
order: ['path', 'cookie', 'htmlTag', 'localStorage', 'subdomain'],
caches: ['cookie'],
},
debug: true,
whitelist: Languages,
interpolation: {
escapeValue: false, // not needed for react as it escapes by default
},
nsSeperator: false,
keySeperator: false,
backend: {
loadPath: '/locales/{{lng}}/{{ns}}.json',
},
});
export default i18n;
index.js :
import React, {Suspense} from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import 'bootstrap/dist/css/bootstrap.min.css';
import './index.css';
import './i18n';
ReactDOM.render(
<React.StrictMode>
<Suspense fallback={(<div className='index__loading'><h2>Loading...</h2></div>)}>
<App />
</Suspense>,
</React.StrictMode>,
document.getElementById('root')
);
here's where I switch between languages loginheader.js :
import React, { Fragment, useEffect, useState } from 'react';
import './LoginHeader.css'
import { Link } from 'react-router-dom';
import { connect } from 'react-redux';
import { logout } from '../actions/auth';
import SortIcon from '@mui/icons-material/Sort';
import ExpandMoreIcon from '@mui/icons-material/ExpandMore';
import Alert from './Alert';
// import Drower from './Drower';
import Logo from '../assets/images/logo.png';
import { useTranslation } from "react-i18next";
import { FormControl, Select, MenuItem } from '@mui/material';
// import LanguageIcon from '@mui/icons-material/Language';
import i18next from 'i18next';
import cookies from 'js-cookie';
const languages = [
{
code: 'fr',
name: 'Français',
country_code: 'fr'
},
{
code: 'en',
name : 'English',
country_code: 'en'
},
{
code: 'ar',
name: 'العربية',
country_code: 'ly',
dir: 'rtl'
}
]
function LoginHeader({ logout, isAuthenticated }) {
const currentLanguageCode = cookies.get('i18next') || 'en';
const currentLanguage = languages.find(l => l.code === currentLanguageCode);
useEffect (() => {
document.body.dir = currentLanguage.dir || 'ltr'
// document.title = t('app_title')
},[currentLanguage]);
const { t } = useTranslation()
const [value, setValue] = useState('English')
const handleChange = (event) => {
setValue(event.target.value)
}
const guestLinks = () => (
<Fragment>
<div className='loginHeader__right'>
<div className='middle__header__bx'>
<div className='loginHeader__main__btns'>
<Link className='loginHeader__loginButton' to='/login'><button>{t('header_login')}</button></Link>
<Link className='loginHeader__signupButton' to='/signup'><button>{t('header_signup')}</button></Link>
</div>
<div className='loginHeader__services__dropdown'>
<button className='dropdown__btn dropdown__services'>{t('header.services')}<ExpandMoreIcon className='services__expand'/></button>
<div className='dropdown__content dropdown__services__content'>
<Link className='loginHeader__menuItem' to='/visa-assist'>{t('services_visaAssist')}</Link>
<Link className='loginHeader__menuItem' to='/admission'>{t('services_addmissionOffers')}</Link>
<Link className='loginHeader__menuItem' to='/application-form'>{t('services_forms')}</Link>
<Link className='loginHeader__menuItem' to='/premuim-support'>{t('services_premium')}</Link>
</div>
</div>
{/* start of lang box */}
<div className='loginHeader__lang'>
<div className='loginHeader__lang__bx'>
<div className='loginHeader__lang__container'>
<Select
className='loginHeader__select'
labelId='select-demo'
id='language-select'
value={value}
onChange={handleChange}
disableUnderline
variant='standard'
>
{languages.map(({code, name, country_code}) =>
<MenuItem
value={name}
key={country_code}
>
<button
onClick={() => i18next.changeLanguage(code)}
className='loginHeader__lang__btn'
>
{name}
</button>
</MenuItem>
)}
</Select>
</div>
</div>
</div>
{/* end of lang box */}
<div className='loginHeader__services__dropdown sortIcon__bx'>
<SortIcon className='dropdown__btn loginHeader__sortIcon'/>
<div className='dropdown__content sortIcon__dropdown'>
<Link className='loginHeader__menuItem' to='/premuim-support'>{t('header_dropdown_prem')}</Link>
<Link className='loginHeader__menuItem' to='/visa-assist'>{t('header_dropdown_visaAssist')}</Link>
<Link className='loginHeader__menuItem' to='/admission'>{t('header_dropdown_admission')}</Link>
<Link className='loginHeader__menuItem' to='/request-service'>{t('header_dropdown_requestService')}</Link>
<Link className='loginHeader__menuItem' to='/contact'>{t('header_dropdown_contact')}</Link>
<Link className='loginHeader__menuItem' to='/signup'>{t('header_signup')}</Link>
<Link className='loginHeader__menuItem' to='/login'>{t('header_login')}</Link>
<Link className='loginHeader__menuItem' to='/guid'>{t('header_dropdown_guide')}</Link>
</div>
</div>
</div>
</div>
</Fragment>
);
const authLinks = () => (
<Fragment>
<div className='loginHeader__right'>
{/* <button onClick={logout} className='loginHeader__logout__btn'>{t('header_logout')}</button> */}
{/* start of lang box */}
<div className='loginHeader__logged__lang'>
<div className='loginHeader__lang__bx'>
<FormControl>
<Select
className='loginHeader__select'
labelId='select-demo'
id='language-select'
value={value}
onChange={handleChange}
disableUnderline
variant='standard'
>
{languages.map(({code, name, country_code}) =>
<MenuItem
value={name}
key={country_code}
>
<button
onClick={() => i18next.changeLanguage(code)}
className='loginHeader__lang__btn'
disabled={code === currentLanguageCode}
>
{name}
</button>
</MenuItem>
)}
</Select>
</FormControl>
</div>
</div>
{/* end of lang box */}
<div className='loginHeader__services__dropdown loggedin__icon__bx'>
<button className='dropdown__btn'><SortIcon className='loginHeader__sortIcon logedin__sortIcon'/></button>
<div className='dropdown__content logged__sortIcon__dropdown'>
<Link className='loginHeader__menuItem' to='/premuim-support'>{t('header_dropdown_prem')}</Link>
<Link className='loginHeader__menuItem' to='/admission'>{t('header_dropdown_admission')}</Link>
<Link className='loginHeader__menuItem' to='/visa-assist'>{t('header_dropdown_visaAssist')}</Link>
<Link className='loginHeader__menuItem' to='/request-service'>{t('header_dropdown_requestService')}</Link>
<Link className='loginHeader__menuItem' to='/contact'>{t('header_dropdown_contact')}</Link>
<Link className='loginHeader__menuItem' to='/guid'>{t('header_dropdown_guide')}</Link>
<button onClick={logout} className='logout__btn'>{t('header_logout')}</button>
</div>
</div>
</div>
</Fragment>
);
return (
<div className='loginHeader'>
<div className='loginHeader__left'>
<Link to='/'><img className='logo' src={Logo} alt='logo'/></Link>
</div>
{isAuthenticated ? authLinks() : guestLinks()}
<Alert/>
</div>
)
};
const mapStateToProps = state => ({
isAuthenticated: state.auth.isAuthenticated
});
export default connect(mapStateToProps, { logout }) (LoginHeader);
debug console network/headers:
Request URL: http://127.0.0.1:8000/locales/en/translation.json
Request Method: GET
Status Code: 200 OK
Remote Address: 127.0.0.1:8000
Referrer Policy: same-origin
Content-Length: 948
Content-Type: text/html; charset=utf-8
Cross-Origin-Opener-Policy: same-origin
Date: Sat, 02 Jul 2022 13:54:00 GMT
Referrer-Policy: same-origin
Server: WSGIServer/0.2 CPython/3.10.2
Vary: Origin
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
Accept: */*
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Connection: keep-alive
Cookie: csrftoken=KKBUsud0hxf0n2XkfSuQw9Hx3RLkHnSTyJHzGL8xyg502fPxxcDab3113rLJxQyu; i18next=en
Host: 127.0.0.1:8000
Referer: http://127.0.0.1:8000/
sec-ch-ua: ".Not/A)Brand";v="99", "Google Chrome";v="103", "Chromium";v="103"
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: "Windows"
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-origin
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36
network/preview: You need to enable JavaScript to run this app.
network/response :
<!doctype html><html lang="en"><head><meta charset="utf-8"/><link rel="icon" href="/favicon.ico"/><meta name="viewport" content="width=device-width,initial-scale=1"/><meta name="theme-color" content="#000000"/><meta name="description" content="Web site created using create-react-app"/><link rel="apple-touch-icon" href="/logo192.png"/><link rel="preconnect" href="https://fonts.googleapis.com"><link rel="preconnect" href="https://fonts.gstatic.com" crossorigin><link href="https://fonts.googleapis.com/css2?family=Lora:ital,wght@0,400;0,500;0,600;0,700;1,700&family=Roboto:wght@300;400;500;700;900&display=swap" rel="stylesheet"><link rel="manifest" href="/manifest.json"/><title>Diploman</title><script defer="defer" src="/static/js/main.1e76e6bb.js"></script><link href="/static/css/main.e38e49bd.css" rel="stylesheet"></head><body dir="ltr"><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div></body></html>
CodePudding user response:
Make sure the translation json files are hosted/hosted as static resources in your Django (WSGIServer) server. https://www.linkedin.com/pulse/serving-static-files-wsgi-tercio-a-oliveira