How to re-translate Django

Hello,

Django comes pre-translated in my language but I don’t like some of phrases. One way to solve this is to edit the django.mo file of the corresponding app (auth for instance), but I assume if I update Django, it will overwrite my edits.

What is the appropriate solution then?

I would outline two different cases:

  1. If the phrases you mention are obviously wrong or suboptimal, I would strongly encourage you to join the Transifex team of your language and fix the affected strings so you and everyone else in your language can benefit of your work… in the spirit of open source.

  2. If this is mostly a matter of personal/project preference, then I guess you have to create your own po/mo files somewhere in your project, add the affected strings with modified translations in those files, and place those files in a location that have higher priority for discovery, as described in Translation | Django documentation | Django

Hope this helps,

Claude

P.S. you should refrain from directly editing .mo files, create/edit .po files and compile them with msgfmt (or using compilemessages management command if the files are discoverable by Django).

Thank you very much.

What I don’t understand is that why I can see this in venv\Lib\site-packages\django\contrib\auth\locale\fa\LC_MESSAGES\django.po:

#: .\venv\Lib\site-packages\django\contrib\auth\base_user.py:59
msgid "password"
msgstr "گذرواژه"

But not in the locale\fa\LC_MESSAGES\django.po when I run python manage.py makemessages -l fa command?

And I do have another question. As you see below, some of permissions of internal models are not translated. How can I translate them?
Screenshot 2024-01-13 165920

[quote=“OmidShojaee, post:3, topic:26683, full:true”]

But not in the locale\fa\LC_MESSAGES\django.po when I run python manage.py makemessages -l fa command?

Because the makemessages command will only extract strings from your project, not the strings from Django built-in code or templates. A trick is for example to create some fake (=unused in your project) files (code or template) in your project where you put the strings you want to re-translate in your own po files.

And I do have another question. As you see below, some of permissions of internal models are not translated. How can I translate them?

This is a known issue: #1688 (Permissions don't get translated in admin interface) – Django

Claude

Would you please elaborate? Let’s say I want to re-translate msgid "Personal info" from django.contrib.auth. How that trick works here?

In one of your apps that have translations, put in one of the files somehting like:

from django.utils.translation import gettext

gettext("Personal info")

So when you run makemessages, this translatable string will appear in your <language>.po file and you can translate it like you want.
Now for your app translations being prioritized over contrib.auth translations, it should appear before it in INSTALLED_APPS. Or you could decide to put your project translations to LOCALE_PATHS (Translation | Django documentation | Django).

Hope this helps,

Claude

Unfortunately this didn’t work.
I’m trying to re-translate django-filebrowser. One of the entries is translated as this:

.\venv\Lib\site-packages\filebrowser\locale\fa\LC_MESSAGES\django.po

#: .\venv\Lib\site-packages\filebrowser\models.py:8
#: .\venv\Lib\site-packages\filebrowser\models.py:9
#: .\venv\Lib\site-packages\filebrowser\sites.py:350
#: .\venv\Lib\site-packages\filebrowser\templates\filebrowser\include\breadcrumbs.html:9
#: .\venv\Lib\site-packages\filebrowser\templates\filebrowser\include\breadcrumbs.html:11
msgid "FileBrowser"
msgstr "فایل‌بروز"

So in my app I create a file called translations.py with the following content:

from django.utils.translation import gettext

gettext("FileBrowser")

I make messages and find the above entry in my django.po file. I translate it and then compile the messages but in the Admin site I still see the original translation.

It may depend on the order of the apps in INSTALLED_APPS. You can try to explore the effect of various positions.

I moved my app to the top. Nothing changed.

Hello @claudep

As discussed, you may find the project I’ve started recently here: omidshojaee/artanetwork.com: The source code of artanetwork.com website, shop and blog. (github.com)

There are a few customizations but you may ignore them.

As explained here on SO I have an app called core with a translations.py file containing a phrase from django-filebrowser library.

If you check the Admin site you’ll notice that no matter what I do, I can’t override the library’s translation as shown here:

image

Helo @OmidShojaee,

Thanks for the project! I explored it a bit today. I can confirm this is unrelated to the Django translation system.

To display this string in the admin, Django is using the AppConfig.verbose_name of the installed application, and if not present, it defaults to the (untranslatable) AppConfig.label.title(). You can see the code here: django/django/apps/config.py at bc9b6251e0b54c3b5520e3c66578041cc17e4a28 · django/django · GitHub

django-filebrowser-no-grappelli does not provide any apps.py and hence the default untranslatable name is computed from its default label.

What you could do:
a. Ask django-filebrowser-no-grappelli to include an apps.py in their package, with a translatable verbose_name attribute.
b. Create your own AppConfig instance for filebrowser in your project (explained here in the docs: Applications | Django documentation | Django), including a translatable verbose_name attribute.

Hopefully this should help you going forward, Happy coding :smile:

Hello @claudep

You’re mistaking “FILEBROWSER” with “فایل‌بروز”.

The first is the app title and you’re correct that the AppConfig is not present so this string is untranslatable.

The second is a string you can find in the django.po file of the django-filebrowser package (locale/fa/LC_MESSAGES).

The English version is “FileBrowser”, it is translated to “فایل‌بروز” from Transifex, and I want to re-translate it to “مدیریت فایل” (in the translations.py file of the core app) and it doesn’t work.

Sorry, my bad. I will try to explore further ASAP.

That’s fine. Thanks.

On second look, I discovered your are experiencing issue #34221 (Plural-Forms in .po files break Django's translation precedence.) – Django

You should be able to workaround it temporarily by using the same Plural-Forms equation in your .po file as filebrowser (Plural-Forms: nplurals=1; plural=0;), even if it’s not the right equation for Farsi.

Of course, the proper resolution would be to write the patch as a pull request for Django so as to solve #34221 (for Django 5.2).

Hope this helps!

So this is a bug after all :wink:

Thank you very much. Your workaround works and now I’m able to translate “فایل‌بروز”.

However, I’ve created this file but the string doesn’t show up in the po file so I can’t translate app title:

# venv/Lib/site-packages/filebrowser/apps.py

from django.apps import AppConfig
from django.utils.translation import gettext_lazy as _


class FileBrowserConfig(AppConfig):
    name = 'filebrowser'
    verbose_name = _('filebrowser')

What is the issue here?

You must create that file somewhere in your source tree, not in the virtualenv. Then add a path to it in your INSTALLED_APPS setting.

Sorry @claudep

Tried many combinations of locations and content of apps.py file and none worked.

Truly appreciate if you provide the working code and where to save it.

Here’s how I’ve followed the instructions provided in the documentation using an app called core:

# core/apps.py

from django.apps import AppConfig
from django.utils.translation import gettext_lazy as _

from filebrowser.apps import FileBrowserConfig


class CoreConfig(AppConfig):
    default_auto_field = 'django.db.models.BigAutoField'
    name = 'core'


class CustomFileBrowserConfig(FileBrowserConfig):
    name = 'filebrowser'
    verbose_name = _('File Browser')

I get ModuleNotFoundError: No module named 'filebrowser.apps'

Sure, as filebrowser doesn’t provide any apps.py, you should inherit from AppConfig also for your CustomFileBrowserConfig class. Of course, if filebrowser adds an apps.py in the future, you may then change the base class (or simply remove your class).