Backend

Internationalization

Error messages and emails in the user's language: English, Italian and Spanish ship with the package.

Every human string in pleate-backend goes through Django's gettext: error messages, validation messages, email subjects and bodies. The package ships catalogs for English (the source), Italian and Spanish. Error codes never change with the language, so the frontend can switch on them or use its own wording.

How the language is picked

pleate_backend.core.middleware.LocaleMiddleware picks, in order:

SourceSet by
locale cookieYour language switcher, or PATCH /auth/me with locale, which sets it for a year.
user.localeSaved at signup (from the request) or in the profile. Copied to the cookie on the next response.
Accept-LanguageThe browser, or the client's locale option.

Only languages in LANGUAGES are accepted; anything else falls back to LANGUAGE_CODE. Responses say which language was used in Content-Language.

http
POST /api/auth/login
Accept-Language: it

HTTP/1.1 400 Bad Request
Content-Language: it

{"error": {"status": 400, "code": "invalid_credentials", "message": "Email o password sbagliate."}}

Emails

Emails are rendered in the recipient's language, not the language of whoever triggered them: user.locale when it is set, else the language of the current request. A staff member writing in English sends an Italian user an Italian reset email. Pass language= to send_email for your own emails.

From the frontend

tsx
// Follow the app's current locale on every request
<PleateProvider options={{ baseUrl: "/api", locale: () => document.documentElement.lang }}>

// Or remember the choice on the account (also sets the locale cookie)
const update = useUpdateMe();
update.mutate({ locale: "es" });

useSignup sends locale when you pass it, so the verification email of a new account is already in the right language.

Adding a language

  • Add it to LANGUAGES in your settings.
  • Create a catalog for pleate's strings in one of your LOCALE_PATHS: copy pleate_backend/locale/it/LC_MESSAGES/django.po as a template, translate the msgstrs and compile.
  • Translate your own strings as usual with makemessages.
settings.py
from pleate_backend.settings import LANGUAGES, LOCALE_PATHS

LANGUAGES = [*LANGUAGES, ("fr", "Français")]
LOCALE_PATHS = [BASE_DIR / "locale", *LOCALE_PATHS]   # yours first, they win
sh
python manage.py makemessages -l fr
python manage.py compilemessages

Writing translatable code

  • Use gettext in views and gettext_lazy at import time (serializer fields, model fields, class attributes).
  • Raise errors with a stable code and a translated message: ApiError("out_of_stock", _("This product is sold out."), 409).
  • In templates, {% load i18n %} then {% translate %} and {% blocktranslate %}.
  • Write English source strings; keep placeholders named (%(email)s) so translators can reorder them.