Using blocktrans for translation - django

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.

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.

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

Weird behavior of Django translation of one word in plural and singular form

In our code, we have the word "Photo" marked for translation in singular. At a different position in the code, we have this word in pluralized translation "Photo" / "Photos", liek so:
1 {% trans 'Photo' %}
2 {% trans 'Photos' %}
and
{{ x }} {% blocktrans count counter=x %}Photo{% plural %}Photos{% endblocktrans %}
Possibly, we must use our counter variable x inside the translation strings. However, I couldn't find anything about such requirement in the docs. Anyway, with our code, all we get in our PO files is:
msgid "Photos"
msgstr ""
msgid "Photo"
msgid_plural "Photos"
msgstr[0] ""
msgstr[1] ""
There is no msgid for "Photo", resulting in "Photo" not being translated at all, since the actual translation string does not exist - except when used in *n*gettext, but not in {% trans 'Photo' %}.
Am I doing something wrong here? Is it a Django bug?
It's not a bug in Django -- you are trying to translate the term "Photo" two different ways, in two different places. Once as a plain (number-agnostic) term, and once as a number-aware term. There is no way to represent that in a PO file, which can only have one entry with msgid "Photo".
(Note that "Photos" is handled differently in your case, since as far as gettext is concerned, it is only translated once, as a plain term.)
Plural forms can be very different across languages, and you shouldn't just be trying to localize the single noun "Photo" in this case. Instead, you should be localizing the term "x Photo(s)" for the singular and plural case in each language.
(In English, that would be "1 Photo" and "{x} Photos", but in other languages, you could have more or less than two, and the number itself may not even go before the word for "photos", which is why you have to localize the whole term)
In your template, then, you should have:
{% blocktrans count counter=x %}{{ count }} Photo{% plural %}{{ count }} Photos{% endblocktrans %}
Then your PO file should contain lines like this:
msgid "%(count)s Photo"
msgid_plural "%(count)s Photos"
msgstr[0] ""
msgstr[1] ""
And you can localize msgstr[0] (singular case) and msgstr[1] (plural case) for each language. Some languages will require more than just [0] and [1], but gettext should take care of that for you when it generates the PO file for that language.

Handling percent-sign (%) in Django blocktrans tags

I'm currently localizing my Django app. All other translations work fine except percent-sign inside blocktrans tags.
In my template I have {% blocktrans %}Original % blocktrans{endblocktrans %}.
django-admin makemessages produces this in django.po:
#: templates/index.html:78
#, python-format
msgid "Original %% blocktrans"
msgstr ""
I update that to msgstr "Translated %% blocktrans", run django-admin compilemessages, restart dev server and refresh the page, but I still see Original % blocktrans in the output. Other translations are shown properly.
For reference, {% trans "Original % trans" %} also works ok. After makemessages and translation I have:
#: templates/index.html:72
msgid "Original % trans"
msgstr "Translated % trans"
This works as expected - translated version is shown.
I must use blocktrans because I also need to embed variables to the strings. I'm using Django 1.2.5.
How can I make blocktrans work with percent-signs?
Check out this ticket - it's not a solution, but it sheds light on what's going on
Couldn't find a real solution to the problem, so I used a workaround: create a constant PERCENT_SIGN = u'%' and use that as {{ PERCENT_SIGN }} inside blocktrans-blocks.
Another ticket has been opened for this particular issue, with a patch that fixes it. Hopefully it will be fixed for Django 1.4.
https://code.djangoproject.com/ticket/16721