In short, he wraps the component with another component called Translate component. This Translate component would get the currentLanguage from this.context, which is passed down to every child components from the TranslationProvider, used in top class components (in his project, are the pages and layout components which hold other components without rendering a single word of text, since they could not translate themselves).

The top class components don’t know about the currentLanguage, the TranslationProvider does. TranslationProvider connects to the store (is this case, the user store) to get the currentLanguage, and passes it to all of its child components via getChildContext(), so every child component can access currentLanguage by this.context.currentLanguage.

Translate component is a function which receives a key (the component name) and the Component class reference. It get the currentLanguage and the correct translation file, then return the same Component injected “strings” into its props. “Strings” is an array with correct translated strings.

More carefully, he puts a default Strings array in every component’s props, so that if somehow the Translate component couldn’t inject the translated strings, the component would still render anyway, using the default strings.

Each component deal with translation in isolation.The component is standalone, can be reuse anywhere, optionally being wrapped by a Translate component, without crashing if the currentLanguage could not be reached.

Translated strings are centralized in a file, divided into Component sections. Edit once, use anywhere.

What’s confusing me is the default strings array in every component, does it necessary? Why don’t we just pick a default language (e.g. English) to ensure the currentLanguage always exists? He uses the TranslationProvider to help wrapping any component wants to have translation. In my opinion, I would just use the App component as the TranslationProvider, since its the highest level component in the app.

Another thing, I’m working on an isomorphic web app (isomorphic application is one whose code can run both in the server and the client), which has server-side rendering. How do I know which language to render for the first time the user request to my server? And the URL will not change when the language changes. Definitely I can not just pick one as default. The answer is: cookies.

Before thinking of using cookies on server side, I was desperate watching my website to render in English on the server and then re-render in Vietnamese on the client, as the user’s language setting is Vietnamese. There was always a flash of language-changing frames when viewing the page, such a nightmare for a web app!

On the first time a user visit the website, we have no choice but showing the default language, but then if they change the language, we must make sure that next time they visit it should render the same language they chose. So here is how I do:

This looks quite normal, but it would have some update when we get to server-side rendering problem.

The App component

In my case, App is the highest level component (defined in route file for React Router):

<Route path="/" component={App}>
// Child routes
</Route>

App will be the first component to be rendered, so it’s the most suitable to hold the currentLanguage. The App component connects to the language node in the state tree to get the currentLanguage, then passes it down to its children via child context.