Closed cristodcgomez closed 9 years ago
This is the way that I've got it all setup, it works pretty well for us :)
// app/app.js
module.exports = BaseApp.extend({
initialize: function() {
this.polyglot = new Polyglot();
...
},
// This is called directly on the server so we can use Polyglot
// during server rendering.
setPhrases: function(phrases) {
this.polyglot.extend(phrases);
},
// The `start` method only gets called in the client on pageload.
start: function() {
// This sets the phrases in the client-side so we can use Polyglot
// during client rendering. The phrases are accessible with
// `this.get('phrases')` because in the middleware (below) we set
// them as an app attribute. An app's attributes are serialized as
// JSON and bootstrapped to the client.
this.setPhrases(this.get('phrases'));
// If you have lots of phrases, you may as well free up some memory
// because they will no longer be accessed directly from `this.get()`.
this.unset('phrases');
...
},
...
});
// server/middleware/initI18n.js
module.exports = function() {
return function(req, res, next) {
// Fetch phrases from API or cache based on req.
// Example fake method:
fetchPhrasesBasedOnReq(req, function(err, phrases) {
if (err) next(err);
// Set the phrases so they're usable on the server during
// view rendering, etc.
req.rendrApp.setPhrases(phrases);
// Now set them as app attributes so they get serialized and
// bootstrapped onto the page as JSON so we can use them in
// the client.
req.rendrApp.set({phrases: phrases});
next(err);
});
};
};
after that I created a handlebars helper to do the translation:
t: function (phrase, options) {
return this.app.polyglot(phrase, options.hash);
}
that way in your template you can simply inline the button like this: <button>{{ t 'button_text' }}</button>
Dynamically changing the language is a bit harder cause you'll have to deliver all of the translations on page load. The way I've gotten around that is to simply refresh the page to display the new locale. That way you only need to deliver what is being used by the client at that time.
If it's a requirement to do the translations on the client-side only, you might just want to look at the structure of the phrases and maybe have it be a JSON structure that is locale + phrase => translation
Thank you. I'll try it... I didn't developed that middleware. Maybe it's the solution :)
@cristomc was that able to resolve your issue?
@saponifi3d your solution is pretty nice, may be would be nice to put it in a example/post/tutorial, it would be usefull for a lot of people I am pretty sure... :) what do you think?
@pjanuario sounds like a great idea! starts writing a blog post
@saponifi3d I didn't get it, if you started writing a blog post or you are asking me to do it! :) Either way I available to help you with that, I don't have experience with polyglot but I can help building a sample application using it.
sorry! I'm writing one about it. The italics were meant to show an action.. I guess not everybody does that! My b. Blog post is coming.
@saponifi3d awesome... I hope to read it soon! :)
I couldn't try it until now... starting to test middleware solution. BTW that blog post will be wellcome to understand better this :)
EDIT: Not working for me :disappointed: I can't start middle-ware code. Maybe wrong place for calling the initI18n?
index.js
/**
* Initialize Express middleware stack.
*/
server.configure(function (expressApp) {
...
expressApp.use(mw.initI18n);
});
Hmmm, that's def where you want to attach middleware for Rendr, and everything you have looks like it should work. Are you mounting Rendr in another express app? I've seen some issues around that (more of problems w/ the middleware, Rendr mounts fine in multiple express apps).
Also, if you're accessing the this
scope in initI18n you'll be in the wrong scope for mw
, maybe that's it?
I started using 1 of the rendr examples (middle-ware example), and I’m not accessing to this
scope. At this moment my page don't load (keep loading eternally).
I'll try to upload to my git the code later... maybe I made a mistake :sa: EDIT: I commented the mw line. I'm having this error:
500 TypeError: Cannot call method 'polyglot' of undefined
at Object.t (/media/Datos/web/market/mkplace/app/lib/handlebarsHelpers.js:11:23)
at Object.templates.home/index.Handlebars.template.main (/media/Datos/web/market/mkplace/app/templates/compiledTemplates.js:175:78)
at ret (/media/Datos/web/market/mkplace/node_modules/rendr-handlebars/node_modules/handlebars/dist/cjs/handlebars/runtime.js:137:30)
at module.exports.Backbone.View.extend.getInnerHtml (/media/Datos/web/market/mkplace/node_modules/rendr/shared/base/view.js:191:12)
at module.exports.Backbone.View.extend.getHtml (/media/Datos/web/market/mkplace/node_modules/rendr/shared/base/view.js:198:21)
at ViewEngine.getViewHtml (/media/Datos/web/market/mkplace/node_modules/rendr/server/viewEngine.js:75:15)
at ViewEngine.render (/media/Datos/web/market/mkplace/node_modules/rendr/server/viewEngine.js:22:16)
at View.render (/media/Datos/web/market/mkplace/node_modules/express/lib/view.js:93:8)
at EventEmitter.app.render (/media/Datos/web/market/mkplace/node_modules/express/lib/application.js:566:10)
at ServerResponse.res.render (/media/Datos/web/market/mkplace/node_modules/express/lib/response.js:938:7)
Maybe it's a mistake about when is using the helper as server?
I created this repo, it's easier see there the code if you need it: https://github.com/cristomc/mkplace
Thank you for helping too! you are awesome!
Oh, I wonder if you're having a problem w/ the private view scope variables in the handle bar helpers, try this._app.polyglot
instead of this.app.polyglot
. rendr-handlebars
moves all of the "private" variables to a variable with an _ prefix so it's not confused with the variables being passed in. Here's some docs on the private variables: https://github.com/rendrjs/rendr-handlebars#helpers
Thank you! that scope problem is gone :)
I'll try later to fix links to translate, but I think it's almost done
Finally I managed this to get it working. I made a variation to control languaje switch using cookies (I don't know if its the best choise but I need end this project as fast as I can so... I used it :P)
//server side, I put this in index.js but can be made as a separate file:
expressApp.use(function (req, res, next) {
if(req.cookies.lang !== 'es'){ //I check which languaje is set in the cookies, if there is no cookie, fr by default
res.cookie('lang', 'fr', { maxAge: 900000 });
req.rendrApp.setPhrases('fr');
}
else{
res.cookie('lang', 'es', { maxAge: 900000 });
req.rendrApp.setPhrases('es');
}
next();
});
app.js: same as proposed. It has just a little difference. I keep my phrases loaded in this place, so i only need check phrases text to load it.
...
, es =require('./i18n/es_ES/locale.json')
, fr =require('./i18n/fr_FR/locale.json');
...
initialize: function() {
this.templateAdapter.registerHelpers(handlebarsHelpers);
this.polyglot = new Polyglot();
},
setPhrases: function(phrases) {
if(phrases === 'es')
this.polyglot.extend(es);
else
this.polyglot.extend(fr);
},
...
//app/lib/handlebarsHelpers.js: just modified to control scope of polyglot, not fancy, it can be improved, but it works.
module.exports = function(Handlebars) {
return {
copyright: function(year) {
return new Handlebars.SafeString("©" + year);
},
t: function (phrase, options) {
try{
return this.app.polyglot.t(phrase, options.hash);
}
catch (err){
return this._app.polyglot.t(phrase, options.hash);
}
}
};
};
Thank you a lot!! now this part of the project is done, so I can finish other parts of the webservice. I'll put a tutorial too in my blog after finish this, It can be usefull for noobs with rendr & express/node like me :D
Greetings!
@cristomc happy to help! feel free to post questions here whenever :) Stoked that you're picking up Rendr. Let me know if you have any problems with the documentation site too! That's a pretty new thing and always looking for feedback on it.
The blog post sounds epic! I'm working on a few myself to help people ease into Rendr. I'll probably start doing more complex workflows for people who already have Rendr apps too.
@cristomc Drop the URL here when you the post online! ;)
of course. ATM I'm bussy due to master's projects and work, but I'll post info about rendr as fast as I can. :)
Hi! I'm having some troubles to load polyglot in client side of my service.
My goal is having 2 buttons that when I click on one of them, the service call extend() method of polyglot and load the language desired. But, I only can load a new instance of polyglot in here:
app/app.js
I also overwrote handlebarshelper. to get it working:
Notice that I have t() and tc(), because my polyglot needs to translate in layout and in the templates of each view, so i use t() in layout and tc in other case.
to get it working, I'm using JQuery to get when someone clicks on the correct button, and I'm setting this in app/view/base.js
I think that it's ugly code, but I'm in a hurry so I need help :confounded: . Thank you in advance