Supporting internationalization is not optional. It must be a core feature.— Jannis Leidel, Django Under the Hood 2015
Benefits of Internationalization
Enabling internationalization allows you to:- Select a language other than English as the default using Django’s
LANGUAGE_CODEsetting - Allow clients to choose a language using
LocaleMiddlewareand theAccept-Languageheader - Provide localized error messages and validation feedback
- Support multiple languages in your API responses
Enabling Internationalized APIs
Setting the Default Language
Change the default language using Django’s standardLANGUAGE_CODE setting:
en-us- English (United States)es-es- Spanish (Spain)fr-fr- French (France)de-de- German (Germany)pt-br- Portuguese (Brazil)zh-hans- Chinese (Simplified)ja- Japaneseko- Korean
Per-Request Language Selection
Enable per-request language selection by addingLocaleMiddleware to your MIDDLEWARE setting:
LocaleMiddleware should be placed after SessionMiddleware but before CommonMiddleware in the middleware list.Client-Specified Language
WithLocaleMiddleware enabled, clients can specify their preferred language using the Accept-Language header:
Request:
The error message is automatically translated to Spanish based on the
Accept-Language header.Translation Coverage
REST framework includes built-in translations for:- Standard exception messages - HTTP error responses
- Serializer validation errors - Field validation messages
- Authentication errors - Login and permission errors
- Pagination messages - Page navigation text
Error Message Format
Translations apply to error strings themselves, but the structure and field names remain unchanged: English:The keys (
detail, username) remain in English, while the error messages are translated.Customizing Response Keys
To translate response keys likedetail and non_field_errors, use a custom exception handler:
Specifying Supported Languages
By default, all available languages are supported. To restrict to specific languages:Adding New Translations
You may need to add translations locally when:- Using REST Framework in a language not supported by the project
- Adding custom error messages specific to your project
Translating REST Framework Messages
To translate REST framework’s built-in messages to a new language: 1. Create a locale directory:Use locale name notation:
de, pt_BR, es_AR, etc.Translating Custom Error Messages
For custom error messages in your project: 1. Mark strings for translation:Language Detection Order
WhenLocaleMiddleware is enabled, Django determines the language preference in this order:
- URL language prefix -
/es/api/users/ - Session key -
LANGUAGE_SESSION_KEYin session - Cookie - Language preference cookie
- Accept-Language header - HTTP header from client
- Global LANGUAGE_CODE - Default setting
For API Clients
For API clients, the
Accept-Language header is the most appropriate method. Sessions and cookies may not be available unless using session authentication.Language-Specific Content
To serve different content based on language:Testing Translations
Manual Testing
Automated Testing
Available Languages
REST framework includes translations for:- Arabic (ar)
- Chinese Simplified (zh-hans)
- Chinese Traditional (zh-hant)
- Czech (cs)
- Danish (da)
- Dutch (nl)
- English (en)
- Finnish (fi)
- French (fr)
- German (de)
- Hungarian (hu)
- Indonesian (id)
- Italian (it)
- Japanese (ja)
- Korean (ko)
- Norwegian (no)
- Persian (fa)
- Polish (pl)
- Portuguese (pt)
- Portuguese Brazil (pt-br)
- Romanian (ro)
- Russian (ru)
- Slovak (sk)
- Spanish (es)
- Swedish (sv)
- Turkish (tr)
- Ukrainian (uk)
Contributing Translations
To contribute new translations or improve existing ones:- Fork the REST framework repository
- Add or update translation files in
rest_framework/locale/ - Follow the Contributing to REST Framework guidelines
- Submit a pull request
Best Practices
Always Use Lazy Translation
Always Use Lazy Translation
Use
gettext_lazy for strings defined at the module level:Prefer Accept-Language Header for APIs
Prefer Accept-Language Header for APIs
API clients should use the
Accept-Language header rather than URL prefixes or cookies:Test All Supported Languages
Test All Supported Languages
Ensure your API works correctly in all supported languages:
Provide Context for Translators
Provide Context for Translators
Add translator comments to provide context:
Related Resources
- Django Internationalization - Django’s i18n documentation
- Exceptions - Custom exception handlers
- Contributing - Contributing translations to REST framework
