I'm trying to implement i18n in my React project which also uses Redux with the help of react-i18next
.
In this project, we use class components with decorators.
Initially, I wanted to try react-i18next
v10 but since it's relying on hooks and I cannot use those in class components, it's out of the question for me.
Falling back to the legacy v9, I followed the step by step guide ( https://react.i18next.com/legacy-v9/step-by-step-guide ) and performed the following steps:
i18n.js
config file with translationsi18nextProvider
ReactDOM.render(
<Provider store={store}>
<Router history={history}>
<I18nextProvider i18n={i18n}>
<RootContainer />
</I18nextProvider>
</Router>
</Provider>,
$root,
);
RootContainer
, with the withNamespaces()
HOC, but with decorator syntax@withNamespaces()
export default class SimpleComponent extends React.PureComponent {
// (... component class code ...)
}
Which is equivalent without decorators to the following:
class SimpleComponent extends React.PureComponent {
// (... component class code ...)
}
export default withNamespaces()(SimpleComponent);
I must be missing something since I get the following error during SSR:
react-i18next:: You will need pass in an i18next instance either by props, using I18nextProvider or by using i18nextReactModule. Learn more https://react.i18next.com/components/overview#getting-the-i-18-n-function-into-the-flow
0|ssr-dev | TypeError: Cannot read property 'wait' of null
0|ssr-dev | at NamespacesConsumerComponent.render (/client/node_modules/react-i18next/dist/commonjs/NamespacesConsumer.js:220:33)
Problem is, I'm no longer having this error if I remove the @withNamespaces()
HOC on my component class, but then I do not have {t, i18n}
in the component's props and therefore cannot translate anything. Moreover, the given URL in the error unfortunately doesn't exist anymore.
As I understood from the documentation, the <I18nextProvider>
is supposed to pass the {t, i18n}
values down the component tree, which is not in my case.
I find myself stuck between not being able to use v10 (we have a lot of components and I can't just refactor them all to functional components at the moment) and not being able to make v9 work either.
I'm running out of options and could use some hindsight if you ever encountered similar issues.
Thanks in advance.
I managed to use the last version of react-i18next in class by doing like this:
import { withTranslation } from 'react-i18next';
class RootContainer extends React.Component {
constructor(props) {
super(props);
}
render() {
<span>{this.props.t('Home')}</span>
}
}
For anyone wondering, I got it working by wrapping the <RootContainer>
child instead of wrapping <RootContainer>
itself in the renderer method, which leaves me with something like the following:
ReactDOM.render(
<Provider store={store}>
<Router history={history}>
<RootContainer />
</Router>
</Provider>,
$root,
);
import i18n from "../core/translations/i18n";
import {I18nextProvider} from "react-i18next";
@connectWithStore(mapStateToProps, mapActionsToProps)
export default class RootContainer extends React.PureComponent {
// (... class code ...)
render {
return (
<I18nextProvider i18n={i18n}>
<div>
<SimpleComponent/>
</div>
</I18nextProvider>
);
}
}
import {withNamespaces} from "react-i18next";
@withNamespaces()
export default class SimpleComponent extends React.PureComponent {
// (... class code ...)
componentDidMount() {
// Successfully logging the values below
console.warn("Got i18n props?", {
t: this.props.t,
i18n: this.props.i18n,
});
}
}
The only difference being that my renderer is a function, not a component per se, whereas RootContainer
is a fully-fledged React component (PureComponent, to be precise). Maybe it has to do with render chaining, not sure, but it still works as intended that way.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.