Cereal Killer
Cereal Killer

Reputation: 3414

Multilingual in Meteor

I'm developing a multilingual app in Meteor.js I would like to know about best way in your opinion to do that; as example here is wat I'm doing right now (pretty sure that can be done better);

First I save items in mongodb with properties neted in a language root:

{
    en: {
      name: "english name",
      content: "english content"
    },
   it: {
      name: "italian name",
      content: "italian content"
    },
   //since images are the same for both, are not nested
   images: {
       mainImage: "dataURL",
       mainThumb: "dataURL"
   }
}

Then I publish a subscription using currentLang session variable:

Meteor.publish("elementsCurrentLang", function(currentLang) {

    var projection = {
        images: 1
    };

    projection[currentLang] = 1;

    return Elements.find({}, projection);
});

I subscribe on route using Iron Router waitOn hook:

Router.route('/eng/elements', {
    waitOn: function() {
        return Meteor.subscribe("municipalitiesCurrentLang", Session.get('currentLang'));
    },
    action: function() {
        this.layout('ApplicationLayout');
        this.render('elements');
    } 
});

Now the first problem: I would like to reuse the same template for every language, but I can't simply put in the template {{name}} or {{content}} since the subscription returns the attributes nested under lang root, so it is needed to do for example {{en.name}} for english or {{it.name}} for italian; To avoid this I use a template helper that buids a new object; essentially it removes attributes from the lang root:

Template.elements.helpers({
    elements: function() {
        var elements = Elements.find();
        var currentLang = Session.get('currentLang');
        var resultList = [];

        elements.forEach(function(element, index) {
            var element = {
                name: element[currentLang].name,
                content: element[currentLang].nameUrl,
                images: element.images
            };

            resultList.push(element);
        });

        return resultList;
    }
});

And now in the template I can access attributes like wanted:

 <h1>{{name}}</h1>
 <p>{{content}}</p>

Before continuing with this approach I want to listen for suggestions, since I don't know if this will work well; when Session.currentLang will change, the subscription will be reloaded? is there a way to avoid the forEach loop in template helpers?

Upvotes: 6

Views: 4391

Answers (3)

Finally there is a package which is very complete (it also works with number formats, locales...) and is being updated frequently.

https://github.com/vazco/meteor-universe-i18n

You can also install https://atmospherejs.com/universe/i18n-blaze for using it with blade.

Just name your files with the pattern locale.i80n.json and its contents like

{
  name: "english name",
  content: "english content"
}

then translate your strings with {{__ 'name'}}.

Upvotes: 2

Charles
Charles

Reputation: 148

This module does what you're looking for

https://github.com/TAPevents/tap-i18n-db

As the developer says: "Extends the tap:i18n package to allow the translation of collections."

Upvotes: 3

roro_57
roro_57

Reputation: 600

I'm developping a multilangage web app too and I advise you to use a package, like this one : https://atmospherejs.com/tap/i18n

You can change the langage reactively. Have the same template for all your langages, as you want ! You can put it as a parameter in the route. Personnaly I use it as a Session variable and in the user profile !

If you use this package, you also can export your app, or part of it, more easily as many developpers will use the same code.

you put all your words in json files :

en.i18n.json:
{
    "hello": "hello"
}
fr.i18n.json:
{
    "hello": "bonjour"
}

and

{{_ "hello" }}

will write hello or bonjour depending of the langage set. You can set it with :

TAPi18n.setLanguage(getUserLanguage())
//getUserLanguage() <- my function to get the current langage in the user profile or 
the one used by the navigator

Upvotes: 4

Related Questions