Enable multi-language support in Django Unfold admin with language switching, internationalization configuration, custom language lists, and i18n URL patterns for a fully localized admin interface.
Django Unfold provides built-in support for multi-language admin interfaces. Enable language switching to allow users to view the admin interface in their preferred language.
The language switcher appears in the top-right corner of the admin interface, allowing users to quickly switch between available languages. Once enabled, the admin interface will be fully localized based on the selected language.
Add the locale middleware to handle language selection.
settings.py
MIDDLEWARE = [ "django.middleware.security.SecurityMiddleware", "django.contrib.sessions.middleware.SessionMiddleware", "django.middleware.locale.LocaleMiddleware", # Add this line "django.middleware.common.CommonMiddleware", # ... other middleware]
3
Configure URL Patterns
Set up i18n URL patterns for language-specific URLs.
urls.py
from django.conf.urls.i18n import i18n_patternsfrom django.urls import include, pathurlpatterns = [ # This is required for the language selector to work path("i18n/", include("django.conf.urls.i18n")),] + i18n_patterns( path("admin/", admin.site.urls), # ... other patterns)
The path("i18n/", include("django.conf.urls.i18n")) line must be outside the i18n_patterns() block. This provides the endpoint for language switching.
Use a callback function to generate the language list dynamically:
settings.py
from django.utils.translation import gettext_lazy as _UNFOLD = { "SHOW_LANGUAGES": True, "LANGUAGES": { "navigation": "app.utils.get_languages", },}
utils.py
from django.utils.translation import get_language_infodef get_languages(request): """ Return list of available languages. Args: request: The current HTTP request Returns: list: List of language dictionaries """ # Define which languages to show language_codes = ["en", "de", "fr", "es"] # Generate language info using Django's helper return [get_language_info(code) for code in language_codes]
Show different languages based on user permissions:
utils.py
from django.utils.translation import get_language_infodef get_languages(request): """ Return languages based on user permissions. """ # Base languages available to all users languages = ["en"] # Add additional languages for staff if request.user.is_staff: languages.extend(["de", "fr"]) # Add all languages for superusers if request.user.is_superuser: languages.extend(["es", "it", "pt", "ja", "zh-hans"]) return [get_language_info(code) for code in languages]
from django.conf import settingsfrom django.http import HttpResponseRedirectfrom django.utils import translationfrom django.views.decorators.http import require_POST@require_POSTdef custom_language_switch(request): """ Custom language switching with logging. """ language = request.POST.get('language') if language and language in dict(settings.LANGUAGES): # Activate the language translation.activate(language) request.session[translation.LANGUAGE_SESSION_KEY] = language # Log the language change logger.info(f"User {request.user} switched to language: {language}") # Redirect back to the previous page return HttpResponseRedirect(request.META.get('HTTP_REFERER', '/'))
from django.utils import translationclass RegionLanguageMiddleware: def __init__(self, get_response): self.get_response = get_response def __call__(self, request): if not request.session.get(translation.LANGUAGE_SESSION_KEY): # Detect region from IP or other method region = self.detect_region(request) # Map regions to languages region_language_map = { 'US': 'en', 'GB': 'en', 'DE': 'de', 'FR': 'fr', 'ES': 'es', } language = region_language_map.get(region, 'en') translation.activate(language) request.session[translation.LANGUAGE_SESSION_KEY] = language return self.get_response(request) def detect_region(self, request): # Implement region detection logic return 'US'
Implement graceful fallback for unsupported languages:
utils.py
from django.conf import settingsfrom django.utils.translation import get_language_infodef get_languages(request): """ Return languages with fallback support. """ try: # Try to get user's preferred languages from profile if hasattr(request.user, 'profile'): language_codes = request.user.profile.available_languages else: # Fallback to all configured languages language_codes = [code for code, name in settings.LANGUAGES] return [get_language_info(code) for code in language_codes] except Exception as e: # If anything fails, return English only logger.error(f"Error loading languages: {e}") return [get_language_info('en')]
Always display language names in their native language for better user experience.
# Good - native names{"code": "de", "name_local": "Deutsch"}{"code": "fr", "name_local": "Français"}# Less optimal - English names only{"code": "de", "name_local": "German"}{"code": "fr", "name_local": "French"}
Test RTL Languages
If supporting right-to-left languages (Arabic, Hebrew), test thoroughly.
LANGUAGES = ( ("en", _("English")), ("ar", _("Arabic")), # RTL language ("he", _("Hebrew")), # RTL language)
Provide Fallback
Always include a fallback language in case of errors.
def get_languages(request): try: return get_user_languages(request) except Exception: # Fallback to English return [get_language_info('en')]
Cache Language Info
Cache language information to avoid repeated processing.
from django.core.cache import cachedef get_languages(request): cache_key = f'languages_{request.user.id}' languages = cache.get(cache_key) if languages is None: languages = [ get_language_info(code) for code in get_available_languages(request) ] cache.set(cache_key, languages, 3600) # Cache for 1 hour return languages