Internationalize your React Redux app with React Intl

Emilien Giard
BPAM Tech Blog
3 min readJun 26, 2017

--

It is common to construct a website for different countries. You have to be capable of translating the text but also you have to display your number and your date in the format used by the country. We have found a library that take care of this: React Intl.

For our project, we used a starter React-Redux kit. You can find it on :

https://github.com/davezuko/react-redux-starter-kit

The first thing you need to do is to create a “locale” that the user will pick to set his language.

You need to create in a reducer an action that I have called « CHANGE_LOCALE » which role is to set a variable in the state « locale ». In the starter kit I have put this reducer in src/store.

After creating the reducer, it must be in the rootReducer so add in « makeRootReducer » in the file src/store/reducers.js

combineReducers({  location: locationReducer,  locale: localeReducer,  …asyncReducers})

Every time we create a new reducer we will inject it in the rootReducer.

You need to have it in the root reducer because you want your app to be traduced when it loads.

Then in your parent component, which is called App in the starter kit, you need to have the locale sub-state in your component’s props.

{
routes : PropTypes.object.isRequired,
locale : PropTypes.string.isRequired,
store : PropTypes.object.isRequired
}

And:

const mapStateToProps = (state) => {
return ({
locale: state.locale.get('locale')
})
}

Then, import the data for the language you want:

import fr from 'react-intl/locale-data/fr'

After this, in the same file, add a constructor which will create a key « translations » in the state and add locale data for all the locale you will use in your application.

constructor () {  super()  this.state = {    translations: null  }  addLocaleData([...fr])}

You will have to set “translations”, you can fetch them and set them:

this.setState({
translations: response.body
})

Finally, inside the react-redux “Provider”, put the intl provider:

<IntlProvider locale={this.props.locale} messages=this.state.translations}>
<Router history={hashHistory} children={routes} />
</IntlProvider>

Now you can use “FormattedMessage”, “FormattedNumber” and “FormattedDate” in your jsx app just by importing them from “react-intl”.

If you need to translate a string or format number not inside jsx but inside your logic, you will have to use the “Injection API”. So you have to inject Intl inside your component like this:

export default injectIntl(YourComponent)

Then, define a props, that you can simply call “intl”, which has a type of “intlShape” that you import from react-intl:

intl: intlShape.isRequired

Finally, from this props you will access to functions that do the same thing as “FormattedMessage”, “FormattedNumber” and “FormattedDate”:

const { formatDate, formatNumber, formatMessage } = this.props.intl

We use enzyme to test our components, and using the “Injection Api” will cause trouble when rendering a component via “shallow” or “mount”. In this section:

https://github.com/yahoo/react-intl/wiki/Testing-with-React-Intl

You have some helpers for Jest or Enzyme that will fix the rendering of your components, and let you test them.

If your language selector is accessible in all your page and that you nested Components, you will have to “injectIntl” in your reducer if you want it to be traduced otherwise only the parent component will be update.

--

--