Reputation: 3414
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
Reputation: 7092
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
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
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