Language middleware allows us to create a multi-lingual React application. Explaining each step of how it works is beyond the scope of this book. However, we will try to give a brief walk-through of how it is configured. The working code for the language middleware is in the GitHub repository inside CH06:
- We used the react-intl (https://github.com/yahoo/react-intl) library for internationalization. It can be added to the application in the same way as other—yarn add react-intl.
- The CH06 repository is configured with two locales, Norwegian and English. If you check the CH06/app/app.js file, you will see the LanguageProvider container. We are providing the container as the parent component of the Router so that we can change locale easily:
const render = messages => {
ReactDOM.render(
<Provider store={store}>
<LanguageProvider messages={messages}>
<ConnectedRouter history={history}>
<App />
</ConnectedRouter>
</LanguageProvider>
</Provider>,
MOUNT_NODE,
);
};
- There are also browsers without international support. To support those browsers, we need to polyfill (learn more about polyfills at https://javascript.info/polyfills):
// Chunked polyfill for browsers without Intl support
if (!window.Intl) {
new Promise(resolve => {
resolve(import('intl'));
})
.then(() =>
Promise.all([
import('intl/locale-data/jsonp/en.js'),
import('intl/locale-data/jsonp/nb-NO.js'),
]),
) // eslint-disable-line prettier/prettier
.then(() => render(translationMessages))
.catch(err => {
throw err;
});
} else {
render(translationMessages);
}
- To inject two types of locale, we have created the i18n.js file, in which we provide a path to JSON files containing translations. Check the CH06/app/i18n.js file.
- The next step is to make every string translatable. To do so, react-intl provides two handy functions—IntlProvider and FormattedMessage. To understand the concept, here is a code snippet that is easy to understand:
import React, {Component} from 'react'; import ReactDOM from 'react-dom'; import {IntlProvider, FormattedMessage} from 'react-intl'; class App extends Component { constructor(props) { super(props); this.state = { name : 'Yoshmi', unreadCount: 9000, }; } render() { const {name, unreadCount} = this.state; return ( <p> <FormattedMessage id="welcome" defaultMessage={`Hello {name}, you have {unreadCount, number} {unreadCount, plural, one {message} other {messages} }`} values={{name: <b>{name}</b>, unreadCount}} /> </p> ); } } ReactDOM.render( <IntlProvider locale="en"> <App /> </IntlProvider>, document.getElementById('container') );
- We have used similar methods to translate each of the string and provided a locale toggle component in the footer.
As the part of the assignment, please have a look at how we have separated the translatable string into separate files in each of the containers. The <Login />, <NotFoundPage />, <Register />, and <User /> containers contain the intl file, messages.js. These files are included inside the component and use FormattedMessage from react-intl to make a string translatable. Have a play around to get a better understanding of how it works.