0

I am using react-intl package for translation purpose. There is a functionality for user to choose between Spanish and English language. By default, Spanish language is used. If user selects for English, all the text should be translated to English and if Spanish then Spanish. I have created an action and also reducer which stores the locale and its message. The component accepts locale and message as a prop. I could pass the locale and message dynamically too. By dynamically, i mean when user selects for English language, gets locale as 'en' and its message accordingly.

But i could not render the message/text dynamically. I get following error

Cannot format message: "Nav__registration_text", using message id as fallback.

Here is my code

export const SPANISH_STATE = {
  lang: 'es',
  messages: {
      'nav.registration.text': 'Registrate',
      'nav.login.text': 'Incesar',
  }
};

 export const ENGLISH_STATE = {
  lang: 'en',
  messages: {
      'nav.registration.text': 'Registration',
      'nav.login.text': 'Login',
  }
};

import { connect } from 'react-redux';
import { IntlProvider } from 'react-intl';

function mapStateToProps(state) {
  const { lang, messages } = state.locale;
  return { locale: lang, key: lang, messages };
}
export default connect(mapStateToProps)(IntlProvider);

import { Provider } from 'react-redux';
import { addLocaleData } from 'react-intl';
import en from 'react-intl/locale-data/en';
import es from 'react-intl/locale-data/es';
import App from './components/app';
import reducers from './reducers';

const createStoreWithMiddleware = applyMiddleware()(createStore);

addLocaleData(en);
addLocaleData(es);

ReactDOM.render(
  <Provider store={createStoreWithMiddleware(reducers)}>
    <ConnectedIntlProvider>
      <App />
    </ConnectedIntlProvider>
  </Provider>
  , document.querySelector('.app'));

action.js

export function selectedLocale(locale) {
  console.log('locale', locale);
  return {
    type: 'LOCALE_SELECTED',
    locale
  };
}

reducer

import { SPANISH_STATE } from '../../message/es';
import { ENGLISH_STATE } from '../../message/en';

const initialState = {
  lang: SPANISH_STATE.lang,
  messages: SPANISH_STATE.messages
};
export const localeReducer = (state = initialState, action) => {
  switch (action.type) {
    case 'LOCALE_SELECTED':
    if (action.locale === 'es') {
      return { ...initialState, lang: SPANISH_STATE.lang, messages: SPANISH_STATE.messages };
    } else if (action.locale === 'en') {
      return { ...initialState, lang: ENGLISH_STATE.lang, messages: ENGLISH_STATE.messages };
    } break;
    default:
      return state;
  }
};

Nav.js

import { intlShape, injectIntl, defineMessages } from 'react-intl';

const Nav = (props) => (
  <Router>
    <div>
      <nav className="navbar navbar-default">
        <div className="container-fluid">
          <div className="collapse navbar-collapse">
            <ul className="nav navbar-nav navbar-right nav-social-icon">
              <li className="dropdown">
              <a
                href=""
                className="dropdown-toggle"
                data-toggle="dropdown"
                role="button"
                aria-haspopup="true"
                aria-expanded="false"
              >
                ES
                <span className="caret" />
              </a>
              <ul className="dropdown-menu">
                <li onClick={() => props.selectedLocale('en-Us')}>
                  en-US
                </li>
                <li onClick={() => props.selectedLocale('es')}>
                  es
                </li>
              </ul>
              </li>
              <li className="btn-group">
                <button
                  className="btn btn-default"
                  onClick={props.showModal}
                >
                  <Link to={{ pathname: '/signup' }}>
                   <FormattedMessage
                      id='Nav__registration_text'
                      description='This is a registration text'
                    />
                  </Link> // By default, Spanish text is shown Registrate but if user selects English, Registration should be shown
                </button>
                <button
                  onClick={props.showModal}
                  className="btn btn-default"
                >
                  <Link to={{ pathname: '/login' }}>Iniciar sesión</Link>
                </button>
              </li>
            </ul>
          </div>
        </div>
      </nav>
    </div>
  </Router>
  );

Nav.propTypes = {
    intl: intlShape.isRequired,
};
export default injectIntl(Nav);
milan
  • 2,409
  • 2
  • 34
  • 71
  • Possible duplicate of [React-Intl How to use FormattedMessage in input placeholder](https://stackoverflow.com/questions/39630620/react-intl-how-to-use-formattedmessage-in-input-placeholder) – rofrol Oct 18 '17 at 10:09

1 Answers1

0

I found the solution. Everything is fine. Wherever i want the translated message, i would do

{ intl.formatMessage({ id: 'key of that message/text' }) }

For example in case of registrate in my Nav i would do

<Link to={{ pathname: '/signup' }}>
   {props.intl.formatMessage({ id: 'nav.registration.text' }) }
</Link>

similarly for login 

<Link to={{ pathname: '/login' }}>
    {props.intl.formatMessage({ id: 'nav.login.text' }) }
 </Link>

. I hope this will help others.

milan
  • 2,409
  • 2
  • 34
  • 71