Using react-i18next within a class component

19,312

Solution 1

Just like t is available as props in a functional component, you can access it from props in a class component after wrapping TradesTableComponent with translate HOC. All you need to do is destructure it from props in render method like

const { t } = this.props;

Relevant code

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

Solution 2

Currently (ie 2021) the docs suggest the packaged 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);

If you like to use namespaces then export:

export default withTranslation('namespace')(MyComponent);

Ref: official docs.

Solution 3

Here's a working example of how to use translation in a class-based component in React Native.

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)
Share:
19,312

Related videos on Youtube

Alexander Valtingojer
Author by

Alexander Valtingojer

Updated on June 04, 2022

Comments

  • Alexander Valtingojer
    Alexander Valtingojer almost 2 years

    I am trying to translate my application using react-i18next. I know how to use it with simple const components, but not within a class.

    I'm working with the I18nextProvider. This is my App.js file.

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

    Now using it within a const based component is quite easy. Here is an example:

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

    As you can see I just import the translate from the react-i18next and I'm almost ready to go with the t function.

    How can I achieve the same within a class component? I want to implement it in this 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);
    

    I'm quite new to React and ES6, but I was unable to find the solution online. Would really appreciate any help!

    Thanks!

  • Jean-François Beauchamp
    Jean-François Beauchamp almost 4 years
    @liquid_boy Normally, we are asked to provide the answer directly in our posts on StackOverflow. We can provide a link directing to a page with more details, but the gist of the solution should be in the post. Also, following that link I found a project with all the basic stuff to do localization, but there is no example in the component itself. The last bit is missing.
  • Fernando Tholl
    Fernando Tholl over 3 years
    I used the answer from @Mathissimo, but extracting t from this.props I didn't need to change anything in JSX, very good! - const { t } = this.props;
  • shery089
    shery089 over 2 years
    I needed this package in a class which I was using to make API related functions. From the above repo, I have found this code which helped me. import i18next from 'i18next'; i18next.t('someKey'); Thanks