Django uggetext as __ instead of _ breaks makemessages - django

I just came across a weird bug (?) where I initially had
from django.utils.translation import ugettext as _
Which I changed for
from django.utils.translation import ugettext as __
But, surprisingly, running ./manage.py makemessages --all after doing that breaks all translations, they basically get all commented in my .po files, as if they weren't recognized as being translations anymore.
Going back to _ and running makemessages fixes it. I don't quite follow why the name of the variable matters, and I wonder how I should name my ugettext and ugettext_lazy when I need both, for consistency.
Django 1.8, with python 2.7.14

That's because of the internals of the gettext utility and more specifically of the xgettext command.
In short, in order to mark strings as translatable you must wrap them in specific keywords (i.e translate("hello world"), translate here is the keyword). The xgettext program works for many programming languages. Each language has its own predefined keywords (press Ctrl + f and search for --keyword).
In Python, these keywords are (note the _ at the end):
For Python: gettext, ugettext, dgettext:2, ngettext:1,2, ungettext:1,2, dngettext:2,3, _
xgettext command has several options which alter it's behavior. One of these, is --keyword option. When you invoke the xgettext command with the --keyword option, then all strings in a python file will be considered translatable if they are wrapped in one of the predefined keywords or the --keyword option(s) you gave. If, for example you run xgettext --keyword=jimmy_hendrix then all strings like jimmy_hendrix("hello world") will be included in your .po file.
But, you will never run this command, in Django, explicitly. You use the makemessages command. Looking at the source of makemessages command, you can see that Django provides additional --keywords for marking strings for translation. In fact, these keywords are the same as Django's additional functions for translation.
After all these, I think it's clear now that aliasing __ or ___ will not work since it's not in the list of Django's xgettext command invocation, neither in the predefined keywords of xgettext command.
You may look at an outdated, but still valid answer.
Also, an example of xgettext on MDN, using PHP.

Related

Flask Babel: adding pycountry external locale

I am trying to add an external locale directory from the pycountry package.
Before initializing Flask Babel, I do the following:
import pycountry
app.config['BABEL_TRANSLATION_DIRECTORIES'] = 'translations;' + pycountry.LOCALES_DIR
But alas, this does not seem to be enough. For example, gettext('Germany') will not find the translation.
I think the problem might be how translations are structured in pycountry.
~/.local/lib/python3.5/site-packages/pycountry/locales/pt/LC_MESSAGES$ ls
iso15924.mo iso3166-3.mo iso4217.mo iso639-3.mo
iso3166-1.mo iso3166.mo iso639_3.mo
Do I need to specify I want, e.g., the iso3166 file? Please see the following reference.
Reference: pycountry locale documentation section
I also needed to load pycountry locale with flask babel.
To do that, I look into flask-babel get_translations() about how they load translations.
Anyway, I have something working putting this somewhere in your app.
def hack_country_gettext(string):
translations = support.Translations()
catalog = translations.load(pycountry.LOCALES_DIR, [get_locale()], 'iso3166')
translations.merge(catalog)
return translations.ugettext(string)
and instead of _('Germany') use the hack function hack_country_gettext('Germany')

python tkinter using variables across files,?

I have been playing with Tkinter in Python 2.7, and just ran across something that SHOULD be a bug, but isn't and the program seems to work OK still.
To make my program more manageable, I have split it into separate .py files.
One file (called globs.py) is a list of global variables in the form
global var_1
global var_2
...
Then I import globs into my other files.
In another file I can set the variable, thus...
import globs
globs.var_1 = "some value"
In a third file I can use it..
import globs
if globs.var_1 == "something":
...
So far, all is as expected, but...
I just found out if the variable is NOT mentioned in the globs.py file at all, the program still seems to work OK.
Is this intended behavior? Any other programming language would give a 'variable not found' error.
If it is intended, why should I even setup any variables in globs.py?
What are the drawbacks?
Thanks, Mark.

Django: blocktrans not working anymore

In my current project blocktrans is not working anymore (it used to work just fine). trans or one-line-blocktrans work just fine, only multi-line-blocktrans fail. django-admin.py makemessages still picks all these messages up correctly, but in the output the default (en) language will be shown instead of the translated.
Using the python shell I can retrieve the translation. It's the template/localization where system doesn't seem to retrieve the translations. Inside python manage.py shell:
from django.utils import translation
s = "the text"
translation.activate('en')
translation.ugettext(s) # gets the default text
translation.activate('hi')
translation.ugettext(s) # gets the correct translated text
The messages are not fuzzy
I tried to make the translation have as many lines as the original
I'm still on django 1.1
What could I be missing/doing wrong?

Why do Django and gettext fail to load my 'zh' translations?

Django's default LANGUAGES settings contains zh-cn and zh-tw. However, I would like to use zh instead of zh-tw. I've set up my LANGUAGES setting appropriately and compiled the gettext messages but Django will only load the zh-cn translation.
Frustratingly, gettext will load the zh translation fine if I delete the zh_CN directory!
Is there any way to get zh to load the right translation?
My assumption on this is because django itself is only translated into zh-cn and zh-tw. Django translation will only allow you to translate into a language Django itself is translated for.
You should try to translate Django into zh (or copy zh-tw into zh).
Maybe the "Using Gettextize software" from GNU C help.
http://www.gnu.org/software/libc/manual/html_node/Using-gettextized-software.html
Quote:
The file /usr/share/locale/locale.alias (replace /usr with whatever
prefix you used for configuring the C library) contains a mapping of
alternative names to more regular names. The system manager is free to
add new entries to fill her/his own needs. The selected locale from
the environment is compared with the entries in the first column of
this file ignoring the case. If they match the value of the second
column is used instead for the further handling.
Note that the in some system (e.g. Fedora 21), /usr/system/locale/locale.alias is obsoleted and just for backward compatibility.

Django's makemessages creates a lot of fuzzy entries

Each time I added some strings to a Django project, I run "django-admin.py makemessages -all" to generate .PO files for all locales.
The problem is even I only added 5 news strings, the makemessages command will mark 50 strings as fuzzy in .PO files which brings a lot of extra work for our locale maintainers.
This also makes the entire i18n unusable before they manually revise those fuzzy strings.
Removing fuzzy is exactly what I am doing... check this out.
http://code.djangoproject.com/ticket/10852
Sounds like we need extra sh script that automatically removes all the fuzzy from po.
You can use the gettext command line tools to do this now:
msgattrib --clear-fuzzy --empty -o /path/to/output.po /path/to/input.po
The Django management commands just call these tools directly, so you must have this installed. The makemessages uses msgattrib to clear the obsolete strings by setting the output to the same as the input, so I suspect you can do the same with the above to remove fuzzy strings.
From the msgattrib man page:
--clear-fuzzy
set all messages non-'fuzzy'
--empty
when removing 'fuzzy', also set msgstr empty