django translating variable by name instead of content - django

I would like to use django i18n system for translating content of my website.
One of this purpuse would be <meta keywords="word1, word2"> tag. At the moment I am translating "word1, word2" string but if I change it the rest of translations won't work.
The best would be just setting the variable and saying the translation system "Use english version of the content of this variable".
I would like to avoid setting this in the database as this can be specified in the template or other html/python file. I'd like to avoid the additional database/cache hit.
Is there any way of displaying different language versions of variable - not the content ?
I know this can be done by including template with {% if LANGUAGE_CODE == "xx" %} conditions but maybe there is the other way ?

Use placeholder text and create a en.po file with only that one translation containing the values. Note that you will then be responsible for making the translators aware of the English content instead of it being contained in their corresponding .po file.
<meta keywords={% trans "META KEYWORDS" %} />

Related

Translating dynamic content in django

I have a text that has both static and dynamic part like this.
Custom message with %(card_status)s text inside
I am in fix as to what the best method there is to translate the text.
This is what I currently have,
{% blocktrans with obj.card_status as card_status %}Custom message with {{ card_status }} text inside{% endblocktrans %}
If I do that, the message generated is
msgid "Custom message with %(card_status)s text inside"
msgstr "This will be translated"
But the problem with this approach is that, no matter what the card_status variable is, the translated text will be same.
I tried enumerating the django.po file manually with msgid for each of the card_status's possible values.
But that is not being considered, example,
msgid "Custom message with ACTIVE text inside"
msgstr "This will be translated with ACTIVE text"
Can somebody suggest a method or a hack that can be used here. There are many similar questions in stack that I referred, but somehow I am not able to get the solution I require.
Hope someone can put an end to this question once and for all for everybody's joy.
Answering this for people who might needs this in the future.
This is more of an understanding than a solution that is created by me.
First I had this
{% blocktrans with obj.card_status as card_status %}Custom message with {{ card_status }} text inside{% endblocktrans %}
Problem: The part card_status was replaced with dynamic value, but not getting translated.
Solution: So I applied a template filter called template_trans to the calculated value 'card_status' that marks to django that this variable also needs to be translated. (will add that filter code below)
{% blocktrans with obj.card_status|template_trans as card_status %}Custom message with {{ card_status }} text inside{% endblocktrans %}
Doing a makemessages command now generates this text inside the po file like before
Custom message with %(card_status)s text inside
Now you need to manually add all the possible values the card_status can take into the same po file. Like in my case I added these values
msgid "ACTIVE"
msgstr ""
msgid "INACTIVE"
msgstr ""
msgid "LOST"
msgstr ""
Now the code for the template_trans is here, add this as a filter where you would generally have your other filters.
from django.utils.translation import ugettext
#register.filter(name='template_trans')
def template_trans(text):
try:
return ugettext(text)
except Exception, e:
return text
Thats it, django now does two translations for you, one the static part using the first msgid posted above. It then does the second one based on the actual value ACTIVE or INACTIVE etc to give you a combined output.
Note 1: Translators should see this %(variable_name)s in the message id and not {{ variable_name }}. That is archieved by using with tag along with blocktrans and template trans filter. Example shown above.
Note 2: You should have all the possible values of the %(variable_name)s populated in django.po. If not you will get the value of the variable and not the translated one.
Note 3: Ensure that the individual values that you poplated in the po file have their msgstr part filled in...
Django provides lots of tools for localizing content both in Python code (mainly via gettext and gettext_lazy, including pluralization) and in templates (via the tags trans, blocktrans and plural; even _() is available in templates).
If you find that there is untranslated text in your UI, you need to expose that text via the mechanisms above instead of manually tinkering with PO files.
So if you have some status flags ACTIVE, INACTIVE etc., then this is clearly language-specific content that needs to be exposed in some way.
One way to go about it is to imagine that the flag values are meaningless to humans – what would you do to ensure they make sense in a UI? Exactly: You would assign string labels to them, and you would display those string labels instead of any cryptic status values.
Now you only have to expose those labels via gettext and you're set.

Template Contexts not recognized from external file (Django)

So, I've been editing a website and have many JavaScript functions that utilize the Contexts that the views.py file passes to the page. Until now, these functions have been contained in the base.html file and so have been loaded onto every page directly. However, to make things cleaner, I copy and pasted all the functions to an external .js file. Now, rather than use the contexts, the functions consider them to be literal strings.
Example:
$('#title').text('{{ event.name }}');
The above line will actually set the text of the element to say "{{ event.name }}" rather than the name of the event. Any ideas on how to fix this? I really don't want to keep these functions in the base file where they can be seen by anyone who inspects the page source.
It doesn't matter if you put your javascript functions in an external file or in your base.html it would still get exposed to the user. Only a minification of the file would actually help to trick the user from seeing the actual values but with javascript all your code is public.
Why you're having this problem is because when you rendered the javascript inline (in your base.html) you had access to the template context.
This is no longer the case and the Django template engine doesn't interpolate your {{ event.name }} anymore.
The problem you're facing as well is a good one. You should never mix and match javascript with Djangos template language or any template language for that matter and the only way of fixing it is to
a) start pulling the values from the DOM ie. render a proper DOM
b) to start to fetch the values from the server, traditionally using AJAX.
And the smallest example that I can muster at the moment is below:
Your view:
def my_django_view(request):
return HttpResponse(json.dumps({'meaningoflife':42}), mimetype='application/json')
Your HTML
<input type="hidden" id="myMeaning" value="{{ meaningoflife }}" />
Your javascript
var meaning = document.querySelector('#myMeaning').value;
alert(meaning); //should alert 42.
In your view you return some form of render_to_response which takes a template argument and a context argument. What the render_to_response function does is read your template, and replace all {{ placeholders }} with the values passed via the context dictionary.
Templates are essentially a complex version of this
"""
<h1>{{ person.name }}</h1>
<p>{{ person.phone_number }}</p>
""".format(person)
The problem is the templating engine does not know files specified by a scripts src attribute is actually a Django template. To fix this don't use the script src attribute. Instead do something like this.
<!--base.html-->
<h1>Site Title</h1>
<p>Some content</p>
<script>
{% include 'jsfile.js' %}
</script>
Using the include statement should do the trick.

How to put translatable text (including English) into files in Django

I'd like to have all of my templates' actual non-html text in one (or multiple) seperate files in Django. At the moment my templates are quite jam-packed by passages like:
{% if request.session.lang == "en" %}
Some text in English
{% else %}
Some text in the default language
{% endif %}
The templates' text (main language or English) gets changed often by other people, so I would like to just have some files, which other people can edit as well (without having to edit the actual view-files).
After reading the localization section of django docs, it seems that one still has to hardcode text (English in the docs' examples) into the templates/views.
Example from django docs on generated .po files:
msgid "Welcome to my site."
msgstr ""
I'd rather have something like:
msgid APP-XY_VIEW-XY_INTRODUCTION
msgstr ""
Of course, the obvious solution seems like using something like:
ugettext('APP-XY_VIEW-XY_INTRODUCTION') # in a view
However, I'd like to make sure if there's no other solution (without creating some custom id string literals, that are hardcoded in every view/template).
Thanks very much!
/edit, Django Version 1.4.5
You don't say what version of Django you are using (you should pretty much always include this information - it will help you get the best answers). But, you should just be able to put
{% load i18n %}
at the top of your template. Then you can just call trans and handle it like you would your models, etc.
<title>{% trans "My very important title" %}</title>
The Django book 2.0 has a pretty good chapter on this topic. Might be work a read? Click here for more info.
You can create language files for the same language as your project and it will override the hardcoded strings (both template and views)
my project:
LANGUAGE_CODE = 'en-US'
In locale/en/LC_MESSAGES/django.po my translators can override my faulty/bad choice of words

How do I include raw HTML files in Symfony2/Twig templates?

I'm working on a project in Symfony2 and I have several small pieces of html that need to be included in one of my main views. According to the official Twig documentation I should be able to simply use {% include 'filename.html' %} but in Symfony unless the filename ends in ".html.twig" it throws and error saying it cannot find the file. I'd like to avoid using Twig templates for these files since they have no dynamic content and lots of double braces (they're javascript templates) and requiring the template designer to have to wrap every one of these files in {% raw %} tags seems like a really Kludgey way to do it.
I also came upon the same problem trying to find a solution to include files (mustache templates) as raw in Twig templates so Twig doesn't try to parse them.
At first I had my mustache template files named simply sometemplate.html and wrapped in {% raw %} tags. This worked for a while, but then I started using PhpStorm IDE with the Handlebars plugin (for mustache syntax). For PhpStorm to recognize the files as mustache syntax, they need to have a unique file extension (.mustache by default), so I renamed my sometemplate.html to sometemplate.mustache but I really disliked the idea that my mustache templates needed to be wrapped with Twig tags. So I ended up doing what #rdjs said in his option 3. This is the best solution imo.
Here's the working Twig extension function I made:
function twig_include_raw(Twig_Environment $env, $template) {
return $env->getLoader()->getSource($template);
}
$twig->addFunction('include_raw', new Twig_Function_Function('twig_include_raw', array('needs_environment' => true)));
With this in place you can easily include files as "raw" without Twig parsing them by doing:
{{ include_raw('sometemplate.mustache')|raw }}
I even made a Twig macro for simplifying including mustache templates to HTML head sections:
{% macro mustache_script(id, file) -%}
<script id="{{ id }}" type="text/x-mustache-template">
{{ include_raw(file)|raw }}
</script>
{%- endmacro %}
And after importing the file with the above macro to your Twig template ({% import "macros.twig" %} for example), you can easily import mustache template files in your Twig templates by simply doing {{ mustache_script('sometemplate_tpl', 'sometemplate.mustache') }} inside a HTML <head> section.
I hope this helps someone who's looking for a solution to the same problem.
A quick recap on twig file extensions (taken from the documentation):
Every template name also has two extensions that specify the format and engine for that template.
AcmeBlogBundle:Blog:index.html.twig - HTML format, Twig engine
AcmeBlogBundle:Blog:index.html.php - HTML format, PHP engine
AcmeBlogBundle:Blog:index.css.twig - CSS format, Twig engine
By default, any Symfony2 template can be written in either Twig or PHP, and the last part of the extension (e.g. .twig or .php) specifies which of these two engines should be used. The first part of the extension, (e.g. .html, .css, etc) is the final format that the template will generate.
Therefore it makes sense to me that including a file as .html would be at the least ambiguous even if it didn't throw an error.
So you have 3 choices:
If the files are purely javascript then include them as script tags in your page.
If they are mixed HTML and JS then escape the JS with {% raw %} and include the files as foo.html.twig templates. If there are lots of scripts being included like this then most likely your designers could do with a little refactoring and move the bulk of their scripts to external files (see option 1)
If you really insist you could always write a Twig extension to include raw HTML files. (EDIT: See #Haprog's answer below for more details on this option).
{{ include_html('foo/bar.html') }}
UPDATE 2015 twig has since added the source function:
{{ source('AcmeSomeBundle:Default:somefile.html.twig') }}
Kudos to #Nigel Angel in the comments below for option 4.
I came accross this post, as I had a similar question. After an hour or so searching and trying, I found out, that as from Twig Version 1.15 the "source Function" was added.
Maybe that helps someone in the future.
Follow up on Kari, if you're in an extension.. you can apply it this way.
public function getFunctions() {
return [
'include_raw' => new \Twig_Function_Method($this, 'twig_include_raw', array('needs_environment'=> true, 'is_safe'=> array('all')))
];
}
And that'd be a $this->twig_include_raw type method. You'd include within your template as:
{{ include_raw("my/file/here.html.twig") }}
No need for " | raw".

Is is possible to html encode output in AppEngine templates?

So, I'm passing an object with a "content" property that contains html.
<div>{{ myobject.content }}</div>
I want to be able to output the content so that the characters are rendered as the html characters.
The contents of "conent" might be: <p>Hello</p>
I want this to be sent to the browser as: &amplt;p&ampgt;Hello&amplt;/p>
Is there something I can put in my template to do this automatically?
Yes, {{ myobject.content | escape }} should help (assuming you mean Django templates -- there's no specific "App Engine" templating system, GAE apps often use the Django templating system); you may need to repeat the | escape part if you want two levels of escaping (as appears to be the case in some but not all of the example you supply).
This is Django's django.utils.html.escape function:
def escape(html):
"""Returns the given HTML with ampersands, quotes and carets encoded."""
return mark_safe(force_unicode(html).replace('&', '&').replace('<', '&l
t;').replace('>', '>').replace('"', '"').replace("'", '''))
Also, see here.