Translates Django models using a registration approach without modifying original model classes.
—
Seamless integration with Django's admin interface for managing multilingual content. Provides admin classes that automatically handle translation fields with proper layout, widgets, and validation.
Admin classes that automatically display translation fields with proper language tabs and field organization.
class TranslationAdmin(admin.ModelAdmin):
"""
ModelAdmin subclass with automatic translation support.
Automatically handles:
- Language-specific field grouping
- Translation field widgets
- Prepopulated fields for translations
- Required field validation per language
"""
class TranslationBaseModelAdmin:
"""
Base admin mixin providing translation functionality.
Can be used with custom admin classes.
"""Usage Example:
from django.contrib import admin
from modeltranslation.admin import TranslationAdmin
from .models import Article
@admin.register(Article)
class ArticleAdmin(TranslationAdmin):
list_display = ('title', 'author', 'created_at')
list_filter = ('author', 'created_at')
search_fields = ('title', 'content')
prepopulated_fields = {'slug': ('title',)} # Works with translationsInline admin classes for handling related model translations within parent model admin.
class TranslationTabularInline(admin.TabularInline):
"""
TabularInline with translation support.
Displays related translations in tabular format.
"""
class TranslationStackedInline(admin.StackedInline):
"""
StackedInline with translation support.
Displays related translations in stacked format.
"""Usage Example:
from modeltranslation.admin import TranslationAdmin, TranslationTabularInline
class CommentInline(TranslationTabularInline):
model = Comment
extra = 1
fields = ('content', 'author')
@admin.register(Article)
class ArticleAdmin(TranslationAdmin):
inlines = [CommentInline]Support for generic foreign key relationships in admin with translation handling.
class TranslationGenericTabularInline(GenericTabularInline):
"""GenericTabularInline with translation support."""
class TranslationGenericStackedInline(GenericStackedInline):
"""GenericStackedInline with translation support."""Usage Example:
from django.contrib.contenttypes.admin import GenericTabularInline
from modeltranslation.admin import TranslationGenericTabularInline
class TagInline(TranslationGenericTabularInline):
model = Tag
extra = 1Translation admin automatically organizes fields by language with intuitive grouping.
Automatic Field Grouping:
# Model with translations
@register(News)
class NewsTranslationOptions(TranslationOptions):
fields = ('title', 'content', 'summary')
# Admin automatically creates language-specific fieldsets:
# - English: title_en, content_en, summary_en
# - French: title_fr, content_fr, summary_fr
# - German: title_de, content_de, summary_de
@admin.register(News)
class NewsAdmin(TranslationAdmin):
# No special configuration needed for basic translation support
passCustom Field Organization:
@admin.register(Article)
class ArticleAdmin(TranslationAdmin):
fieldsets = (
(None, {
'fields': ('title', 'slug', 'author')
}),
('Content', {
'fields': ('content', 'summary'),
'classes': ('collapse',)
}),
('Metadata', {
'fields': ('published', 'created_at'),
'classes': ('collapse',)
})
)
# Translation fields are automatically added to appropriate fieldsetsSpecialized widgets for handling translation-specific input requirements.
class ClearableWidgetWrapper:
"""
Widget wrapper that adds clear functionality for nullable translation fields.
Parameters:
- widget: Base widget to wrap
- empty_value: Value to use when field is cleared (default: None)
"""Usage in Admin:
from modeltranslation.widgets import ClearableWidgetWrapper
from django import forms
class ArticleAdmin(TranslationAdmin):
def formfield_for_dbfield(self, db_field, request, **kwargs):
if db_field.name == 'optional_field':
kwargs['widget'] = ClearableWidgetWrapper(forms.Textarea())
return super().formfield_for_dbfield(db_field, request, **kwargs)Automatic handling of prepopulated fields (like slugs) across all translation languages.
@admin.register(Article)
class ArticleAdmin(TranslationAdmin):
prepopulated_fields = {'slug': ('title',)}
# Automatically creates:
# - slug_en from title_en
# - slug_fr from title_fr
# - slug_de from title_deConfigure required fields and validation per language.
@register(Product)
class ProductTranslationOptions(TranslationOptions):
fields = ('name', 'description')
required_languages = ('en', 'fr') # English and French are required
@admin.register(Product)
class ProductAdmin(TranslationAdmin):
# Admin automatically enforces required language validation
passTranslation-aware field filtering and search functionality.
@admin.register(Article)
class ArticleAdmin(TranslationAdmin):
list_display = ('title', 'author', 'created_at')
list_filter = ('author', 'created_at', 'category')
search_fields = ('title', 'content') # Searches across all language versions
def get_search_results(self, request, queryset, search_term):
# Custom search logic can access all translation fields
return super().get_search_results(request, queryset, search_term)Translation admin includes specialized JavaScript and CSS for enhanced user experience.
Built-in Assets:
# Assets are automatically included, but can be customized:
class CustomTranslationAdmin(TranslationAdmin):
class Media:
js = TranslationAdmin.Media.js + ('custom_translation.js',)
css = {
'all': TranslationAdmin.Media.css['all'] + ('custom_translation.css',)
}Combine translation admin with other admin mixins and functionality.
from django.contrib.admin import ModelAdmin
from modeltranslation.admin import TranslationBaseModelAdmin
from some_package.admin import SomeAdminMixin
class CustomArticleAdmin(SomeAdminMixin, TranslationBaseModelAdmin, ModelAdmin):
# Combines functionality from multiple admin classes
passShow/hide translation fields based on conditions.
class ConditionalTranslationAdmin(TranslationAdmin):
def get_fieldsets(self, request, obj=None):
fieldsets = super().get_fieldsets(request, obj)
# Modify fieldsets based on user permissions or object state
if not request.user.has_perm('myapp.change_advanced_fields'):
# Remove advanced translation fields
pass
return fieldsetsAdmin actions for bulk translation operations.
def copy_translation(modeladmin, request, queryset):
"""Copy content from default language to other languages."""
for obj in queryset:
# Bulk translation logic
pass
copy_translation.short_description = "Copy to all languages"
class ArticleAdmin(TranslationAdmin):
actions = [copy_translation]Custom validation for translation forms.
from django import forms
from modeltranslation.forms import TranslationModelForm
class ArticleTranslationForm(TranslationModelForm):
class Meta:
model = Article
fields = '__all__'
def clean(self):
cleaned_data = super().clean()
# Custom validation across translation fields
title_en = cleaned_data.get('title_en')
title_fr = cleaned_data.get('title_fr')
if title_en and not title_fr:
raise forms.ValidationError(
"French title is required when English title is provided"
)
return cleaned_data
class ArticleAdmin(TranslationAdmin):
form = ArticleTranslationFormInstall with Tessl CLI
npx tessl i tessl/pypi-django-modeltranslation