Backbone.js and i18n


backbonei18n
A few weeks ago I had to support i18n in a backbone.js project I’m developing. Many doubts quickly appeared, when to load the i18n’ed content? how? where to define it? in which format? …

I started looking into JavaScript i18n libraries/frameworks, and decided to take a look at three: i18next, jed and jsperanto.
Jed looks really good and is truly the closest thing you can get to gettext in JavaScript.

But this time I needed something simpler which could allow me to quickly delegate translations to someone without explaining all these concepts about pluralization and interpolation since the i18n that needed to be done was really simple and small.

From my perspective jsperanto is like i18next on steroids. (edit: not that jsperanto supported more features, but it felt more complex due to the lack of documentation in comparison to i18next)

I ended up using i18next, it was clean and simple solution for a simple problem with basic i18n necessities.

Initialization

Since i18next features async initialization, it is the first thing initialized and then the main backbone.js router is initialized in its callback. Something like this:

$.i18n.init({
    lng: "en-US",
    ...
}, function(t) {
    app = new Router();
    Backbone.history.start();
});

Since the main router is initialized in i18next initialization callback, I will have i18next initialized inside the app scope allowing me to call the i18n main method.

Translation

With initialization done, the only thing left was content translation.
Which in i18next is accomplished by inner html replacement in DOM elements that contain the specified i18next attribute.

I didn’t want to blind translate everything. Instead I decided to translate each backbone.js view in its rendering final stage.
Something like this:

window.ProfileView = Backbone.View.extend({
    ...
    render: function() {
        $(this.el).html(this.template(this.model.toJSON()));

        $('#profile_container', this.el).html(new ProfileInfoView({
            model: this.model
        }).render().el);

        $('.content_sub_menu', this.el).i18n();

        return this;
    }
});
Advertisements