How to translate variables in Jinja2/Django - django

I use i18n in my Jinja2 templates and everything works fine for plain text.
But I can't find any info how to use translations with variables, which I can't avoid using. Here is an example:
{% set words = ["Hello", "world"] %}
{% for word in words %}
{{ _(word) }}
{% endfor %}
What should I do to get "Hello" and "world" in my .po file?

It turned out I needed to use Babel for jinja2:
http://jinja.pocoo.org/docs/2.10/integration/
Posting here, because someone can be in the same trouble

Related

How to do regex search and then show the regex match as an output in jinja2?

So i have this jinja2 code
{% for vul3 in vul.ports_data %}
{% if vul3.vulnerabilities.vulners and vul3.vulnerabilities.vulners | trim | length %}
<td><label class="badge badge-success">{{ vul3.vulnerabilities.vulners }}</label></td>
{% endif %}
{% endfor %}
And it shows this output,
cpe:/a:igor_sysoev:nginx:1.20.0: NGINX:CVE-2021-23017 6.8 https://vulners.com/nginx/NGINX:CVE-2021-23017 9A14990B-D52A-56B6-966C-6F35C8B8EB9D 6.8 https://vulners.com/githubexploit/9A14990B-D52A-56B6-966C-6F35C8B8EB9D *EXPLOIT* 1337DAY-ID-36300 6.8 https://vulners.com/zdt/1337DAY-ID-36300 *EXPLOIT* PACKETSTORM:162830 0.0 https://vulners.com/packetstorm/PACKETSTORM:162830 *EXPLOIT*
I want to use this regex CVE-(?:(?:18|19|20|21)[0-9]{2})-[0-9]{5} to show only the CVEs in this string. Like below
CVE-2021-23017
CVE-2021-23017
Thanks!
The regex is fine and I'd suggest adding this in your view code, or even as an accessor, perhaps:
{% for vul3 in vul.ports_data %}
{% with vulns as vul3.vulnerabilities.vulners|trim|length %}
{% for cve in vulns.regex_list %}
<td>...
Or whatever you want to call it. I don't believe there is a built-in Jinja regex method that returns the list you're looking for, so you'll either want to add a custom filter or just add it in your view/model code which I'd suggest.

Django templates - Formatting strings

I've these variables:
#Int
user.id
#Float (e.g. X.YYYY)
profile.rating
I need these formatted like so (the ` is delimiter):
`profile.rating`
I've tried numerous ways to format them, but none worked. For example, concatenating them: ""|add:profile.rating|add:"" gave me nothing (literally, nothing).
I suspect that this is because add: is numbers-first, but converting the numbers into string with either slugify or stringformat:"" gave me, again, nothing.
How do I do this?
Do note: I need to do this with filters since the result will be passed as a parameter to an include.
Update:
Basically, I'm building a sort of modular include. It include looks like this:
<section>
...
{% if custom_section %}
<section id="{{ custom_section_id }}">
{{ custom_section }}
</section>
{% endif %}
...
</section>
which means that I can't just directly include the values in a parameter, I need the markup that will go inside the nested section.
I managed to solve this issue with this piece of markup:
{% with "<a href="\"/user/" as link_start %}
{% with profile.rating|stringformat:".1f" as rating %}
{% with user.id|slugify as id %}
{% with link_start|add:id|add:"/\">" as link %}
{% with link|add:rating|add:"/5</a>" as data %}
{% include "XX" with custom_data:data|safe %}
{% endwith %} a couple of times
Key here is the |stringformat:".1f" and the user.id|slugify since without them, djangos worthless templating language defaults on the belief all values are numerical, and thus crap comes out.
Of note is the |safe as well, as without it the language escapes the value.
Do note: I need to do this with filters since the result will be
passed as a parameter to an include.
You can pass them directly to include, as it will take context correctly.
{% include user.id %}

Line breaks in django po files

How can I use line breaks in translation strings inside .po files?
Currently I added "\n" and used {{msg|linebreaks}} in my template, but the string is printed in one single line... how can I print it on multiple lines?
I assume you want HTML output. In such case, it would be better to include HTML tags in the string:
{% blocktrans %}
First line<br/>
Second line
{% endblocktrans %}
If you are looking for something else, please describe better what you are actually trying to achieve.
Update:
If the lines are independent, it might be even better to actually split them up:
{% trans "First line" %}
<br/>
{% trans "Second line" %}
bit late, but maybe helps someone, add your translation like this:
po file
msgid "_your_msgid"
msgstr "first line\nsecond line"
template
{% trans '_your_msgid' as local_var %}
{{ local_var|linebreaksbr }}
You can use
character both in django template file and your .po files
Like this .po:
msgid "Psycological
aid"
msgstr "Психологическая
помощь"
django template:
{% trans 'Psycological
aid' %}
Containing block should have white-space: pre-line; css rule

_() or {% trans %} in Django templates?

In Django templates, you can use either {{ _("Hello World") }} or {% trans "Hello World" %} to mark strings to be translated. In docs, the “official” approach seems to be the {% trans %} tag, but the _() syntax is mentioned too once.
How these approaches differ (except syntax) and why should be one preferable rather than the other?
One difference is that you obviously can't use {% trans %} with tags and filters. But does that mean that I can just use _() everywhere, like {{ _("String") }}? It works and looks much cleaner and more consistent than using {% trans "String" %} with standalone strings and _() with tags and filters.
So it seems that there's technically no difference as of Django 1.5. Template engine internally marks a variable for translation (by setting its translate attribute) in two cases:
when you do {% trans VAR %} (see TranslateNode), or
if the name of a variable starts with _( and ends with ) (see Variable.__init__).
Later, when the variable is being resolved, Django wraps it with ugettext or pgettext if it sees the translate attribute.
However, as can be seen from source code, there are some flexibility considerations in favor of {% trans %} tag:
you can do {% trans "String" noop %}, which will put the string for translation into .po files, but won't actually translate the output when rendering (no internal translate attribute on variable, no ugettext call);
you can specify message context*, like {% trans "May" context "verb" %};
you can put translated message into a variable for later use*, like {% trans "String" as
translated_string %}.
* As of Django 1.4.
Please feel free to correct me or post a better answer in case I'm missing anything.
The trans template tag calls the ugettext() function. In Django _() is an alias to ugettext().
This is covered in the django docs.

How do I DRY up common text in a Django template?

I have some static text that needs to show up at 2 locations within a template.
For example:
<div>
{% if something %}
This is a static text
{% else %}
Something else happened
{% endif %}
</div>
... more html
<span>
{% if something %}
This is a static text
{% else %}
Something else happend
{% endif %}
</span>
I can do the above by duplicating the above text at 2 different locations in my template file(as shown above).
I could also create a model which will store the text(This is DRY but cost a call to the DB for a simple task)
I'm thinking of using include template but that's probably not the best way to achieve my goal.
What's the best way to do it?
Definitely use Inclusion Tags:
http://docs.djangoproject.com/en/dev/howto/custom-template-tags/#inclusion-tags
The tag file would either be something super simple like just the text "This is a static text" or the entire block:
{% if something %}
This is a static text
{% else %}
Something else happened
{% endif %}
"something" can be passed as a variable to the template tag so you can use that entire block in a variable way.
I use the django internationalization to do that. So in my apps/template I just write the key, and in the .po files is the value of the keys.
{% load i18n %}
<div>
{% if something %}
{% trans "static" %}
{% else %}
{% trans "something else" %}
{% endif %}
</div>
And in my .po file:
msgid "static"
msgstr "This is a static text"
msgid "something else"
msgstr "Something else happened
Besides useful for multi-language, it's much easier for copy writing just in case you want to change it in the future because you can just look unto one file instead of browsing several templates.
There are several ways, but it probably depends on what the text is and how often it will be used. It's hard to recommend a specific choice without full details
Create a custom template tag (this one makes the most sense based on how you've described your problem above).
Create a base template which has the text in it at the correct location and then inherit off of it for your "2 locations"
Put the static piece of text in a settings file and pass it to the template renderer via Context (probably not the best idea, but depending on what you're doing it could be a possibility)
You could use flatblocks : http://github.com/zerok/django-flatblocks
or chunks : http://code.google.com/p/django-chunks/
Those may be overkill for your problem, since they store your snippets in the database, but they add the benefit of making it possible to edit them via the admin.
{% load chunks %}
<div>
{% if something %}
{% chunk "something" %}
{% else %}
{% chunk "something_else" %}
{% endif %}
</div>
There are lots of forks or similar projects, for example:
http://bitbucket.org/hakanw/django-better-chunks/
http://github.com/bartTC/django-generic-flatblocks
I have a file like Java properties that I use for all of my resource strings. I just serve up the one that I want. Keeping these in one place also makes translating easy.
Ex.:
welcome_msg="hello user!"
thank_you="thank you"
goodbye_msg="goodbye, " + thank_you
If the included text gets bigger, use an 'include' tag.
{% include "myapp/helptext.html" %}
GrtzG