1

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']
}
});
eb1
  • 2,897
  • 3
  • 31
  • 42
  • Can you let me know whether you are using normal i18next or i18next with amd? – Manish Mulimani Apr 13 '14 at 13:44
  • I've used several permutations. I'm currently using i18next.amd.withJQuery.min.js. But I'll try again with your link below. Thanks! – eb1 Apr 15 '14 at 14:54
  • Also have you defined shim configuration for jQuery? – Manish Mulimani Apr 15 '14 at 15:00
  • I don't have one for jQuery, but I do for i18next (I just put the block into the question above). Do I need one? All my 3rd party .js files are in the lib directory, which is defined as the baseUrl. – eb1 Apr 15 '14 at 16:03
  • I've updated my answer. Include jQuery in shim configuration and remove i18next as you are using AMD version. Also ensure you use i18next amd with jquery version i.e. i18next.amd.withJQuery.min.js – Manish Mulimani Apr 15 '14 at 16:18
  • I've updated my answer with a link to git repository which contains a i18n,backbone, require based working app code. – Manish Mulimani Apr 15 '14 at 17:33
  • Fantastic! But it seems to be getting 404 errors: Failed to load resource: net::ERR_FILE_NOT_FOUND --> file://cdnjs.cloudflare.com/ajax/libs/require.js/2.1.11/require.min.js – eb1 Apr 15 '14 at 20:09
  • Sorry I forgot that you are using Cordova, hence was using cdn repository links. I've made changes and updated git repository, you can download the files and try it. – Manish Mulimani Apr 16 '14 at 01:27
  • Got it, I think. I'm getting "Origin null is not allowed by Access-Control-Allow-Origin" errors, but only in Safari and Chrome -- I think this is a similar file:// error that shows up in Chrome for some other pieces. Firefox is working, and translating things correctly. Thanks so much! – eb1 Apr 16 '14 at 03:01

2 Answers2

2

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: '$'
}

}

Manish Mulimani
  • 17,535
  • 2
  • 41
  • 60
  • The current Github repo is a good example of using i18n with Backbone.js and require.js. Note that you will need to use Firefox to avoid Origin Null errors (see http://stackoverflow.com/questions/8456538/origin-null-is-not-allowed-by-access-control-allow-origin). Thanks again, Manish! – eb1 Apr 16 '14 at 03:04
  • Happy to know the example helped you. And thanks for sharing the link regarding Origin error. Got to learn something today :-) – Manish Mulimani Apr 16 '14 at 03:07
0

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)
eb1
  • 2,897
  • 3
  • 31
  • 42