Internalization¶
django-modern-rest supports optional i18n feature
which is provided by the Django itself.
Docs: https://docs.djangoproject.com/en/stable/topics/i18n/
Note
If no configuration is specified, we default to en-us locale.
If you just want to use the default language, you don’t have to do anything.
Core features:
Setting default language for everything with a single LANGUAGE_CODE configuration variable
Using
django.middleware.locale.LocaleMiddlewareto set language per-request based onAccept-Languageheader
Enabling translated API messages¶
Note
See full list of the supported languages here.
Setting the default language code for all users:
LANGUAGE_CODE = 'ru-ru'
Setting the language code per request:
MIDDLEWARE = [
# ...
'django.middleware.locale.LocaleMiddleware',
]
Then any requests with Accept-Language header will set
the required language for this specific response.
1from dmr import Controller, ResponseSpec
2from dmr.exceptions import NotAuthenticatedError
3from dmr.plugins.pydantic import PydanticSerializer
4
5
6class UsersController(Controller[PydanticSerializer]):
7 responses = (
8 ResponseSpec(
9 Controller.error_model,
10 status_code=NotAuthenticatedError.status_code,
11 ),
12 )
13
14 def post(self) -> dict[str, str]:
15 assert self.request.LANGUAGE_CODE == 'ru'
16 raise NotAuthenticatedError # demo for the custom error translation
17
Run result
$ curl http://127.0.0.1:8000/api/lang/ -X POST -H 'Accept-Language: ru'
{"detail":[{"msg":"Не аутентифицирован","type":"security"}]}
Specifying the list of the supported languages:
from django.utils.translation import gettext_lazy as _
LANGUAGES = [
('ru', _('Russian')),
('en', _('English')),
]
Important
Whenever you use Django’s built-in translation feature, don’t forget to run compilemessages management command before using the translations.
Enabling translation for type validation¶
Since we are using pydantic and msgspec directly
to handle all type validation and schema checks, their messages
won’t be affected by the Django’s i18n settings.
If you want to translate their messages as well, use their own docs:
For
pydantic: https://github.com/boardpack/pydantic-i18nFor
msgspecone can use Babel directly to translate their error messages manually
You can customize
dmr.serializer.BaseSerializer.serialize_validation_error()
on the serializer that needs the validation errors to be translated.
Or you can change dmr.controller.Controller.format_error() method
to translate messages there.
Forcing constant API language¶
If you have a website using some non-English LANGUAGE_CODE
and you want to add an API that will always use
1from collections.abc import Callable
2
3from django.http import HttpRequest, HttpResponse
4from django.utils import translation
5
6
7class ForceEnglishForAPI:
8 def __init__(
9 self,
10 get_response: Callable[[HttpRequest], HttpResponse],
11 ) -> None:
12 self.get_response = get_response
13
14 def __call__(self, request: HttpRequest) -> HttpResponse:
15 # You can use `router.prefix` here instead:
16 if request.path.startswith('/api/'):
17 # You can configure this to be
18 # `settings.API_LANGUAGE_CODE`
19 # and set `API_LANGUAGE_CODE = 'en-us'` in your settings file.
20 translation.activate('en-us') # or any other language
21 # Or just run: `request.META.pop('HTTP_ACCEPT_LANGUAGE', None)`
22 return self.get_response(request)
And then add it to your MIDDLEWARE setting:
MIDDLEWARE = [
# ...
'path.to.ForceEnglishForAPI',
# ...
]
Adding local translations¶
If you are using a language that is not supported by django-modern-rest
natively, you can translate them right in your own local project.
Here’s how to do it:
Create a directory called
locale/inside your project and add it to LOCALE_PATHS setting insettings.pyCreate a language directory inside
locale/, for example:locale/pt-br/, with the locale name that you want to support. See ISO 639 for the list of the language codesTake the initial translation template from our repository
Fill in the translations
Run
python manage.py compilemessages -l pt-br, wherept-bris the locale you want to supportRestart your development server with
python manage.py runserver, if you want to see the changes
Please, contribute your translation back to django-modern-rest!
It would be a good addition to the library.