在 class 组件中使用 react-i18next
Using react-i18next within a class component
我正在尝试使用 react-i18next 翻译我的应用程序。我知道如何将它与简单的 const 组件一起使用,但不能在 class 中使用。
我正在使用 I18nextProvider。这是我的 App.js 文件。
import React, { Component } from 'react';
import { Provider } from 'react-redux';
import { BrowserRouter } from 'react-router-dom';
import { I18nextProvider } from 'react-i18next';
import i18next from 'i18next';
// eslint-disable-next-line import/no-extraneous-dependencies
import { hot } from 'react-hot-loader';
import 'bootstrap/dist/css/bootstrap.css';
import '../../scss/app.scss';
import Router from './Router';
import store from './store';
import ScrollToTop from './ScrollToTop';
import { config as i18nextConfig } from '../../translations';
i18next.init(i18nextConfig);
class App extends Component {
constructor() {
super();
this.state = {
loading: true,
loaded: false,
};
}
componentDidMount() {
window.addEventListener('load', () => {
this.setState({ loading: false });
setTimeout(() => this.setState({ loaded: true }), 500);
});
}
render() {
const { loaded, loading } = this.state;
return (
<Provider store={store}>
<BrowserRouter basename="/easydev">
<I18nextProvider i18n={i18next}>
<ScrollToTop>
{!loaded &&
<div className={`load${loading ? '' : ' loaded'}`}>
<div className="load__icon-wrap">
<svg className="load__icon">
<path fill="#4ce1b6" d="M12,4V2A10,10 0 0,0 2,12H4A8,8 0 0,1 12,4Z" />
</svg>
</div>
</div>
}
<div>
<Router />
</div>
</ScrollToTop>
</I18nextProvider>
</BrowserRouter>
</Provider>
);
}
}
export default hot(module)(App);
现在在基于 const 的组件中使用它非常容易。这是一个例子:
import React from 'react';
import { Card, CardBody, Col } from 'reactstrap';
import HeartOutlineIcon from 'mdi-react/HeartOutlineIcon';
import { translate } from 'react-i18next';
import PropTypes from 'prop-types';
const InfoCard = ({ t }) => (
<Col md={12} xl={3} lg={6} sm={12} xs={12}>
<Card>
<CardBody className="dashboard__health-chart-card">
<div className="card__title">
<h5 className="bold-text">{t('dashboard_fitness.heartrate')}</h5>
</div>
<div className="dashboard__health-chart">
<div className="dashboard__health-chart-info">
<HeartOutlineIcon style={{ fill: '#ff4861' }} />
<p className="dashboard__health-chart-number">96</p>
<p className="dashboard__health-chart-units">b/min</p>
</div>
</div>
</CardBody>
</Card>
</Col>
);
InfoCard.propTypes = {
t: PropTypes.func.isRequired,
};
export default translate('common')(InfoCard);
如您所见,我只是从 react-i18next 导入翻译,我几乎准备好使用 t 函数。
如何在 class 组件中实现相同的目的?我想在这个 class:
中实现它
/* eslint-disable react/no-typos */
import React, { PureComponent } from 'react';
import { DropdownItem, DropdownMenu, DropdownToggle, UncontrolledDropdown } from 'reactstrap';
import { translate } from 'react-i18next';
import MenuDownIcon from 'mdi-react/ChevronDownIcon';
import MagnifyIcon from 'mdi-react/MagnifyIcon';
class TradesTableControls extends PureComponent {
constructor() {
super();
this.state = {
rows: 10,
};
}
changeRowAmount = (rows) => {
switch (rows) {
case 10:
this.setState({ rows: 10 });
break;
case 25:
this.setState({ rows: 25 });
break;
case 50:
this.setState({ rows: 50 });
break;
case 100:
this.setState({ rows: 100 });
break;
default:
this.setState({ rows: 10 });
break;
}
};
render() {
return (
<div className="trades-table__controls-wrap">
<div className="trades-table__controls">
<UncontrolledDropdown>
<DropdownToggle className="icon icon--right" outline size="sm">
<p>
{t('history.controls.show')}
{this.state.rows}
{t('history.controls.results')}
<MenuDownIcon />
</p>
</DropdownToggle>
<DropdownMenu className="dropdown__menu">
<DropdownItem onClick={() => this.changeRowAmount(10)}>10</DropdownItem>
<DropdownItem onClick={() => this.changeRowAmount(25)}>25</DropdownItem>
<DropdownItem onClick={() => this.changeRowAmount(50)}>50</DropdownItem>
<DropdownItem onClick={() => this.changeRowAmount(100)}>100</DropdownItem>
</DropdownMenu>
</UncontrolledDropdown>
</div>
<div className="trades-table__controls-right">
<div className="trades-table__control-search">
<input placeholder="Search" />
<div className="trades-table__control-search-icon"><MagnifyIcon /></div>
</div>
</div>
</div>
);
}
}
export default translate('common')(TradesTableControls);
我对 React 和 ES6 很陌生,但我无法在线找到解决方案。非常感谢任何帮助!
谢谢!
就像 t
在 functional
组件中作为 props 可用一样,您可以在包装 TradesTableComponent
后从 class 组件中的 props
访问它translate HOC
。您需要做的就是 destructure
它来自 render 方法中的道具,例如
const { t } = this.props;
相关代码
render() {
const { t } = this.props;
return (
<div className="trades-table__controls-wrap">
<div className="trades-table__controls">
<UncontrolledDropdown>
<DropdownToggle className="icon icon--right" outline size="sm">
<p>
{t('history.controls.show')}
{this.state.rows}
{t('history.controls.results')}
<MenuDownIcon />
</p>
</DropdownToggle>
<DropdownMenu className="dropdown__menu">
<DropdownItem onClick={() => this.changeRowAmount(10)}>10</DropdownItem>
<DropdownItem onClick={() => this.changeRowAmount(25)}>25</DropdownItem>
<DropdownItem onClick={() => this.changeRowAmount(50)}>50</DropdownItem>
<DropdownItem onClick={() => this.changeRowAmount(100)}>100</DropdownItem>
</DropdownMenu>
</UncontrolledDropdown>
</div>
<div className="trades-table__controls-right">
<div className="trades-table__control-search">
<input placeholder="Search" />
<div className="trades-table__control-search-icon"><MagnifyIcon /></div>
</div>
</div>
</div>
);
}
这是一个示例,说明如何使用带有 class 定义的 i18next + React + Typescript https://gitlab.com/damjan89/i18next-typescript-example
目前(即 2021 年)文档建议打包 HOC withTranslation()
:
import React from 'react';
import { withTranslation } from 'react-i18next';
class MyComponent extends Component {
return <p>{this.props.t('key')}</p>
}
export default withTranslation()(MyComponent);
如果你喜欢使用命名空间然后导出:
export default withTranslation('namespace')(MyComponent);
参考:官方 docs.
这是一个如何在 React Native 的 class-based 组件 中使用 translation
的工作示例。
import { withTranslation } from 'react-i18next';
class PersonalScreen extends React.Component {
render() {
const { t } = this.props;
return (
<Text>{t('Translate this text')}</Text>
)
}
}
export default withTranslation()(PersonalScreen)
我正在尝试使用 react-i18next 翻译我的应用程序。我知道如何将它与简单的 const 组件一起使用,但不能在 class 中使用。
我正在使用 I18nextProvider。这是我的 App.js 文件。
import React, { Component } from 'react';
import { Provider } from 'react-redux';
import { BrowserRouter } from 'react-router-dom';
import { I18nextProvider } from 'react-i18next';
import i18next from 'i18next';
// eslint-disable-next-line import/no-extraneous-dependencies
import { hot } from 'react-hot-loader';
import 'bootstrap/dist/css/bootstrap.css';
import '../../scss/app.scss';
import Router from './Router';
import store from './store';
import ScrollToTop from './ScrollToTop';
import { config as i18nextConfig } from '../../translations';
i18next.init(i18nextConfig);
class App extends Component {
constructor() {
super();
this.state = {
loading: true,
loaded: false,
};
}
componentDidMount() {
window.addEventListener('load', () => {
this.setState({ loading: false });
setTimeout(() => this.setState({ loaded: true }), 500);
});
}
render() {
const { loaded, loading } = this.state;
return (
<Provider store={store}>
<BrowserRouter basename="/easydev">
<I18nextProvider i18n={i18next}>
<ScrollToTop>
{!loaded &&
<div className={`load${loading ? '' : ' loaded'}`}>
<div className="load__icon-wrap">
<svg className="load__icon">
<path fill="#4ce1b6" d="M12,4V2A10,10 0 0,0 2,12H4A8,8 0 0,1 12,4Z" />
</svg>
</div>
</div>
}
<div>
<Router />
</div>
</ScrollToTop>
</I18nextProvider>
</BrowserRouter>
</Provider>
);
}
}
export default hot(module)(App);
现在在基于 const 的组件中使用它非常容易。这是一个例子:
import React from 'react';
import { Card, CardBody, Col } from 'reactstrap';
import HeartOutlineIcon from 'mdi-react/HeartOutlineIcon';
import { translate } from 'react-i18next';
import PropTypes from 'prop-types';
const InfoCard = ({ t }) => (
<Col md={12} xl={3} lg={6} sm={12} xs={12}>
<Card>
<CardBody className="dashboard__health-chart-card">
<div className="card__title">
<h5 className="bold-text">{t('dashboard_fitness.heartrate')}</h5>
</div>
<div className="dashboard__health-chart">
<div className="dashboard__health-chart-info">
<HeartOutlineIcon style={{ fill: '#ff4861' }} />
<p className="dashboard__health-chart-number">96</p>
<p className="dashboard__health-chart-units">b/min</p>
</div>
</div>
</CardBody>
</Card>
</Col>
);
InfoCard.propTypes = {
t: PropTypes.func.isRequired,
};
export default translate('common')(InfoCard);
如您所见,我只是从 react-i18next 导入翻译,我几乎准备好使用 t 函数。
如何在 class 组件中实现相同的目的?我想在这个 class:
中实现它/* eslint-disable react/no-typos */
import React, { PureComponent } from 'react';
import { DropdownItem, DropdownMenu, DropdownToggle, UncontrolledDropdown } from 'reactstrap';
import { translate } from 'react-i18next';
import MenuDownIcon from 'mdi-react/ChevronDownIcon';
import MagnifyIcon from 'mdi-react/MagnifyIcon';
class TradesTableControls extends PureComponent {
constructor() {
super();
this.state = {
rows: 10,
};
}
changeRowAmount = (rows) => {
switch (rows) {
case 10:
this.setState({ rows: 10 });
break;
case 25:
this.setState({ rows: 25 });
break;
case 50:
this.setState({ rows: 50 });
break;
case 100:
this.setState({ rows: 100 });
break;
default:
this.setState({ rows: 10 });
break;
}
};
render() {
return (
<div className="trades-table__controls-wrap">
<div className="trades-table__controls">
<UncontrolledDropdown>
<DropdownToggle className="icon icon--right" outline size="sm">
<p>
{t('history.controls.show')}
{this.state.rows}
{t('history.controls.results')}
<MenuDownIcon />
</p>
</DropdownToggle>
<DropdownMenu className="dropdown__menu">
<DropdownItem onClick={() => this.changeRowAmount(10)}>10</DropdownItem>
<DropdownItem onClick={() => this.changeRowAmount(25)}>25</DropdownItem>
<DropdownItem onClick={() => this.changeRowAmount(50)}>50</DropdownItem>
<DropdownItem onClick={() => this.changeRowAmount(100)}>100</DropdownItem>
</DropdownMenu>
</UncontrolledDropdown>
</div>
<div className="trades-table__controls-right">
<div className="trades-table__control-search">
<input placeholder="Search" />
<div className="trades-table__control-search-icon"><MagnifyIcon /></div>
</div>
</div>
</div>
);
}
}
export default translate('common')(TradesTableControls);
我对 React 和 ES6 很陌生,但我无法在线找到解决方案。非常感谢任何帮助!
谢谢!
就像 t
在 functional
组件中作为 props 可用一样,您可以在包装 TradesTableComponent
后从 class 组件中的 props
访问它translate HOC
。您需要做的就是 destructure
它来自 render 方法中的道具,例如
const { t } = this.props;
相关代码
render() {
const { t } = this.props;
return (
<div className="trades-table__controls-wrap">
<div className="trades-table__controls">
<UncontrolledDropdown>
<DropdownToggle className="icon icon--right" outline size="sm">
<p>
{t('history.controls.show')}
{this.state.rows}
{t('history.controls.results')}
<MenuDownIcon />
</p>
</DropdownToggle>
<DropdownMenu className="dropdown__menu">
<DropdownItem onClick={() => this.changeRowAmount(10)}>10</DropdownItem>
<DropdownItem onClick={() => this.changeRowAmount(25)}>25</DropdownItem>
<DropdownItem onClick={() => this.changeRowAmount(50)}>50</DropdownItem>
<DropdownItem onClick={() => this.changeRowAmount(100)}>100</DropdownItem>
</DropdownMenu>
</UncontrolledDropdown>
</div>
<div className="trades-table__controls-right">
<div className="trades-table__control-search">
<input placeholder="Search" />
<div className="trades-table__control-search-icon"><MagnifyIcon /></div>
</div>
</div>
</div>
);
}
这是一个示例,说明如何使用带有 class 定义的 i18next + React + Typescript https://gitlab.com/damjan89/i18next-typescript-example
目前(即 2021 年)文档建议打包 HOC withTranslation()
:
import React from 'react';
import { withTranslation } from 'react-i18next';
class MyComponent extends Component {
return <p>{this.props.t('key')}</p>
}
export default withTranslation()(MyComponent);
如果你喜欢使用命名空间然后导出:
export default withTranslation('namespace')(MyComponent);
参考:官方 docs.
这是一个如何在 React Native 的 class-based 组件 中使用 translation
的工作示例。
import { withTranslation } from 'react-i18next';
class PersonalScreen extends React.Component {
render() {
const { t } = this.props;
return (
<Text>{t('Translate this text')}</Text>
)
}
}
export default withTranslation()(PersonalScreen)