data = {
'person-count': 5,
}
{.section person-count|plural?}
There are {@} people here.
{.or}
There is {@} person here.
{.end}
So this would print either:
There are 5 people here.
or
There is 1 person here.
There would be a predicate map like the formatter map: e.g.
predicate_map = {
'plural?': lambda value: value > 1,
}
So I think this again provides the right separation between logic and
strings. I've been a bit religious about not putting logic in the
templates, but whether a sentence is plural is *not* something that
the application should be concerned with. This is a matter of
presentation that can be put in the template, with a little help from
these user-defined predicates.
Another place I ran into this was trying to use Protocol Buffers as
the data dictionary format. This might be an appropriate choice for
compiled languages, where JSON isn't as convenient:
http://code.google.com/apis/protocolbuffers/docs/cpptutorial.html
Basically there is no good way to express this switch in JSON Template:
switch (phone_number.type()) {
case tutorial::Person::MOBILE:
cout << " Mobile phone #: ";
break;
case tutorial::Person::HOME:
cout << " Home phone #: ";
break;
case tutorial::Person::WORK:
cout << " Work phone #: ";
break;
With predicates, you could do something like:
{.repeated section phone_number}
{.section @|home-phone?}
Home phone #: {number}
{.end}
{.section @|work-phone?}
Work phone #: {number}
{.end}
{.section @|mobile-phone?}
Mobile phone #: {number}
{.end}
{.end}
The home-phone? predicate would look at the {'type': 'mobile',
'number': 123-456-7890} record, and return whether it's a home phone
number. Although for this particular example, I realize it's better
expressed with a custom formatter:
{.repeated section phone_number}
{type|phone-type-to-string} phone #: {number}
{.end}
But I think there could be cases where you want to format something
very differently based on the contents of a whole record. Comments
appreciated.
Andy