Question

I'm having some issues getting i18next to initialize properly and pull out the appropriate translation strings. There are a few libraries in the mix:

  • PhoneGap 3.x
  • Backbone.js
  • Require.js
  • i18next.js
  • handlebars.js

My app.js has the following for the document.ready function:

$(document).ready(function () {
    var lang    = "",
        locale  = "en-AU";  // default

    // get the user's locale - mobile or web
    if (typeof navigator.globalization !== 'undefined') {
        // on mobile phone
        navigator.globalization.getLocaleName(
            function (loc) {locale = loc.value; },
            function () {console.log('Error getting locale\n'); }
        );
    } else {
        // in web browser
        lang = navigator.language.split("-");
        locale = lang[0];
    }
    console.log("locale: %s", locale);

    i18n.init({
        lng: locale,
        debug: true,
        fallbackLng: 'en'
    }, function () {
        // i18next is done asynchronously; this is the callback function
        $("body").i18n();
    });

Unfortunately, the code isn't even hitting the document.ready breakpoint I've set. Instead, the router.js define is calling the initialization code in the View class first:

define(function (require) {

"use strict";

var $           = require('jquery'),
    Backbone    = require('backbone'),
    Handlebars  = require('handlebars'),
    i18next     = require('i18next'),
    HomeView    = require('app/views/HomeView'),
    homeView    = new HomeView(); // <<-- this line

...Homeview.js:

define(function (require) {

"use strict";

var $               = require('jquery'),
    Handlebars      = require('handlebars'),
    Backbone        = require('backbone'),
    i18next         = require('i18next'),
    tplText         = require('text!tpl/Home.html'),
    template = Handlebars.compile(tplText);


return Backbone.View.extend({
    initialize: function () {
        this.render();
    },
    render: function () {
        this.$el.i18n(); // << causes an error
        this.$el.html(template());

        return this;
    }
  });
});

During the page load, a TypeError is thrown:

'Undefined' is not a function (evaluating 'this.$el.i18n()')

Any idea what I'm doing wrong here?


EDIT: require.config block in app.js (including shim):

require.config({

baseUrl: 'lib',
paths: {
    app: '../js',
    'i18next': 'i18next.amd-1.7.2',
    tpl: '../tpl'
},
map: {
    '*': {
        'app/models': 'app/models/memory'
    }
},
shim: {
    'handlebars': {
        exports: 'Handlebars'
    },
    'backbone': {
        deps: ['underscore', 'jquery'],
        exports: 'Backbone'
    },
    'underscore': {
        exports: '_'
    },
    'i18next': ['jquery']
}
});
Was it helpful?

Solution

I've created a demo application on using i18n with Backbone and require.js. You can download the code from the github repository.

Based on the logs you have shared I feel you are using normal i18next.js, which has issues when i18next is downloaded before jQuery. Have a look at this issue.

Instead download the AMD version specifically the jQuery version. Here is the link. Note that this version does not include jQuery, it just introduces dependency on it.

Add jQuery and remove i18next from shim configuration:

shim: {
'handlebars': {
    exports: 'Handlebars'
},
'backbone': {
    deps: ['underscore', 'jquery'],
    exports: 'Backbone'
},
'underscore': {
    exports: '_'
},
'jquery': {
    exports: '$'
}

}

OTHER TIPS

For those that come across this question in the future, I was able to get things working using Manish's example and some other tweaks. There are a few gotchas to keep in mind:

  1. Make sure you have the initialization order correct. Classes that use i18next need their initialization held off until after the i18next.init call returns.

  2. Check for malformed json in your translations.json files. i18next will sometimes tell you that there's something wrong if you're using the uncompressed version of i18next.js, but you're better off using something like http://jsonlint.com/ to verify that there aren't any problems with the json.

  3. Variable replacement is ...interesting in i18next. Use double underscore and the tr handlebars helper to do it.

Hopefully not a shameless plug -- if you need an example of how the parts fit together, my project repo is here: https://github.com/adapt-it/adapt-it-mobile. Files that are important for localization include:

  • www/app.js (require.js plumbing for i18next.js, call to i18next.init)
  • www/router.js (handlebars helpers for templated html)
  • www/tpl directories (handlebars templates, including some with variable replacements)
  • www/locales directories (localization files)
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top