How to handle pluralization in Hogan

453 views Asked by At

I'm using Hogan.js, which is compatible with the Mustache spec. And im having trouble implementing a solid way of doing pluralization. I would like to keep using Hogan and use http://i18next.com/ for i18n handling

doing something like this works for the simple cases

tpl:

{{#plural(count)}}
  I have {{count}} apples!
{{/plural(count)}}

data:

{
  count: 2,
  'plural(count)': function () {
    return function () {
      return _t[arguments[0].trim()][this['count']]
    }
  }
}

this requires parsing/scanning/rendering in seperate steps to be able to generate all of the required plural methods (plural(key.val) etc.) but thats fine, it only needs to be done once, at server boot.

this breaks on things like

{{#plural(key.nested)}}

that would match if the data looked like

{
  'plural(key': {
    'val)': ...
  }
}

this also requires me to manually lookup the values from the context, not a major problem but there are some cases with lambda's/partials that might be impossible to resolve

for the default translation mappings, thing are a lot less complex, and thats easy to handle

1

There are 1 answers

0
Paul Scheltema On BEST ANSWER

Ok found the way I think is best to handle this problem:

var tpl_data = fs.readFileSync('./tpl/test.hjs', 'utf8');
var scan = Hogan.scan(tpl_data);
var tree = Hogan.parse(scan);
var gen = Hogan.generate(tree, tpl_data, {asString:false});
var out = gen.render(data);

alter the tree, replacing all tag keys to i18n where the n matches your pattern /i18n .+/

I use {{#i18n {count: count, text: 'I have <%count%> apples!'} }} and the like to add the options for i18next so i match all n's starting with i18n

add the i18n to Hogan.codegen

Hogan.codegen.i18n = function (node, context) {
  context.code += 't.b(t.v(t.i18n("' + esc(node.n) + '",c,p,0)));';
}

add the i18n method to the prototype of Hogan.Template

Hogan.Template.prototype.i18n = function (key, ctx, partials, returnFound) {
  //here the ctx is an array with from right to left the render scopes
  // most right is the most inner scope, most left is the full render data
  //1. get the config from the key, 
  //2. get the values out of the scope
  //3. get the values for the translation
  //4. lookup the translation, and repleace the values in the translation
  //5. return the translated string
};

note that inside the Hogan.Template.prototype.i18n you can access all of the template's methods