ericf / express-handlebars

A Handlebars view engine for Express which doesn't suck.
BSD 3-Clause "New" or "Revised" License
2.31k stars 382 forks source link

i18n helpers #133

Open leoGalani opened 9 years ago

leoGalani commented 9 years ago

Hi,

I didn't got it right how to make custom helpers to use i18n without using handlebars direct

im getting this error when i start my application.

exphbs.registerHelper('__', function () {
       ^
TypeError: undefined is not a function

Otherwise the templates are rendering just fine, so im must be doing almost everything ok.. :)

zolzaya commented 9 years ago

Hello @leoGalani I have a same problem. Did u solve it?

iamsebastian commented 9 years ago

Why don't you create an instance?

var exphbs  = require('express-handlebars');

var hbs = exphbs.create({
    helpers: {
        foo: function () { return 'FOO!'; }
    }
});

app.engine('handlebars', hbs.engine);
gzurbach commented 8 years ago

I have been using the following solution for a while but I just discovered a bug that I'm tracking down. Maybe you guys have a better solution for this?

var express = require('express'),
    i18n = require('i18n'),
    expressHandlebars = require('express-handlebars');

module.exports = function() {

  var app = express();

  var hbs = expressHandlebars.create({
    extname: '.hbs'
  });

  app.use(function(req, res, next) {
    hbs.handlebars.registerHelper('i18n', function() {
      return i18n.__.apply(req, arguments);
    });
    next();
  });

  app.use(i18n.init);
};

In my template I can use the helper that way:

{{i18n 'common.hello' firstName}}

It works, but I am having serious concurrency issues in production (see https://github.com/mashpie/i18n-node/issues/209).

That SO thread mentions that...

This is because you are using a single instance of Handlebars and with lots of requests you are polluting one request with another. I use hbs as it creates a new instance of handlebars for each request/render for you.

The above line expressHandlebars.create() suggests that we create an instance of express-handlebars for each request. Are those instances sharing a single instance of handlebars?

A potential solution would be to use the syntax from the README:

var hbs = exphbs.create({
    // Specify helpers which are only registered on this instance.
    helpers: {
        foo: function () { return 'FOO!'; },
        bar: function () { return 'BAR!'; }
    }
});

But how to create a helper that has access to the req object since this last contains the current locale?

gzurbach commented 8 years ago

Figured it out! The solution simply consists in using the data.root.locale from the last argument of the helper.

app.use(function(req, res, next) {
  hbs.handlebars.registerHelper('i18n', function() {
    var args = Array.prototype.slice.call(arguments);
    var options = args.pop();
    return i18n.__.apply(options.data.root, args);
  });
  next();
});
travnels commented 8 years ago

using data.root.locale worked for me too. I however am only using it when this.locale is not set for optimization.

    if(!this.locale){
      var args = Array.prototype.slice.call(arguments)
      var options = args.pop()
      return i18n.__.apply(options.data.root, args)
    }
    return i18n.__.apply(this, arguments)