When text templating can fail you

There are lots of systems out there to generate HTML pages, emails and reports in which you set up a specific template and then a pre/post processing step fills the "blanks" with data from a database or some other backing data structures. The problem with this approach is that it doesn't fail very gracefully. Because the original page is an actual valid output page, if the process to fill in the gaps misses one of the gaps, it might not be able to tell and will just output things that look like gibberish. Just like the email that I received this morning from babbel:

Remember what {Trans:LearningLang [ENG]} word for thank you is?

Apparently I'm not learning any language right now (I haven't really touched that site in a few months), so it couldn't find my current learning language translated to English. Instead of failing to send the email, because {Trans:LearningLang[ENG]} is a valid text in the title of an email, the templating engine falls back to believing that that's what the user meant to provide, and gives me a funny looking email.

What is the solution to this? Well, there are many ways templating can be made safer. First of them is to disable fallbacks and actually throw exceptions when something that looks like a template "blank" turns out not to have backend data for. The problem with this solution is that if you actually want to write text that looks like the template (very useful if you are trying to generate documentation for your engine), you now need to provide escaping mechanisms, and if the person forgets to escape their markup, they will get errors or very weird results.

Another option is to not start with plain text, but actually structured data. This provides a "type-safe" way of saying: this is text and this is a "blank". The problem with this approach is that you need special UI for building your templates and not just a text processor. So things become much more expensive to maintain (because whenever you have to also maintain a UI, any project becomes a never-ending project, as contexts where UIs are used are constantly changing and adapting to different input behavior and operating system choices).

My preferred solution is somewhere in between. I think you should be explicit on what you want to replace. At the beginning of your template, you can say something like:

{REQUIRED_REPLACE:*} or {REQUIRED_REPLACE:Trans:*}

This will make it fail if it sees a template that starts with it (or any, with the *). Then you have to still have escaping mechanisms for the documentation use case (you probably need that anyway). The problem that this still doesn't solve is the case that somebody made a typo and instead of starting their template entry with "{" they started with, let's say, "(". In the middle of everything, they didn't really realize it.

That's a trickier problem. Solution for that would require a spelling-correction-type warning system, which would look for things that look like a valid template except for one character. Or just look for common mistakes. This quickly becomes a hard problem if the templating system is very powerful and allows for a lot of different says of representing templates (like many HTML-generating template frameworks). And in the execution it will require a warnings report, which also is not straight-forward to integrate with a build process (how to ensure that people are actually looking at the report, for example).

Anyway, it's funny how simple emails can trigger long posts when I'm in an introspective mood.