Translations¶
Messages that reach API clients are translated with Django's gettext, in the language
Django activates for the request (LocaleMiddleware, Accept-Language,
translation.override). That covers permission denials, domain errors, validation messages
from pagination, shaping, bulk and import, and contrib responses. ninja-devx ships English
defaults and no catalog; add a catalog for each language you support.
MIDDLEWARE = [..., "django.middleware.locale.LocaleMiddleware", ...]
LANGUAGES = [("en", "English")]
Your own messages¶
-
Permissions.
messageis looked up withgettextwhen the denial is sent, so mark it for extraction and translate it in your project's catalog: -
Domain errors.
default_messageworks the same way. A message passed explicitly (NotFound(_("Order %(id)s is gone") % {...})) is used as it is, so translate it where you raise it. - Ninja's own responses ("Unauthorized", "Not Found" for
Http404) come from Ninja and are not translated.
Adding a language¶
Catalogs live in src/ninja_devx/locale/<language>/LC_MESSAGES/. They are managed without
GNU gettext:
uv run python tools/messages.py --language de # creates django.po + django.mo
# fill the msgstr lines, run it again, and check:
uv run python tools/messages.py --check # discovers existing catalogs and verifies them
--language is repeatable. Without it, tools/messages.py updates the catalogs that
already exist; --check fails on stale or untranslated ones.
For an application's own strings, use Django's standard makemessages/compilemessages
and point LOCALE_PATHS at your project's locale directory. The messages the package
translates are listed in the settings guide and the
errors reference.