ibiza ibiza - 15 days ago 4
Javascript Question

How to lazy load a js file in React (for a multilingual app)

I would like to create a multilingual app with React.

The way I see it would be to have a js file for each language, for example :

en.js:

module.exports = {
langEnglish: 'English',
langFrench: 'French',

navHome: 'Home',
navUsers: 'Users',
...
};


fr.js:

module.exports = {
langEnglish: 'Anglais',
langFrench: 'Fran├žais',

navHome: 'Accueil',
navUsers: 'Utilisateurs',
...
};


As each language file will be quite big and there could be dozens of different languages supported, I would prefer to download only the correct file to use depending on the language chosen in order to minimize loading time (and bandwidth usage).

For example I could have a variable in the app state

var App = React.createClass({
getInitialState: function () {
return {
lang: 'en'
};
},

...


and some user control to switch this variable between
fr
and
en
.

Is it possible to load only the
en.js
file on the initial load, and if the user switches the language to French then load and use the
fr.js
file instead and so on for each language?

Answer

Make use of some advanced webpack features, such as code splitting. You can use webpacks require.ensure for async loading your files.

Create a file:

i18n.js

var currentTranslation = {};

module.exports = {
    getTranslation: function() {
        return currentTranslation;
    },

    loadI18n: function(region, cb) {
        switch (region) {
            case 'en':
                require.ensure([], function(require) {
                    cb(currentTranslation = require('./en'));
                }, 'i18n-en'); // will create a chunk named 'i18n-en'
                break;
            case 'fr':
                require.ensure([], function(require) {
                    cb(currentTranslation = require('./fr'));
                }, 'i18n-fr'); // will create a chunk named 'i18n-fr'
                break;
            default:
                require.ensure([], function(require) {
                    cb(currentTranslation = require('./en'));
                }, 'i18n-en');
        }
    }
}

App.js

var i18n = require('./i18n');

and when you need the translation strings to be loaded async

you can call:

i18n.loadI18n('en', function(texts) {
    console.log(texts);
});

once webpack loads that chunk, you will be able to get the translation texts using the function

var texts = i18n.getTranslation(); // call this from anywhere and it will return english texts

if you want to switch language, just call

i18n.loadI18n('fr', function(texts) {
    console.log(texts);
});

var texts = i18n.getTranslation(); // will return french texts