Translating dynamic content in django - 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.

Related

How to ignore already translated strings from Django's .po files when running `django-admin makemessages`

My Django app uses some strings that are already translated in Django. In custom templates for password reset process I'd like to use some of the original texts, like this one prompting user to log in after completing the reset process.
Custom template contains <p>{% trans "Your password has been set. You may go ahead and log in now." %}</p> taken directly from the original form file.
After running django-admin makemessages my .po file contains this:
#: core/templates/auth/password-reset-complete.html:10
msgid "Your password has been set. You may go ahead and log in now."
msgstr ""
Translation is working, rendered page already contains the correct translated string. Is it possible to ommit this empty translation from .po file automatically? Simply removing it will only work until I run makemessages again. It's already been translated, to duplicate it in my .po file seems unnecessary.
You can try putting your string into a variable before giving it to trans, so that makemessages doesn't notice it. Something like
{% with mystr="Your password has been set. You may go ahead and log in now." %}
{% trans mystr %}
{% endwith %}
Alternatively, you could create your own custom template tag that simply calls gettext (from django.utils.translation) on its argument, and use that instead of trans.
Using #Ove idea, I used two wrapped tags trans_done and blocktrans_done:
templatetags/i18n_done.py
from django import template
from django.templatetags.i18n import (
do_block_translate,
do_translate,
)
register = template.Library()
#register.tag("translate_done")
#register.tag("trans_done")
def translate_done(parser, token):
return do_translate(parser, token)
#register.tag("blocktranslate_done")
#register.tag("blocktrans_done")
def block_translate_done(parser, token):
return do_block_translate(parser, token)
Then in my template, I simply:
{% load i18n_done %}
<p>{% trans_done "Your password has been set. You may go ahead and log in now." %}</p>
This will still be translated, but gettext will not find those strings.
Simple enough ;-)

Django - putting HTML tags inside blocks of text subject to translation

I am translating my web site from English into Russian (using Django 1.9) and have screened the doc several times, and I still can't solve the issue
I have the following snippet in my template:
{% blocktrans %}
I have <strong>{{apple_count}}</strong> apples
{% endblocktrans %}
After running makemessages, my .po file looks like this:
msgid "I have <strong>%(apple_count)d</strong> apples"
msgstr "У меня есть %(apple_count)d яблок"
The problem is that after running the compilemessages command, the phrase stays in English in Russian version of the web site (in other words, the phrase is not translated into Russian). Please note that the problem lies in <strong> tag. If I remove it from the template, all works just fine.
I've also tried to remove <strong> from the .po automatically-generated msgid so that the .po file would like this:
msgid "I have %(apple_count)d apples"
msgstr "У меня есть %(apple_count)d яблок"
...but this does not help either.
Does Django provide a way to include HTML tags in translation phrases? And if not, what is the cleanest work-around ?
Does Django provide a way to include HTML tags in translation phrases? And if not, what is the cleanest work-around ?
The way to do it is exactly as you did it. It's totally fine to occasionally have some markup inside your blocktrans blocks.
I don't know why it doesn't work with your <strong> tag.I tested this on my django playground and it perfectly worked even with the markup included. The issue must be something else.
That's what the gettext documentation says about this:
HTML markup, however, is common enough that it’s probably ok to use in
translatable strings. But please bear in mind that the GNU gettext
tools don’t verify that the translations are well-formed HTML.

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

django translating variable by name instead of content

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" %} />

Using blocktrans for translation

I am using the following blocktrans:
{% blocktrans with item|gender_text as gendertext %}
This is {{gendertext}} item
{% endblocktrans %}
In my .po file I have
msgid "This is %(gendertext)s item"
msgstr "Some translation ... %(gendertext)s"
For any language other than english, I would not like to use the gendertext variable. So I would want to have
msgstr "Some translation ..."
However, when I take off the %(gendertext)s from from msgstr, django_admin shouts (when compiling the messages):
'msgstr' is not a valid Python format string, unlike 'msgid'. Reason: The string ends in the middle of a directive.
msgfmt: found 1 fatal error
Any workarounds for this case?
Meir
If I understand your question well, Django is right to give that error beacsue, your key should be there for all languages.For example, there is no such case : in English I have a key gendertext but in Turkish I don't need that key.
One easy solution is keep that key in both languages but keep it empty if you don't want to render.
Other than your question, I strongly recommend you to use rosetta application, http://code.google.com/p/django-rosetta/ for translation processes.