REACT I18Next在运行NPM构建后不显示显示翻译
运行构建命令后,React I18Next无法从JSON文件中获取翻译。请注意,一切正常,没有React Localhost中的构建:3000
我正在使用Django中的React Build File。
我检查了一个类似的问题,但该解决方案对我不起作用:使用i18next进行反应生产构建会导致翻译仅显示字符串
index.js:
import React, {Suspense} from 'react';
import ReactDOM from 'react-dom';
import i18n from "i18next";
import { initReactI18next } from "react-i18next";
import App from './App';
import 'bootstrap/dist/css/bootstrap.min.css';
import LanguageDetector from 'i18next-browser-languagedetector';
import Backend from 'i18next-http-backend';
import './index.css';
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'
}
]
i18n
.use(Backend)
.use(LanguageDetector)
.use(initReactI18next) // passes i18n down to react-i18next
.init({
lng: 'en',
react: {
useSuspense: false,
wait: 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: false,
whitelist: languages,
interpolation: {
escapeValue: false, // not needed for react as it escapes by default
},
nsSeperator: false,
keySeperator: false,
backend: {
loadPath: '/locales/{{lng}}/translation.json',
},
});
const loadingMarkup = (
<div className='index__loading'>
<h2>Loading..</h2>
</div>
)
ReactDOM.render(
<Suspense fallback={loadingMarkup}>
<React.StrictMode>
<App />
</React.StrictMode>,
</Suspense>,
document.getElementById('root')
);
登录头我单击以在语言之间切换的位置:
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);
另外,但结果相同,我分开文件并创建了i18n.js文件以使其如下: 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 = [
{
code: 'fr',
name: 'Français',
country_code: 'fr'
},
{
code: 'en',
name : 'English',
country_code: 'en'
},
{
code: 'ar',
name: 'العربية',
country_code: 'ly',
dir: 'rtl'
}
]
i18n
.use(Backend)
.use(LanguageDetector)
.use(initReactI18next) // passes i18n down to react-i18next
.init({
lng: 'en',
react: {
useSuspense: false,
wait: 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: false,
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 i18n from "i18next";
import i18next from "i18next";
import { I18nextProvider } from "react-i18next";
import App from './App';
import 'bootstrap/dist/css/bootstrap.min.css';
import './index.css';
import './i18n';
i18next.init({// <-- This was added
interpolation: {escapeValue: false},
});
i18next.init().then(() => // <-- This was added
ReactDOM.render(
<React.StrictMode>
<Suspense fallback={<div className='index__loading'><h2>Loading...</h2></div>}>
<I18nextProvider i18n={i18n}>
<App />
</I18nextProvider>
</Suspense>,
</React.StrictMode>,
document.getElementById('root')
)
);
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);
React i18next fails to fetch translation from the JSON file after running the build command. Note, everything works fine without the build in react localhost:3000
I'm using React build file in Django.
I checked a similar issue but the solution didn't work for me : Using i18next for a react production build causes the translation to display only strings
index.js :
import React, {Suspense} from 'react';
import ReactDOM from 'react-dom';
import i18n from "i18next";
import { initReactI18next } from "react-i18next";
import App from './App';
import 'bootstrap/dist/css/bootstrap.min.css';
import LanguageDetector from 'i18next-browser-languagedetector';
import Backend from 'i18next-http-backend';
import './index.css';
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'
}
]
i18n
.use(Backend)
.use(LanguageDetector)
.use(initReactI18next) // passes i18n down to react-i18next
.init({
lng: 'en',
react: {
useSuspense: false,
wait: 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: false,
whitelist: languages,
interpolation: {
escapeValue: false, // not needed for react as it escapes by default
},
nsSeperator: false,
keySeperator: false,
backend: {
loadPath: '/locales/{{lng}}/translation.json',
},
});
const loadingMarkup = (
<div className='index__loading'>
<h2>Loading..</h2>
</div>
)
ReactDOM.render(
<Suspense fallback={loadingMarkup}>
<React.StrictMode>
<App />
</React.StrictMode>,
</Suspense>,
document.getElementById('root')
);
loginheader where i click to switch between languages :
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);
Also, other way but same results, I seperated files and created i18n.js file to make it as follows :
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 = [
{
code: 'fr',
name: 'Français',
country_code: 'fr'
},
{
code: 'en',
name : 'English',
country_code: 'en'
},
{
code: 'ar',
name: 'العربية',
country_code: 'ly',
dir: 'rtl'
}
]
i18n
.use(Backend)
.use(LanguageDetector)
.use(initReactI18next) // passes i18n down to react-i18next
.init({
lng: 'en',
react: {
useSuspense: false,
wait: 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: false,
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 i18n from "i18next";
import i18next from "i18next";
import { I18nextProvider } from "react-i18next";
import App from './App';
import 'bootstrap/dist/css/bootstrap.min.css';
import './index.css';
import './i18n';
i18next.init({// <-- This was added
interpolation: {escapeValue: false},
});
i18next.init().then(() => // <-- This was added
ReactDOM.render(
<React.StrictMode>
<Suspense fallback={<div className='index__loading'><h2>Loading...</h2></div>}>
<I18nextProvider i18n={i18n}>
<App />
</I18nextProvider>
</Suspense>,
</React.StrictMode>,
document.getElementById('root')
)
);
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);
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论