Translation for each component for react-i18next

4.2k views Asked by At

Im using react-i18next. Thing is that it expects the <I18nextProvider> to be wrapper on the outside of my App. I cannot wrap it inside my component itself since that will trigger errors.

Is it even possible to run multiple instances of that provider? Since i have about 12 reusable components that i want to deliver with multi-language support. How should i handle that since i want to handle the translations, if possible, in those components itself.

The thing i have right now is giving me errors that options are not set. I guess this happens due the fact that i want to translate on outer component level where the component is render inside. An intermediate wrapper component could do here though.

import React from 'react';
import { connect } from 'react-redux';
import { Form, Button, Input } from '@my/react-ui-elements';
import { authenticateUser } from '../../actions/index';
import { translate } from 'react-i18next';
import { I18nextProvider } from 'react-i18next';
import i18n from '../../i18n';

const styles = {
  wrapper: {
    padding: '30px 20px',
    background: '#fff',
    borderRadius: '3px',
    border: '1px solid #e5e5e5'
  },
  subTitle: {
    opacity: 0.3
  }
};

@connect(store => {
  return {
    config: store.config.components.Authentication,
    loading: store.authentication.loginform_loading,
    errorMessage: store.authentication.loginform_errorMessage,
    forgotpasswordEnabled: store.config.components.Authentication.forgotpassword_enabled
  };
})

@translate(['common'], { wait: false })

class LoginForm extends React.Component {

  constructor() {
    super();
    this.state = {
      username: null,
      password: null
    };
    this.handleForm = this.handleForm.bind(this);
  }

  handleForm(e) {
    e.preventDefault();
    this.props.dispatch(authenticateUser(this.state.username, this.state.password));
  }

  render() {
    const { t } = this.props;

    // Forgot password
    var forgotPassword = null;
    if(this.props.forgotpasswordEnabled) {
      forgotPassword = <Form.Field>
        <Button as='a' href={this.props.config.forgotpassword_path} secondary fluid>Forgot password</Button>
      </Form.Field>;
    }
    // Full element
    return (
      <I18nextProvider i18n={ i18n }>
        <Form style={styles.wrapper} onSubmit={this.handleForm}>
          <h3>{t('Login')}</h3>
          <p>{this.props.errorMessage}</p>
          <Form.Field>
            <Input onChange={e => this.setState({username: e.target.value})} label='Username'/>
          </Form.Field>
          <Form.Field>
            <Input onChange={e => this.setState({password: e.target.value})} type='password' label='Password'/>
          </Form.Field>
          <Form.Field>
            <Button loading={this.props.loading} disabled={this.props.loading} type='submit' primary fluid>Login</Button>
          </Form.Field>
          {forgotPassword}
        </Form>
      </I18nextProvider>
    );
  }
}

export default LoginForm;
1

There are 1 answers

5
jamuhl On BEST ANSWER

If using the i18nextProvider the most inner will set the context. Rule translate hoc has to be nested inside the provider.

Alternative: not use the i18nextProvider. You also can pass i18next instance as props to the translate hoc:

<LoginForm i18n={i18n} />

or pass it in the options:

@translate(['common'], { wait: false, i18n: i18n })

or set it once globally:

translate.setI18n(i18n);

https://react.i18next.com/components/translate-hoc.html