I am attempting a navbar translation to simplified Chinese in Django, however, only the first word is being translated. To wit, I have created a navbar.html with the following content:
{% load i18n %}
<li>{% trans 'Home' %}</li>
<li>{% trans 'Security' %}</li>
I then do a ./manage.py makemessages -l zh_CN and constructed a file django.po which contains
#: templates/navbar.html:20
msgid "Home"
msgstr "首页"
#: templates/navbar.html:25
msgid "Security"
msgstr "安全性"
I then did a ./manage.py compilemessages to get the django.mo, which appears to have all the translations I need.
As opposed to this question, my LOCALE_PATHS is indeed a tuple:
LOCALE_PATHS = (
os.path.join(BASE_DIR, 'locale'),
)
and my LocaleMiddleware is after SessionMiddleware and before CommonMiddleware, as the documentation specifies:
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.locale.LocaleMiddleware',
'django.middleware.common.CommonMiddleware',
...
]
Yet nonetheless, only Home is translated; all other template variables are left untranslated.
To add a bit more mystery, I translated the navbar to Spanish and all variable were translated properly in the browser. This made me suspect my browser was not using the correct language code, so I ran ./manage.py makemessages -l zh-hans and copied over the translation from the zh_CN directory, but no dice.
Following this, I have removed all instances of #, fuzzy, to no avail.
I am on Django 1.10.3 and Python 3.5.
Related
I've been developing an application which works in English or French (Canadian). Django settings are;
LANGUAGE_CODE = 'en'
LANGUAGES = [
('en', gettext('English')),
('fr-ca', gettext('Canadian French')),
]
LOCALE_PATHS = (
...
os.path.join(PROJECT_ROOT, 'console', 'locale'),
...
)
The app's locale path is console/locale/fr-CA/LC_MESSAGES/
The app however has recently stopped rendering the vast majority of the translations, while django debug toolbar, and other apps are displaying French without issue.
For example, I've got a form with 'First name', 'Last name', 'Email'. Yesterday this was correctly using the po file;
#: console/forms/participants.py:631
msgid "First Name"
msgstr "Prénom"
#: console/forms/participants.py:635
msgid "Last Name"
msgstr "Nom"
#: console/forms/participants.py:140 console/forms/participants.py:469
#: console/forms/participants.py:639 console/models/mixins.py:70
msgid "Email"
msgstr "Courriel"
But today, only the Email string is appearing in French. I assume ugettext is getting that from another application because I've tested it in the shell;
>>> from django.utils.translation import ugettext, activate
>>> activate('fr-ca')
>>> ugettext('Sunday')
u'dimanche'
>>> ugettext('Event')
u'Event'
>>> ugettext('Yes')
u'Oui'
>>> ugettext('Gender')
u'Gender'
>>> ugettext('enquiry')
u'enquiry'
>>> ugettext('Enquiry')
u'Enquiry'
>>> ugettext('Receive notifications about other events.')
u'Receive notifications about other events.'
These are all taken from the app's po file;
#: console/models/events.py:35 console/models/events.py:206
#: console/models/participants.py:81 console/models/vouchers.py:14
msgid "Event"
msgstr "Événement"
#: console/models/participants.py:113
msgid "Gender"
msgstr "Sexe"
#: console/models/participants.py:160
msgid "Receive notifications about other events."
msgstr "Recevez des notifications pour un événement."
It goes without saying I've ran the translation management commands (and can see the locale paths being output);
manage.py makemessages -l fr-CA
manage.py compilemessages -l fr-CA
You should remember that ugettext_lazy is a lazy evaluation and should be used in models and forms (as they load only once in Django) for views you should use gettext
Try delete (backup) translation files and recreate them again
Check templates for existence of translation blocks
I'm trying to enable translations for a django project and django-admin.py makemessages -l de doesn't seem to create any .po files, although there is a couple of {% trans ... %} in templates and a couple of gettext(...) in models for tests.
Accorgin to the documentation https://docs.djangoproject.com/en/1.7/ref/django-admin/#django-admin-makemessages, the command should search for translations in the whole project tree and create corresponding files in e.g. conf/locale directory if no setting is specified.
The only output I get is processing locale ru.
Any way to debug it or maybe well known pitfalls that I didn't find in google?
Let me answer my own question :)
The problem was that I:
Didn't import gettext as _ but did import gettext as t, thus makemessage didn't recognize translated strings in .py files
Tried to translate non-existing variables in templates instead of strings. {% trans some_var %} instead of {% trans "some_string" %}
Make sure you have the following settings available in your settings.py file:
DJANGO_ROOT = dirname(dirname(abspath(__file__)))
SITE_ROOT = dirname(DJANGO_ROOT)
USE_I18N = True
LOCALE_PATHS = (
SITE_ROOT + '/locale',
)
If the LOCALE_PATHS value is not set it does not know where it should create the locale directories and translation files, also you don't have to have the DJANGO_ROOT and SITE_ROOT values that's just for ease of use.
I configured my application to support 2 languages: english and italian.
In my settings.py I specified i18n-related stuff as following:
USE_I18N = True
USE_L10N = True
USE_TZ = True
LANGUAGES = (
('en', 'ENGLISH'),
('it', 'ITALIAN'),
)
then I created a "locale" folder for each application and used the following commands to generate .po/.mo files:
django-admin.py makemessages -l en --no-location --no-obsolete
django-admin.py makemessages -l it --no-location --no-obsolete
django-admin.py compilemessages
All works fine, but I have a template where the two translations get mixed up (ie: part of the texts are in italian and other in english). I think that the problem is related to how my browser (Chrome) sends language headers (currently: Accept-Language: it,en-US;q=0.8,en;q=0.6).
Other browser on my machine like Firefox are sending: Accept-Language: en-US,en;q=0.5
Ok, this may be a personal problem related to a "strange browser configuration", but is not acceptable to have such result... how can I avoid this issue and have a coherent translation?
Is it possible that there is some content with origin from DB and thus not provided with translations?
On the other hand it may be the problem in rendering multiline fields in your .po files or .html files (make sure everything is {% trans ... %} wrapped.
Lastly if in Chrome you ask for translation in English when you are in the Italian site, does it provide you with all English content and vice verso?
A python newbie here.
I wanna my website support English and Chinese. So I just follow django book, chapter 19 internationalization. But it seems doesn't work for me, string I hope to be displayed as chinese, still english there. My code and settin is as following.
[settings.py]
LANGUAGE_CODE = 'zh-cn'
USE_I18N = True
USE_L10N = True
LANGUAGES = (
('en', 'English'),
('zh-cn', 'Chinese')
)
TEMPLATE_CONTEXT_PROCESSORS = {
'django.core.context_processors.i18n',
}
MIDDLEWARE_CLASSES = (
'django.middleware.locale.LocaleMiddleware',
'django.middleware.common.CommonMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
)
In my app views.py, I forcely set language code as 'zh-cn' in index
def index( request ):
response= render_to_response( 'index.htm' )
response.set_cookie('django_language','zh-cn')
return response
then I'd hope annother page that will be loaded after index.htm, will display a chinese string.
Annother page is renderred by upload.html
{% load i18n %}
<html>
<head>
{% block head %}
{% endblock %}
</head>
<body>
{% block body %}
<h1>{% trans 'Upload Demo' %}</h1>
{% endblock %}
</body>
</html>
After then, I do
django-admin.py makemessages -l zh-cn -e htm
in my django project folder, and I got django.po at
locale/zh-cn/LC_MESSAGES/django.po
which content is like
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2012-05-10 18:33+0800\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL#ADDRESS>\n"
"Language-Team: LANGUAGE <LL#li.org>\n"
"Language: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
#: uploader/template/base.htm:10
msgid "Upload Demo"
msgstr "上传文件"
Thereafter, I call following command to compile message
django-admin.py compilemessages
I got django.mo file at some folder with django.po
Fistly I access the index page, then I access another page, which has 'Upload Demo' string id. Actually I still see english string there.
And tried debug via printing language code, find that language has been set correctly.
context = RequestContext(request)
print context
translation.activate('zh-cn')
Lastly, I use
gettext locale/zh-cn/LC_MESSAGES/django.mo "Upload Demo"
really got 'Upload Demo'. So I think problem is here.
But why this happen? I really confused. Can any body help me.
Deeply appreciated any comment or help.
gettext locale/zh-cn/LC_MESSAGES/django.mo "Upload Demo"
I think I made a mistake. Above command return a string that is same as string you typed as string ID rather than translated string. In above command, it is "Upload Demo", That is if your change "Upload Demo" in above command as "bla bla", you will "bla bla".
Maybe it's too late, but I bet your problem probably was due to missing LOCALE_PATHS tuple in your project's settings.
After an hour of pulling my hair out, I solved the same problem by simply adding this to the settings.py file in my project:
LOCALE_PATHS = (
'/home/myuser/Projects/Some_project_root/My_django_project_root/locale',
)
And this is how that directory looks:
locale/
├── de
│ └── LC_MESSAGES
│ ├── django.mo
│ └── django.po
├── en
│ └── LC_MESSAGES
│ ├── django.mo
│ └── django.po
└── es
└── LC_MESSAGES
├── django.mo
└── django.po
Your codeblocks are a bit messy so it is quite hard to read it all. But you might want to start with your .mo file. It contains a #, fuzzy annotation. Fuzzy means that the build script was not sure about the translation and therefore requires attention of the translator (=you). Start by checking all #, fuzzy marked translations. If the translation is correct (or after you have corrected the wrong translation) remove the #, fuzzy annotation. Next run compile messages again. This could fix your problem.
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2012-05-10 18:33+0800\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME \n"
"Language-Team: LANGUAGE \n"
"Language: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
See also: django fuzzy string translation not showing up
Friendly regards,
Wout
You can see LANGUAGE_CODE is not the same as django_language. I think get_language in utils.py does not handle underscore LANGUAGES correctly. get_language will return zh-cn but it should not be cut into cn. Instead, zh-cn should be converted to zh_CN.
So you should use below code in setting.py
LANGUAGES = (
('en', _('English')),
('zh-cn', _('Simplified Chinese')),
)
and run the following command from terminal
django-admin.py makemessages -l zh_CN
django-admin.py compilemessages
This is working perfectly for me
I believe the issue lies within the makemessages and compilemessages arguments that you are passing. #Vishnu's answer above is correct.
TLDR
Don't use zh-cn for the locale. Use zh_CN.
django-admin.py makemessages -l zh_CN
django-admin.py compilemessages -l zh_CN
Explanation
The "locale name" as defined in the Django Docs is:
A locale name, either a language specification of the form ll or a combined language and country specification of the form ll_CC. Examples: it, de_AT, es, pt_BR. The language part is always in lower case and the country part in upper case. The separator is an underscore.
In the makemessages example (found at the bottom of the makemessages documentation), you will notice the use of the locale name convention:
django-admin makemessages --locale=pt_BR
django-admin makemessages --locale=pt_BR --locale=fr
django-admin makemessages -l pt_BR
django-admin makemessages -l pt_BR -l fr
django-admin makemessages --exclude=pt_BR
django-admin makemessages --exclude=pt_BR --exclude=fr
django-admin makemessages -x pt_BR
django-admin makemessages -x pt_BR -x fr
You will notice the same in the compilemessages example:
django-admin compilemessages --locale=pt_BR
django-admin compilemessages --locale=pt_BR --locale=fr -f
django-admin compilemessages -l pt_BR
django-admin compilemessages -l pt_BR -l fr --use-fuzzy
django-admin compilemessages --exclude=pt_BR
django-admin compilemessages --exclude=pt_BR --exclude=fr
django-admin compilemessages -x pt_BR
django-admin compilemessages -x pt_BR -x fr
I have experienced a similar problem: compilemessagesseems to be working only on locale in the current directory. This was a remedy:
find . -name "locale" | while read VAR1; do CURR="``pwd``";cd $VAR1/..; echo "in $VAR1";django-admin.py compilemessages ; cd $CURR; done`
There is an outstanding problem in this code which is as follow:
In settings.py Make sure django.middleware.locale.LocaleMiddleware in the MIDDLEWARE setting comes after SessionMiddleware and CacheMiddleware and before CommonMiddleware if those other middlewares are used.
# settings.py
MIDDLEWARE = [
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.cache',
# ...
'django.middleware.locale.LocaleMiddleware',
# ...
'django.middleware.common.CommonMiddleware',
]
for more information see: 1 , 2
I have created translation strings in the template and in the application view.
Then I ran:
django-admin.py makemessages -l it
and the file it/LC_MESSAGES/django.po has been created
I have now translated strings in the django.po file, and then I ran:
django-admin.py compilemessages
And I receive:
processing file django.po in /home/jobber/Desktop/library/books/locale/it/LC_MESSAGES
My settings.py looks like this:
LANGUAGE_CODE = 'it'
TEMPLATE_CONTEXT_PROCESSORS = ( "django.core.context_processors.auth",
"django.core.context_processors.debug",
"django.core.context_processors.i18n",
"django.core.context_processors.media", )
USE_I18N = True
MIDDLEWARE_CLASSES = ( 'django.middleware.common.CommonMiddleware',
'django.middleware.locale.LocaleMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
)
but I still always see English text. Why?
Maybe your browser language is English. The LocaleMiddleware tries to detect the language based on this algorithm (i.e. Accept-Language HTTP header).
So you can either remove the LocaleMiddleware to avoid this or use the set_language redirect view.
In addition to the accepted answer: If you're using Firefox you can install Quick Locale Switcher to test your application with different languages (based on the browser language). It adds a button at the bottom of your screen where you can easily change your browser language.