defunkt/mustache — pull request #150 by ernie (2013-05-20 02:44:53+00:00)
Title: Support i18n in templates.

* To HTML-escape an i18n string: {{% some.key.name }}
* To return an i18n string unmodified: {{$ some.key.name }}

i18n keys are loaded from the "mustache" namespace by default. This is
because they support etags and utags, which are not the standard means
of i18n interpolation.

Options relating to translation:

* i18n_namespace - Sets the namespace containing a Mustache's i18n keys
* locale - Override translation locale during render (I18n.locale by
default)
* translate_only - Allow for a two-pass rendering setup, by only
expanding partials and expanding i18n keys to their translation. In
this way, translation may be done server-side but final rendering may
be done client-side, via Mustache.js or another implementation that
does not (yet?) support i18n.

Some caveats:

* Use of tags other than `{{}}` and `{{{}}}` inside an i18n string has
unspecified behavior. It certainly isn't *intended* to work, so any
success had is purely by accident.
* Use of `translate_only` option means you will blow the stack if you use
recursive partials, for obvious reasons.

Rationale:

While it's possible to implement I18n by handling translations in each
view class, it's less than optimal to do so. If you want to support true
i18n interpolation, then you're forced to provide interpolation
variables from within the view class, and the view class may not have
access to all the information required to supply those variables.

An alternative is to use lambda return values, which of course could
perform the translation as a filter, but this is somewhat more
laborious, since the responsibility is now on the user to create a
mapping between the attributes of the view and those inside the locale
file.

Regarding the implementation itself:

I chose `%` as the sigil both because its appearance brings to mind both
the current `%{}` interpolation syntax and the notion of key/value pairs
in general (to this former Perl guy). `$` was chosen for the unescaped
version for proximity to `%`.

The `translate_only` option is, perhaps, the most questionable feature
here. Its presence stems from a real-world use case in an app I'm
working on, but I realize I may well be the edge case here and would be
happy to remove this functionality if is proves too odd. It certainly
created a few wrinkles in the implementation that could otherwise be
avoided.

One thing I did take the opportunity to do, while I was in here, was
improve the handling of lambda return values to a section tag. While the
LoD violation here is a bit offputting, and could certainly be
refactored out, I find the notion of setting the otag and ctag on a
`tokenizer` for the template to be more readable than defining a
singleton method which then must duplicate the logic in the Template
class's tokens method with modifications.