serving i18n js using babel, django, & jinja2 - python

Using django, with jinja2 for rendering & babel for message extraction
I have some js files that need to be internationalized. I haven't been able to figure out a syntax for extracting messages from them which would also let jinja2 render them. Either jinja2 has to learn to read an extractable syntax, or I have to extract from something jinja2 can render. (Or, do this another way entirely)
Extracting
If I mark messages in the js with
gettext('message')
It extracts just fine.
Rendering
But jinja2 won't replace gettext calls in js (I'm rendering the js templates with jinja2 before returning them) - it needs something like
{% trans %}message{% endtrans %}
But, that syntax can't be used to extract messages.
Babel is using the function extract_javascript from babel.messages to extract messages, which doesn't look equipeed to handle this type of tag.

Well, it looks like I can just do:
{{gettext("message")}}
(without defining gettext)
in the JS and babel will extract & jinja2 will replace it ok.
Watch out for quotes, though. You can't do:
'{{gettext("message")}}'
because extract_javascript will not read it. But, you can just put the quotes inside, as long as you render them safely:
{{gettext("'message'")|safe}}
So have your translators make sure to leave quotations wherever they find them in the original.

Related

Extract translations from tornado template

I'm trying to use python-babel to extract translations from tornado templates.
I have tried some solutions, and none of them is perfect.
solution one
Use python as extractor:
# babel.cfg
[python: **/server/templates/**.html]
It works most of time, but won't work if there are some translations inside script blocks:
<script> var a = {{ _("won't be extracted") }} </script>
solution two
Just let tornado use jinja2 template engine, it works but not pretty.
solution three
Use tornado-babel, it is just an outdated library without python3 support.
Any suggestion?
Finally, I just use jinja2 template engine. Highly recommend tornado's team to use jinja2 template engine! Do not waste time any more.

Using Django's urlize with CommonMark

I'd like to use Django's urlize function together with django-markwhat's CommonMark filter.
I'm imagining something like this:
{{ "http://example.com"|urlize|commonmark }}
Which outputs <p>http://example.com</p>. The issue here is that URLs already marked up in commonmark, like <http://example.com>, will get rendered with angled brackets around them.
If I apply urlize after commonmark, like this:
{{ "http://example.com"|commonmark|urlize }}
The urlize function doesn't detect the url in <p>http://example.com</p> (and it's mentioned in the urlize docs that it won't work as expected for html input).
I haven't come up with a solution yet, so let me know if you have any ideas.
For completeness, the easy answer is to switch to a Markdown parser which provides the behavior you want out of the box. Multiple extensions exist which give Python-Markdown the desired behavior.
However, if you want this behavior with CommonMark, which does not support this behavior itself, then you will need to create a custom urlize filter which operates on HTML. Fortunately, The Bleach library provides a linkify function which will handle that correctly.
Of course, you then need to create a template filter which wraps that:
from django import template
import bleach
from html5lib.tokenizer import HTMLTokenizer
register = template.Library()
#register.filter(is_safe=True)
def linkify(value):
return bleach.linkify(value, skip_pre=True, parse_email=True, tokenizer=HTMLTokenizer)
Note that I'm assuming you do want to parse email addresses as well as URLS, you do not want to have URLs in code blocks parsed, and you do not want CommonMark's output sanitized. Feel free to review Bleach's docs and adjust accordingly.
To use your custom filter, save the above code to a file named linkify.py within a templatetags directory in your app (see the Django docs for a full explanation). Then within a template, do the following:
{% load linkify %}
{{ "http://example.com"|commonmark|linkify }}

Jinja2 Import Static HTML in Pyramid

My application contains Angular code. I want Jinja2 templating within the layout, but need to be able to use Angular expressions within the page. I'd like to do that by importing a static HTML file into the main Jinja2 template that is not parsed.
How can I import an HTML template file without parsing it? A Jinja2 extension? If so, how?
When you say "import", do you mean copying it in by hand, or do you mean you have some HTML in another file that you'd like injected (unparsed) somewhere within the template?
If it's the latter you're after -- including an HTML file without parsing -- you could write an extension, sure, but it's far simpler to just put the file's contents into a context variable (named, say, rawHtml) and output it like so:
{{ rawHtml }}
On the other hand, if you're writing the HTML inside the template itself and you want it rendered without interpretation, you can accomplish that too by using the raw construct:
{% raw %}
He had a great moustache, like this :-{
{% endraw %}

Mako's analog of Django's "spaceless" tag?

Is there a mechanism in Mako templates that would allow me to remove extra spaces from the template output, similar to Django's {% spaceless %} tag?
There are some clues here, but basically it doesn't look like it's supported under Mako directly.
I do want to point out, however that Jinja2 does support whitespace removal via the {%- and -%} opening and closing tags. It is very easy to use under Pyramid via:
pip install pyramid_jinja2
config.include('pyramid_jinja2')
From that point forward you can just use the .jinja2 file extension and build your templates.
Anyway, sorry I couldn't give you better news!

Rendering JSON objects using a Django template after an Ajax call

I've been trying to understand what's the optimal way to do Ajax in Django. By reading stuff here and there I gathered that the common process is:
formulate your Ajax call using some JavaScript library (e.g., jQuery), set up a URL pattern in Django that catches the call and passes it to a view function
in the Python view function retrieve the objects you are interested in and send them back to the client in JSON format or similar (by using the built in serializer module, or simplejson)
define a callback function in JavaScript that receives the JSON data and parses them, so to create whatever HTML is needed to be displayed. Finally, the JavaScript script puts the HTML wherever it should stay.
Now, what I still don't get is how are Django templates related to all of this? Apparently, we're not making use of the power of templates at all.
Ideally, I thought it'd be nice to pass back a JSON object and a template name, so that the data could be iterated over and an HTML block is created. But maybe I'm totally wrong here...
The only resource I found that goes in this direction is this snippet (769) but I haven't tried it yet.
Obviously, what's going to happen in this case is that all the resulting HTML is created on the server side, then passed to the client. The JavaScript-callback function only has to display it in the right place.
Does this cause performance problems? If not, even without using the snippet above, why not formatting the HTML directly in the backend using Python instead of the front-end?
Many thanks!
UPDATE: please use snippet 942 because it is an enhanced version of the one above! I found that the inheritance support works much better this way..
Hey thanks vikingosegundo!
I like using decorators too :-).
But in the meanwhile I've been following the approach suggested by the snippet I was mentioning above. Only thing, use instead the snippet n. 942 cause it's an improved version of the original one. Here's how it works:
Imagine you have a template (e.g., 'subtemplate.html') of whatever size that contains a useful block you can reuse:
........
<div id="results">
{% block results %}
{% for el in items %}
<li>{{el|capfirst}}</li>
{% endfor %}
{% endblock %}
</div><br />
........
By importing in your view file the snippet above you can easily reference to any block in your templates. A cool feature is that the inheritance relations among templates are taken into consideration, so if you reference to a block that includes another block and so on, everything should work just fine. So, the ajax-view looks like this:
from django.template import loader
# downloaded from djangosnippets.com[942]
from my_project.snippets.template import render_block_to_string
def ajax_view(request):
# some random context
context = Context({'items': range(100)})
# passing the template_name + block_name + context
return_str = render_block_to_string('standard/subtemplate.html', 'results', context)
return HttpResponse(return_str)
Here is how I use the same template for traditional rendering and Ajax-response rendering.
Template:
<div id="sortable">
{% include "admin/app/model/subtemplate.html" %}
</div>
Included template (aka: subtemplate):
<div id="results_listing">
{% if results %}
{% for c in results %}
.....
{% endfor %}
{% else %}
The Ajax-view:
#login_required
#render_to('admin/app/model/subtemplate.html')#annoying-decorator
def ajax_view(request):
.....
return {
"results":Model.objects.all(),
}
Of course you can use render_to_response. But I like those annoying decorators :D
There's no reason you can't return a rendered bit of HTML using Ajax, and insert that into the existing page at the point you want. Obviously you can use Django's templates to render this HTML, if you want.
When you are doing Ajax I don't think you have any use for templates.
Template is there so that you can generate dynamic HTML on the server side easily and hence it provides few programming hooks inside HTML.
In case of Ajax you are passing JSON data and you can format it as you want in Python.
and HTML/document elements will be generated on client side using the JSON by some JavaScript library e.g. jQuery on client side.
Maybe if you have a very specific case of replacing some inner HTML from server side HTML then maybe you can use templates but in that case why you would need JSON?
You can just query the HTML page via Ajax and change inner or outer or whatever HTML.
Templates are for the purpose of presentation. Responding with data in format X (JSON, JSONP, XML, YAML, *ml, etc.) is not presentation, so you don't need templates. Just serialize your data into format X and return it in an HttpResponse.
While templates are indeed just for presentation purposes, it shouldn't matter if you are doing it on the serverside or client side. It all comes down to separating the control logic that is performing an action, from the view logic that is just responsible for creating the markup. If your javascript control logic is having to handle how you are rendering or displaying the HTML, then you might be doing it wrong, but if you isolate that rendering logic to another object or function, and just passing it the data necessary for the render, then you should be fine; it mirrors how we separate our controllers, models and views on the server side.
Take a look at the github project: http://github.com/comolongo/Yz-Javascript-Django-Template-Compiler
It compiles django templates into optimized javascript functions that will generate your presentation html with data that you pass it. The compiled functions are in pure javascript, so there are no dependencies on other libraries. Since the templates are compiled instead of being parsed at runtime, the strings and variables are all already placed into javascript strings that just need to be concatenated, so you get a huge speed increase compared to techniques that require you to do dom manipulation or script parsing to get the final presentation. Right now only the basic tags and filters are there, but should be enough for most things, and more tags will be added as people start making requests for them or start contributing to the project.
You can use jquery.load() or similar, generating the HTML on the server and loading it into the DOM with JavaScript. I think someone has called this AJAH.
Unfortunately, Django templates are designed to be executed server side only. There is at least one project to render Django templates using Javascript, but I haven't used it and so I don't know how fast, well supported or up to date it is. Other than this, you have to either use the Django templates on the server or generate dynamic elements on the client without using templates.

Categories