For example below, you can translate English to French. *I use Django 4.2.3.
First, create locale
folder just under django-project
as shown below. *You can see my answer explaining how to set templates:
django-project
|-core
| |-settings.py
| └-urls.py
|-my_app1
| |-views.py
| |-urls.py
| |-models.py
| |_admin.py
| └-apps.py
|-my_app2
|-templates
| └-index.html
└-locale # Here
Then, set core/settings.py
as shown below. *LocaleMiddleware
must be between SessionMiddleware
and CommonMiddleware
. 'en-us'
is set to LANGUAGE_CODE
by default in core/settings.py
:
# "core/settings.py"
MIDDLEWARE = [
...
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.locale.LocaleMiddleware', # Here
'django.middleware.common.CommonMiddleware',
...
]
LANGUAGE_CODE = 'en-us'
TIME_ZONE = 'UTC'
USE_I18N = True
USE_TZ = True
from django.utils.translation import gettext_lazy as _
LANGUAGES = ( # Here
('en', _('English')),
('fr', _('French'))
)
And, Hello
and World
are translated with gettext() and outputted on console and index.html
is rendered in test()
in my_app1/views.py
as shown below. *You can see my answer explaining where to use gettext()
and gettext_lazy():
# "my_app1/views.py"
from django.shortcuts import render
from django.utils.translation import gettext as _
def test(request):
print(_("Hello"), _("World")) # Here
return render(request, 'index.html')
And, test()
path is set to urlpatterns
in my_app1/urls.py
as shown below. *You can see my question and my answer explaining how to translate url in Django:
# "my_app1/urls.py"
from django.urls import path
from . import views
app_name = "my_app1"
urlpatterns = [
path('', views.test, name="test") # Here
]
And, admin
and my_app1
paths are set to urlpatterns
with i18n_patterns() in core/urls.py
as shown below. *You can see my question and my answer explaining prefix_default_language=False with i18n_patterns()
:
# "core/urls.py"
from django.contrib import admin
from django.urls import path, include
from django.conf.urls.i18n import i18n_patterns
urlpatterns = i18n_patterns(
path('admin/', admin.site.urls), # Here
path('my_app1/', include('my_app1.urls')) # Here
)
And, 3 tags are set in templates/index.py
as shown below. *For the translation in Django Templates, {% load i18n %}
is needed and {% translate %}
or {% trans %}
can translate:
# "templates/index.py"
{% load i18n %}
{% translate "Hello" %} {% trans "World" %}
And, name
field and person
model are translated in my_app1/models.py
as shown below:
# "my_app1/models.py"
from django.db import models
from django.utils.translation import gettext_lazy as _
class Person(models.Model):
first_name = models.CharField(
max_length=20, verbose_name=_("first name") # Here
)
last_name = models.CharField(
max_length=20, verbose_name=_("last name") # Here
)
class Meta:
verbose_name = _('person') # Here
verbose_name_plural = _('persons') # Here
And, this is my_app1/admin.py
below:
# "my_app1/admin.py"
from django.contrib import admin
from .models import Person
@admin.register(Person)
class PersonAdmin(admin.ModelAdmin):
pass
And, my_app1
is translated in my_app1/apps.py
as shown below:
# "my_app1/apps.py"
from django.apps import AppConfig
from django.utils.translation import gettext_lazy as _
class MyApp1Config(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'my_app1'
verbose_name = _('my_app1') # Here
Now, run the command below. *You can see my answer explaining the command below:
django-admin makemessages -l fr
Then, django.po
is created in locale/fr/LC_MESSAGES/
as shown below:
django-project
|-core
| |-settings.py
| └-urls.py
|-my_app1
| |-views.py
| |-urls.py
| |-models.py
| |_admin.py
| └-apps.py
|-my_app2
|-templates
| └-index.html
└-locale
└-fr
└-LC_MESSAGES
└-django.po # Here
Then, add Bonjour
, Monde
, Anglais
and Français
to each msgstr ""
respectively in locale/fr/LC_MESSAGES/django.po
as shown below:
# "locale/fr/LC_MESSAGES/django.po"
...
#: .\core\settings.py:140
msgid "English"
msgstr "Anglais" # Here
#: .\core\settings.py:141
msgid "French"
msgstr "Français" # Here
#: .\my_app1\apps.py:7
msgid "my_app1"
msgstr "mon_app1" # Here
#: .\my_app1\models.py:6
msgid "first name"
msgstr "prénom"
#: .\my_app1\models.py:7
msgid "last name"
msgstr "nom de famille"
#: .\my_app1\models.py:13
msgid "person"
msgstr "personne"
#: .\my_app1\models.py:14
msgid "persons"
msgstr "personnes"
#: .\my_app1\views.py:5 .\templates\index.html:3
msgid "Hello"
msgstr "Bonjour" # Here
#: .\my_app1\views.py:5 .\templates\index.html:3
msgid "World"
msgstr "Monde" # Here
...
Then, run the command below to compile django.po
to django.mo
. *You can see my answer explaining the command below:
django-admin compilemessages
Then, django.po
is compiled to django.mo
in locale/fr/LC_MESSAGES/
as shown below:
django-project
|-core
| |-settings.py
| └-urls.py
|-my_app1
| |-views.py
| |-urls.py
| |-models.py
| |_admin.py
| └-apps.py
|-my_app2
|-templates
| └-index.html
└-locale
└-fr
└-LC_MESSAGES
|-django.po
└-django.mo # Here
Now, http://localhost:8000/en/my_app1/
can show Hello World
as shown below:

And, Hello World
below is outputted on console:
Hello World
And, http://localhost:8000/fr/my_app1/
can show Bonjour Monde
as shown below:

And, Bonjour Monde
below is outputted on console:
Bonjour Monde
And, http://localhost:8000/en/admin/my_app1/person/add/
can show the English version of Django Admin including the app, model and field labels as shown below:

And, http://localhost:8000/fr/admin/my_app1/person/add/
can show the French version of Django Admin including the app, model and field labels as shown below:

In addition, you set English
as the 1st language in your browser as shown below. *This is Google Chrome:

Now, if you access http://localhost:8000/my_app1/
, then you are redirected to http://localhost:8000/en/my_app1/
as shown below:

And, you set French
as the 1st language in your browser as shown below.

Now, if you access http://localhost:8000/my_app1/
, then you are redirected to http://localhost:8000/fr/my_app1/
as shown below:

In addition again, you can remove i18n_patterns()
from admin
and my_app1
paths in core/urls.py
as shown below:
# "core/urls.py"
from django.contrib import admin
from django.urls import path, include
# from django.conf.urls.i18n import i18n_patterns
urlpatterns = [
path('admin/', admin.site.urls),
path('my_app1/', include('my_app1.urls'))
]
# urlpatterns = i18n_patterns(
# path('admin/', admin.site.urls), # Here
# path('my_app1/', include('my_app1.urls')) # Here
# )
Then, you set English
as the 1st language in your browser as shown below:

Now, http://localhost:8000/my_app1/
can show Hello World
as shown below:

And, you set French
as the 1st language in your browser as shown below.

Now, http://localhost:8000/my_app1/
can show Bonjour Monde
as shown below:

Lastly, you can easily create i18n switcher following my answer and my answer explaining how to create i18n switcher for Django and Django Admin respectively.