Internationalize Routes¶
Problem¶
The page tree should serve several languages, each under its own URL prefix such as /en/ and /de/, and the in-page text must follow the active language.
Solution¶
The file router mounts as a single include() in the root URLconf.
Wrap that include in i18n_patterns() so Django prepends the language prefix to every routed URL.
Add LocaleMiddleware so the prefix sets the active language, and translate template text with the usual Django i18n tags.
Walkthrough¶
Enable i18n in Settings¶
Turn on translation, list the offered languages, and point at a locale directory.
USE_I18N = True
LANGUAGE_CODE = "en"
LANGUAGES = [
("en", "English"),
("de", "Deutsch"),
]
LOCALE_PATHS = [BASE_DIR / "locale"]
Add the Locale Middleware¶
Place LocaleMiddleware after the session middleware and before CommonMiddleware.
It reads the URL prefix and sets the active language for the request.
MIDDLEWARE = [
"django.middleware.security.SecurityMiddleware",
"django.contrib.sessions.middleware.SessionMiddleware",
"django.middleware.locale.LocaleMiddleware",
"django.middleware.common.CommonMiddleware",
"django.middleware.csrf.CsrfViewMiddleware",
"django.contrib.auth.middleware.AuthenticationMiddleware",
"django.contrib.messages.middleware.MessageMiddleware",
"django.middleware.clickjacking.XFrameOptionsMiddleware",
]
Mount the Router Under a Language Prefix¶
Wrap the file router include in i18n_patterns().
Every routed URL now resolves under /en/ and /de/, and the prefix-free URLs redirect to the active language.
from django.conf.urls.i18n import i18n_patterns
from django.urls import include, path
urlpatterns = i18n_patterns(
path("", include("next.urls")),
)
Keep URLs that must not carry a prefix, such as a health check, in a plain urlpatterns list outside the i18n_patterns call.
Translate In-Page Text¶
Mark template strings with the standard Django i18n tags.
Load the i18n tag library at the top of the template.
The examples below use a separate shop project rather than the Notes project shown elsewhere in the documentation.
{% load i18n %}
<h1>{% translate "Welcome to the shop" %}</h1>
<p>{% blocktranslate %}Browse the catalog below.{% endblocktranslate %}</p>
Translate text built in Python with gettext().
A @context callable returns the already-translated string.
from django.utils.translation import gettext as _
from next.pages import context
@context("heading")
def heading() -> str:
"""Return the localized page heading."""
return _("Featured products")
Compile the Catalogs¶
Extract the marked strings and compile the binary catalogs.
uv run python manage.py makemessages -l de
uv run python manage.py compilemessages
Edit locale/de/LC_MESSAGES/django.po with the German strings before compiling.
Verification¶
Start the server and request the same route under two prefixes.
uv run python manage.py runserver
Visiting /en/ renders the English text and /de/ renders the German text.
A request to the prefix-free URL redirects to the language picked from the request.
Once the router include is wrapped in i18n_patterns, page_reverse returns a URL carrying the active language prefix.
URL names are unchanged.
page_reverse reverses the same next:page_<segments> name, and i18n_patterns applies the active prefix at resolve time.
See Also¶
See also
File Router for how the router include is mounted. Reverse URLs for building prefixed URLs from code.