Week 1: Disappearing Text
We had a case where we wanted to replace some static text in a template with
some text that changed depending on who was logged in. Textbook webdev 101
stuff. We added a property on the relevant model to return the correct
phrase, we made sure that the model was accessible from something in the context, replaced the text in the template with a
reference to this in some {{
curly
brackets }}
… and we came up with nothing. Or it showed
up in some cases but not in other cases where we applied the
|title
filter.
There's no indication of why that reference is coming up blank, as django silently replaces unrecognized references with empty strings (a design decision I vehiminently disagree with, although there's some relief available).
After spinning our wheels for a bit, we realized that the places it wasn't
working were inside {% blocktrans %}
blocks. And while
blocktrans allows simple placeholders, to
translate a template expression — say, accessing object attributes or
using template filters — you need to bind the expression to a local
variable for use within the translation block.
Using the blocktrans with
form as described in the documentation
ended up working just fine, but our localization expert told us to use this
approach with care. Replacing a single word in a sentence may have other
effects on the sentence structure, e.g. gendered nouns may require different
articles, and while blocktrans has a stanza for dealing with pluralization,
it doesn't have any parameters for gender.
Now we know how to use variables within blocktrans
, but how might we
have come to realize our error earlier? Does the aforementioned trick with
raising an exception from TEMPLATE_STRING_IF_INVALID
work inside blocktrans? Not exactly.
Up through Django 1.5, blocktrans was entirely unaware of TEMPLATE_STRING_IF_INVALID
,
so regardless of what you set your IF_INVALID string to, you wouldn't see it
show up in your rendered template. This is somewhat fixed for Django 1.6 (thank you nessita, matíasb, and ramiro), but it's not treated as a
format string. So it'll now show up inside blocktrans blocks, but if you put
a %s
in there hoping to see what the invalid input was, you'll
be disappointed and find a literal %s
in the output. And since
it's never used as a format string, that hack of raising TemplateSyntaxError
when it's formatted never gets triggered.
Let's call that ticket #21417.
That's just one of the things I learned about Django this week. More stories coming soon!