# How to re-translate Django

**URL:** <https://forum.djangoproject.com/t/how-to-re-translate-django/26683>\
**Category:** Internationalization\
**Created:** [January 6, 2024, 2:10pm UTC](https://forum.djangoproject.com/t/how-to-re-translate-django/26683 "2024-01-06T14:10:23Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![OmidShojaee](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/omidshojaee/32/2216_2.png) [@OmidShojaee](https://forum.djangoproject.com/u/OmidShojaee)\
**Post date:** [January 6, 2024, 2:10pm UTC](https://forum.djangoproject.com/t/how-to-re-translate-django/26683/1 "2024-01-06T14:10:23Z")

</div>

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?

---

<div class="post-metadata">

**Author:** ![claudep](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/claudep/32/5377_2.png) [@claudep](https://forum.djangoproject.com/u/claudep)\
**Post date:** [January 7, 2024, 10:11am UTC](https://forum.djangoproject.com/t/how-to-re-translate-django/26683/2 "2024-01-07T10:11:53Z")

</div>

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](https://docs.djangoproject.com/en/5.0/topics/i18n/translation/#how-django-discovers-translations)

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).

---

<div class="post-metadata">

**Author:** ![OmidShojaee](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/omidshojaee/32/2216_2.png) [@OmidShojaee](https://forum.djangoproject.com/u/OmidShojaee)\
**Post date:** [January 14, 2024, 6:41am UTC](https://forum.djangoproject.com/t/how-to-re-translate-django/26683/3 "2024-01-14T06:41:03Z")

</div>

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`:

```auto
#: .\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](https://us1.discourse-cdn.com/flex026/uploads/djangoproject/original/3X/b/7/b7891b85cc5effa57c157e088f0ee8294f6efc70.png)

---

<div class="post-metadata">

**Author:** ![claudep](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/claudep/32/5377_2.png) [@claudep](https://forum.djangoproject.com/u/claudep)\
**Post date:** [January 14, 2024, 3:56pm UTC](https://forum.djangoproject.com/t/how-to-re-translate-django/26683/4 "2024-01-14T15:56:44Z")

</div>

[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](https://code.djangoproject.com/ticket/1688)

Claude

---

<div class="post-metadata">

**Author:** ![OmidShojaee](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/omidshojaee/32/2216_2.png) [@OmidShojaee](https://forum.djangoproject.com/u/OmidShojaee)\
**Post date:** [January 31, 2024, 7:25am UTC](https://forum.djangoproject.com/t/how-to-re-translate-django/26683/5 "2024-01-31T07:25:30Z")

</div>

> [@claudep](#):
>
> 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.

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

---

<div class="post-metadata">

**Author:** ![claudep](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/claudep/32/5377_2.png) [@claudep](https://forum.djangoproject.com/u/claudep)\
**Post date:** [January 31, 2024, 7:55am UTC](https://forum.djangoproject.com/t/how-to-re-translate-django/26683/6 "2024-01-31T07:55:44Z")

</div>

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

```auto
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](https://docs.djangoproject.com/en/stable/topics/i18n/translation/#how-django-discovers-translations)).

Hope this helps,

Claude

---

<div class="post-metadata">

**Author:** ![OmidShojaee](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/omidshojaee/32/2216_2.png) [@OmidShojaee](https://forum.djangoproject.com/u/OmidShojaee)\
**Post date:** [June 20, 2024, 10:06am UTC](https://forum.djangoproject.com/t/how-to-re-translate-django/26683/7 "2024-06-20T10:06:59Z")

</div>

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

```auto
#: .\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:

```auto
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.

---

<div class="post-metadata">

**Author:** ![claudep](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/claudep/32/5377_2.png) [@claudep](https://forum.djangoproject.com/u/claudep)\
**Post date:** [June 20, 2024, 11:26am UTC](https://forum.djangoproject.com/t/how-to-re-translate-django/26683/8 "2024-06-20T11:26:29Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![OmidShojaee](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/omidshojaee/32/2216_2.png) [@OmidShojaee](https://forum.djangoproject.com/u/OmidShojaee)\
**Post date:** [June 20, 2024, 12:08pm UTC](https://forum.djangoproject.com/t/how-to-re-translate-django/26683/9 "2024-06-20T12:08:01Z")

</div>

I moved my app to the top. Nothing changed.

---

<div class="post-metadata">

**Author:** ![OmidShojaee](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/omidshojaee/32/2216_2.png) [@OmidShojaee](https://forum.djangoproject.com/u/OmidShojaee)\
**Post date:** [August 26, 2024, 8:15am UTC](https://forum.djangoproject.com/t/how-to-re-translate-django/26683/10 "2024-08-26T08:15:54Z")

</div>

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)](https://github.com/omidshojaee/artanetwork.com)

There are a few customizations but you may ignore them.

As explained [here on SO](https://stackoverflow.com/a/20439571/14442010) 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](https://us1.discourse-cdn.com/flex026/uploads/djangoproject/original/3X/1/7/17cc47b765fe41065c71604ae2b2f3e52bb2187c.png)

---

<div class="post-metadata">

**Author:** ![claudep](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/claudep/32/5377_2.png) [@claudep](https://forum.djangoproject.com/u/claudep)\
**Post date:** [August 26, 2024, 7:39pm UTC](https://forum.djangoproject.com/t/how-to-re-translate-django/26683/11 "2024-08-26T19:39:11Z")

</div>

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](https://github.com/django/django/blob/bc9b6251e0b5/django/apps/config.py#L40)

[django-filebrowser-no-grappelli](https://github.com/smacker/django-filebrowser-no-grappelli/tree/master) 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](https://docs.djangoproject.com/en/5.1/ref/applications/#for-application-users)), including a translatable `verbose_name` attribute.

Hopefully this should help you going forward, Happy coding 😄

---

<div class="post-metadata">

**Author:** ![OmidShojaee](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/omidshojaee/32/2216_2.png) [@OmidShojaee](https://forum.djangoproject.com/u/OmidShojaee)\
**Post date:** [August 27, 2024, 2:15am UTC](https://forum.djangoproject.com/t/how-to-re-translate-django/26683/12 "2024-08-27T02:15:18Z")

</div>

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.

---

<div class="post-metadata">

**Author:** ![claudep](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/claudep/32/5377_2.png) [@claudep](https://forum.djangoproject.com/u/claudep)\
**Post date:** [August 27, 2024, 7:01am UTC](https://forum.djangoproject.com/t/how-to-re-translate-django/26683/13 "2024-08-27T07:01:05Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![OmidShojaee](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/omidshojaee/32/2216_2.png) [@OmidShojaee](https://forum.djangoproject.com/u/OmidShojaee)\
**Post date:** [August 27, 2024, 7:12am UTC](https://forum.djangoproject.com/t/how-to-re-translate-django/26683/14 "2024-08-27T07:12:12Z")

</div>

That’s fine. Thanks.

---

<div class="post-metadata">

**Author:** ![claudep](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/claudep/32/5377_2.png) [@claudep](https://forum.djangoproject.com/u/claudep)\
**Post date:** [August 27, 2024, 4:46pm UTC](https://forum.djangoproject.com/t/how-to-re-translate-django/26683/15 "2024-08-27T16:46:05Z")

</div>

On second look, I discovered your are experiencing issue [#34221 (Plural-Forms in .po files break Django's translation precedence.) – Django](https://code.djangoproject.com/ticket/34221)

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!

---

<div class="post-metadata">

**Author:** ![OmidShojaee](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/omidshojaee/32/2216_2.png) [@OmidShojaee](https://forum.djangoproject.com/u/OmidShojaee)\
**Post date:** [August 30, 2024, 8:35am UTC](https://forum.djangoproject.com/t/how-to-re-translate-django/26683/16 "2024-08-30T08:35:39Z")

</div>

So this is a bug after all 😉

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:

```auto
# 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?

---

<div class="post-metadata">

**Author:** ![claudep](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/claudep/32/5377_2.png) [@claudep](https://forum.djangoproject.com/u/claudep)\
**Post date:** [August 30, 2024, 11:34am UTC](https://forum.djangoproject.com/t/how-to-re-translate-django/26683/17 "2024-08-30T11:34:45Z")

</div>

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.

---

<div class="post-metadata">

**Author:** ![OmidShojaee](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/omidshojaee/32/2216_2.png) [@OmidShojaee](https://forum.djangoproject.com/u/OmidShojaee)\
**Post date:** [August 31, 2024, 9:16am UTC](https://forum.djangoproject.com/t/how-to-re-translate-django/26683/18 "2024-08-31T09:16:10Z")

</div>

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.

---

<div class="post-metadata">

**Author:** ![OmidShojaee](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/omidshojaee/32/2216_2.png) [@OmidShojaee](https://forum.djangoproject.com/u/OmidShojaee)\
**Post date:** [September 1, 2024, 5:01am UTC](https://forum.djangoproject.com/t/how-to-re-translate-django/26683/19 "2024-09-01T05:01:22Z")

</div>

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

```auto
# 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'`

---

<div class="post-metadata">

**Author:** ![claudep](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/claudep/32/5377_2.png) [@claudep](https://forum.djangoproject.com/u/claudep)\
**Post date:** [September 1, 2024, 7:29am UTC](https://forum.djangoproject.com/t/how-to-re-translate-django/26683/20 "2024-09-01T07:29:40Z")

</div>

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).

[Next page](https://forum.djangoproject.com/t/how-to-re-translate-django/26683.md?page=2)
