March 17, 2015

Recently, I’ve been charged with the internationalization of an app using react-intl. The app was already using react-router so integrating the two took a bit of work. Application.jsx was where the two libraries collided. It looked something like this:

Update Mar 30/2015: The code below has changed to address an issue I was having with the i18n not being passed down properly to nested components.

//Application.jsx

import React from 'react';
import ReactIntl from 'reactIntl';
import Router from 'react-router';
import LocaleStore from 'LocaleStore';

...

var DefaultRoute  = Router.DefaultRoute;
var Route         = Router.Route;
var RouteHandler  = Router.RouteHandler;
var currentLocale = LocaleStore.getLocaleTemplate();

var App = React.createClass({
  //Make sure to include the ReactIntl.IntlMixin here so
  //that the i18n gets passed into it from the RouteHandler
  mixins: [ReactIntl.IntlMixin, Router.State, Router.Navigation],

  componentDidMount() {
    //listen for changes to the locale
    LocaleStore.addChangeListener(this.onLocaleChange)
  },

  componentWillUnmount() {
    LocaleStore.removeChangeListener(this.onLocaleChange);
  },

  onLocaleChange(){
    currentLocale = LocaleStore.getCurrentLocale();

    //now re-render the app when the i18n data gets changed
    renderApp();
  },

  render() {
    return (
      <div className="global-wrapper">
        <RouteHandler />
      </div>
    )
  }
});

var routes = (
  <Route handler={App} name="app" path="/">
    <DefaultRoute name="foo" handler={Foo} />
    //some more routes
  </Route>
);

var CurrentHandler = null;

//this method re-renders the app
function renderApp() {
  if (CurrentHandler) {
    //this is where the i18n data gets passed in
    React.render(<CurrentHandler {...currentLocale} />, document.body);
  }
};

//The initial rendering of the app happens here.
Router.run(routes, function(Handler) {
  CurrentHandler = Handler;
  renderApp();
});

For an idea of what LocaleStore.getLocaleTemplate() returns, check out my other post about empty templates. When the LocaleStore gets updated via some action, it triggers the re-rendering of the app via the onLocaleChange() callback. LocaleStore.getCurrentLocale() returns the currently active locale. Remember to include the ReactIntl.IntlMixin mixin in whichever component you’d like to pass i18n to.

blog comments powered by Disqus