35

Django's internationalization is very nice (gettext based, LocaleMiddleware), but what is the proper way to translate the model name and the attributes for admin pages? I did not find anything about this in the documentation:

I would like to have "Выберите заказ для изменения" instead of "Выберите order для изменения". Note, the 'order' is not translated.

First, I defined a model, activated USE_I18N = True in settings.py, run django-admin makemessages -l ru. No entries are created by default for model names and attributes.

Grepping in the Django source code I found:

$ ack "Select %s to change"
contrib/admin/views/main.py
70:        self.title = (self.is_popup and ugettext('Select %s') % force_unicode(self.opts.verbose_name) or ugettext('Select %s to change') % force_unicode(self.opts.verbose_name))

So the verbose_name meta property seems to play some role here. Tried to use it:

class Order(models.Model):
    subject = models.CharField(max_length=150)
    description = models.TextField()
    class Meta:
        verbose_name = _('order')

Now the updated po file contains msgid 'order' that can be translated. So I put the translation in. Unfortunately running the admin pages show the same mix of "Выберите order для изменения".

I'm currently using Django 1.1.1. Could somebody point me to the relevant documentation? Because google can not. ;-) In the mean time I'll dig deeper into the django source code...

Super Kai - Kazuya Ito
  • 22,221
  • 10
  • 124
  • 129
geekQ
  • 29,027
  • 11
  • 62
  • 58
  • 2
    Sorry to ask, but after updating the .po file did you run ./manage.py makemessages to update the .mo file? – Steve Jalim May 30 '10 at 13:01
  • 1
    `makemessages` only updates the po files. I think you mean `django-admin compilemessages` - thank you for your hint! I thought because python is a dynamic language, the translation files are not compiled, in opposite to C. Unfortunately my solution still does not work delivering a mixed translation (languages are mixed in one sentence). For model name the LANGUAGE_CODE setting of the project is used. The language for remaining message is determined by the User Agent ('Accept-Languages'). I'll experiment with lazy translation and tell if it works. – geekQ May 31 '10 at 16:20

4 Answers4

49

Important things not mentioned in the Django documentation:

  • run django-admin compilemessages, e.g. as a part of your build process. Thanks stevejalim!
  • apply django's ugettext_lazy() to model names ( Meta class and verbose_name )
  • attribute (model field verbose_name) names can also be translated with ugettext_lazy()
  • use lazy translation in your model metadata, otherwise the translation happens while loading the model classes and the settings of your users, especially the browser settings, will not be taken into account
  • I use some scoping for attribute names, e.g. separating the model name and attribute names with a pipe. The same convention is used in ruby-gettext. Background: attribute names like 'title' or 'name' translated differently in the most languages depending on context. Example 'Book|title' -> 'Titel' or 'Buchtitel' in German. But 'Chapter|title' would be translated as 'Überschrift'.

Example using above principles:

from django.utils.translation import ugettext_lazy as _
class Order(models.Model):
    subject = models.CharField(max_length=150, verbose_name = _('Order|subject'))
    description = models.TextField(            verbose_name = _('Order|description'))
    class Meta:
        verbose_name = _('order')
        verbose_name_plural = _('orders')

Or is there a better way to translate the model and admin pages?

Either way we should enhance the Django documentation and fill the gap!

hobs
  • 18,473
  • 10
  • 83
  • 106
geekQ
  • 29,027
  • 11
  • 62
  • 58
2

See https://automationpanda.com/2018/04/21/django-admin-translations/ It's author made an excellent work in showing how to master all django translation features step by step. It's much better than oficial documentation to me.

Alvaro Rodriguez Scelza
  • 3,643
  • 2
  • 32
  • 47
0

I use both ugettext with _ and ugettext_lazy with a double __. Consequently, the makemessages management command was only collecting the first ones.

To collect both _ and __ we can ask the gettext tool to collect more than the default strings enclosed in _( ). To do this, we override the makemessages command: https://docs.djangoproject.com/en/dev/topics/i18n/translation/#customizing-the-makemessages-command

# myapp/management/commands/makemessages.py
from django.core.management.commands import makemessages

class Command(makemessages.Command):
    self.stdout.write("----> Using our custom makemessages command to collect both _ and double __")
    xgettext_options = makemessages.Command.xgettext_options + ['--keyword=__']  # <-- added __

My models in Admin are now finally fully translated.

Ehvince
  • 17,274
  • 7
  • 58
  • 79
0

I also couldn't translate a model label in Django Admin because there are #, fuzzy in django.po as shown below:

# "django.po"

...

#: .\my_app1\models.py:12
#, fuzzy # <- Here
msgid "person"
msgstr "personne"

#: .\my_app1\models.py:13
#, fuzzy # <- Here
msgid "persons"
msgstr "personnes"

...

So, I removed #, fuzzy from django.po as shown below, then I could translate the model label in Django Admin. *You can see my question and my answer explaining it in detail:

# "django.po"

...

#: .\my_app1\models.py:12
msgid "person"
msgstr "personne"

#: .\my_app1\models.py:13
msgid "persons"
msgstr "personnes"

...

In addition, fuzzy is explained in the doc as shown below:

fuzzy

This flag can be generated by the msgmerge program or it can be inserted by the translator herself. It shows that the msgstr string might not be a correct translation (anymore). Only the translator can judge if the translation requires further modification, or is acceptable as is. Once satisfied with the translation, she then removes this fuzzy attribute. The msgmerge program inserts this when it combined the msgid and msgstr entries after fuzzy search only. See Fuzzy Entries.

Super Kai - Kazuya Ito
  • 22,221
  • 10
  • 124
  • 129