【问题标题】:Using react-i18next within a class component在类组件中使用 react-i18next
【发布时间】:2019-07-13 07:00:20
【问题描述】:

我正在尝试使用 react-i18next 翻译我的应用程序。我知道如何将它与简单的 const 组件一起使用,但不是在一个类中。

我正在使用 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 函数。

如何在类组件中实现相同的功能?我想在这个类中实现它:

/* 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 还很陌生,但是我无法在线找到解决方案。非常感谢任何帮助!

谢谢!

【问题讨论】:

    标签: javascript reactjs i18next


    【解决方案1】:

    目前(即 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

    【讨论】:

      【解决方案2】:

      就像t 可以作为functional 组件中的道具使用一样,您可以在用translate HOC 包装TradesTableComponent 后从类组件中的props 访问它。你需要做的就是destructure它来自渲染方法中的道具,比如

      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>
          );
        }
      

      【讨论】:

        【解决方案3】:

        这是一个工作示例,说明如何在 React Native 的基于类的组件中使用 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)
        

        【讨论】:

        • 我使用了@Mathissimo 的答案,但是从this.props 中提取t 我不需要在JSX 中进行任何更改,非常好! - const { t } = this.props;
        【解决方案4】:

        这是一个如何使用 i18next + React + Typescript 和类定义https://gitlab.com/damjan89/i18next-typescript-example的示例

        【讨论】:

        • @liquid_boy 通常,我们会被要求直接在 StackOverflow 上的帖子中提供答案。我们可以提供指向包含更多详细信息的页面的链接,但解决方案的要点应该在帖子中。此外,在该链接之后,我找到了一个包含所有基本内容的项目来进行本地化,但组件本身没有示例。最后一点不见了。
        • 我在一个类中需要这个包,我用它来制作与 API 相关的函数。从上面的 repo 中,我找到了对我有帮助的代码。 import i18next from 'i18next';i18next.t('someKey');谢谢
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2019-01-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多