Admin Reference

This page documents the Django admin integration components.

LocalizedFieldsAdmin

class LocalizedFieldsAdmin

Base admin class for models with localized fields. Combines LocalizedFieldsAdminMixin with admin.ModelAdmin.

Usage:

from i18n_fields import LocalizedFieldsAdmin
from .models import Article

@admin.register(Article)
class ArticleAdmin(LocalizedFieldsAdmin):
    list_display = ['title', 'created_at']

Features:

  • All features of LocalizedFieldsAdminMixin

  • No need to explicitly extend admin.ModelAdmin

  • Cleaner, more concise syntax

  • Full type safety with Generic types

When to Use:

Use LocalizedFieldsAdmin when you don’t need to combine with other admin base classes. For multiple inheritance scenarios, use LocalizedFieldsAdminMixin instead.

LocalizedFieldsAdminMixin

class LocalizedFieldsAdminMixin

Mixin for Django admin that enables localized field widgets and proper display.

Usage:

from django.contrib import admin
from i18n_fields import LocalizedFieldsAdminMixin
from .models import Article

@admin.register(Article)
class ArticleAdmin(LocalizedFieldsAdminMixin, admin.ModelAdmin):
    list_display = ['title', 'created_at']

Features:

  • Automatic widget selection for localized fields

  • Tab or dropdown language switchers

  • Proper display in list_display

  • Read-only field support

  • Works with inlines

Attributes:

localized_fields_display

Display mode for localized fields: "tab" or "dropdown"

Default: None (uses I18N_FIELDS["DISPLAY"] setting)

Example:

class ArticleAdmin(LocalizedFieldsAdminMixin, admin.ModelAdmin):
    localized_fields_display = 'dropdown'

Methods:

formfield_for_dbfield(db_field, request, **kwargs)

Override to use localized field widgets.

Parameters:

  • db_field: The database field

  • request: The HTTP request

  • **kwargs: Additional arguments

Returns: Form field with appropriate widget

get_fieldsets(request, obj=None)

Get fieldsets with localized readonly field names replaced.

Parameters:

  • request: The HTTP request

  • obj: The model instance (None for add view)

Returns: List of fieldsets

Class Attributes:

Media

Media class that includes required CSS and JavaScript files.

CSS:

  • i18n_fields/i18n-fields-admin.css

JavaScript:

  • admin/js/jquery.init.js

  • i18n_fields/i18n-fields-admin.js

  • i18n_fields/js/martor_tabs.js (included automatically when martor is installed)

Display Modes

Tab Mode

Shows language tabs above each field.

Configuration:

class ArticleAdmin(LocalizedFieldsAdminMixin, admin.ModelAdmin):
    localized_fields_display = 'tab'

Features:

  • Horizontal tabs for each language

  • Active tab highlighted

  • Easy switching between languages

  • Best for 2-6 languages

Visual Structure:

┌─────────┬─────────┬─────────┐
│ English │ Spanish │ French  │  ← Tabs
└─────────┴─────────┴─────────┘
┌─────────────────────────────┐
│ Field content in English... │  ← Content
└─────────────────────────────┘

Widgets

AdminLocalizedFieldWidget

class AdminLocalizedFieldWidget(display_mode='tab')

Base widget for localized fields in admin.

Parameters:

  • display_mode (str): "tab" or "dropdown"

Used For: Base LocalizedField

AdminLocalizedCharFieldWidget

class AdminLocalizedCharFieldWidget(display_mode='tab')

Widget for LocalizedCharField with text input.

Inherits From: AdminLocalizedFieldWidget

HTML Input: <input type="text">

AdminLocalizedIntegerFieldWidget

class AdminLocalizedIntegerFieldWidget(display_mode='tab')

Widget for LocalizedIntegerField with number input.

HTML Input: <input type="number">

AdminLocalizedFloatFieldWidget

class AdminLocalizedFloatFieldWidget(display_mode='tab')

Widget for LocalizedFloatField with number input.

HTML Input: <input type="number" step="any">

AdminLocalizedBooleanFieldWidget

class AdminLocalizedBooleanFieldWidget(display_mode='tab')

Widget for LocalizedBooleanField with checkbox.

HTML Input: <input type="checkbox">

AdminLocalizedFileFieldWidget

class AdminLocalizedFileFieldWidget(display_mode='tab')

Widget for LocalizedFileField with file input.

HTML Input: <input type="file">

Features:

  • Shows current file

  • Clear checkbox

  • Upload new file

AdminLocalizedMartorWidget

class AdminLocalizedMartorWidget(display_mode='tab')

Widget for LocalizedMartorField with Markdown editor.

Requires: martor package installed

Features:

  • Full Markdown editor with toolbar (bold, italic, links, images, etc.)

  • Live preview support

  • Syntax highlighting

  • Emoji and mention support (configurable via martor settings)

  • Works with both tab and dropdown display modes

List Display

Localized fields in list_display automatically show translated values.

Example:

@admin.register(Article)
class ArticleAdmin(LocalizedFieldsAdminMixin, admin.ModelAdmin):
    list_display = ['title', 'author', 'created_at']

Behavior:

  • Shows value in active language

  • Falls back to primary language if active language unavailable

  • Shows “-” if no value available

Custom Display:

class ArticleAdmin(LocalizedFieldsAdminMixin, admin.ModelAdmin):
    list_display = ['custom_title', 'created_at']

    def custom_title(self, obj):
        return f"{obj.title} (ID: {obj.id})"
    custom_title.short_description = 'Title'

Readonly Fields

Read-only localized fields show all translations.

Example:

@admin.register(Article)
class ArticleAdmin(LocalizedFieldsAdminMixin, admin.ModelAdmin):
    readonly_fields = ['slug', 'created_at']
    fields = ['title', 'slug', 'content', 'created_at']

Behavior:

  • Shows tab or dropdown interface (based on localized_fields_display)

  • All translations visible but not editable

  • Respects display mode setting

Inline Admin

Use with inline admin classes:

TabularInline:

class ChapterInline(LocalizedFieldsAdminMixin, admin.TabularInline):
    model = Chapter
    fields = ['title', 'order']
    extra = 1

@admin.register(Book)
class BookAdmin(LocalizedFieldsAdminMixin, admin.ModelAdmin):
    inlines = [ChapterInline]

StackedInline:

class ChapterInline(LocalizedFieldsAdminMixin, admin.StackedInline):
    model = Chapter
    fields = ['title', 'content', 'order']
    extra = 0

Behavior:

  • Each inline row has localized field widgets

  • Same display mode as parent admin

  • Works with TabularInline and StackedInline

Fieldsets

Organize localized fields in fieldsets:

Example:

@admin.register(Article)
class ArticleAdmin(LocalizedFieldsAdminMixin, admin.ModelAdmin):
    fieldsets = [
        ('Content', {
            'fields': ['title', 'slug', 'content']
        }),
        ('Metadata', {
            'fields': ['author', 'published', 'created_at'],
            'classes': ['collapse']
        }),
    ]

Features:

  • Localized fields work in any fieldset

  • Support for classes (e.g., collapse, wide)

  • Support for description

Filtering

Custom Filters

Create custom filters for localized fields:

from django.contrib import admin

class TitleLanguageFilter(admin.SimpleListFilter):
    title = 'title language availability'
    parameter_name = 'title_lang'

    def lookups(self, request, model_admin):
        return [
            ('en', 'Has English'),
            ('es', 'Has Spanish'),
            ('fr', 'Has French'),
        ]

    def queryset(self, request, queryset):
        if self.value() == 'en':
            return queryset.filter(title__en__isnull=False)
        if self.value() == 'es':
            return queryset.filter(title__es__isnull=False)
        if self.value() == 'fr':
            return queryset.filter(title__fr__isnull=False)

@admin.register(Article)
class ArticleAdmin(LocalizedFieldsAdminMixin, admin.ModelAdmin):
    list_filter = [TitleLanguageFilter, 'published']

Ordering

Order by localized fields:

Example:

from i18n_fields import L

@admin.register(Article)
class ArticleAdmin(LocalizedFieldsAdminMixin, admin.ModelAdmin):
    def get_queryset(self, request):
        qs = super().get_queryset(request)
        # Order by title in current language
        return qs.order_by(L('title'))

    # Alternative: Order by specific language
    def get_queryset(self, request):
        qs = super().get_queryset(request)
        return qs.order_by(L('title', 'en'))

Actions

Admin actions work with localized fields:

Example:

@admin.register(Article)
class ArticleAdmin(LocalizedFieldsAdminMixin, admin.ModelAdmin):
    actions = ['duplicate_to_spanish']

    def duplicate_to_spanish(self, request, queryset):
        for article in queryset:
            title = article.title
            if title.get('en') and not title.get('es'):
                # Copy English to Spanish
                title.set('es', title.get('en'))
                article.title = title
                article.save()

        self.message_user(
            request,
            f'{queryset.count()} articles updated'
        )
    duplicate_to_spanish.short_description = 'Duplicate EN to ES'

Customization

Custom Widgets

Override widgets for specific fields:

from i18n_fields.widgets import AdminLocalizedFieldWidget

@admin.register(Article)
class ArticleAdmin(LocalizedFieldsAdminMixin, admin.ModelAdmin):
    def formfield_for_dbfield(self, db_field, request, **kwargs):
        if db_field.name == 'title':
            kwargs['widget'] = AdminLocalizedFieldWidget(
                display_mode='dropdown'
            )
        return super().formfield_for_dbfield(db_field, request, **kwargs)

Custom CSS

Add custom styling:

@admin.register(Article)
class ArticleAdmin(LocalizedFieldsAdminMixin, admin.ModelAdmin):
    class Media:
        css = {
            'all': ('css/custom_i18n_admin.css',)
        }
/* static/css/custom_i18n_admin.css */
.i18n-tab {
    padding: 10px 20px;
    font-weight: bold;
}

.i18n-tab.active {
    background-color: #0066cc;
    color: white;
}

Best Practices

  1. Use LocalizedFieldsAdmin or LocalizedFieldsAdminMixin

    Always use one of these for proper widget support:

    # Best - using base class
    class ArticleAdmin(LocalizedFieldsAdmin):
        pass
    
    # Good - using mixin
    class ArticleAdmin(LocalizedFieldsAdminMixin, admin.ModelAdmin):
        pass
    
    # Missing features - don't do this
    class ArticleAdmin(admin.ModelAdmin):
        pass
    
  2. Choose Appropriate Display Mode

    • Tab mode: Best for 2-6 languages

    • Dropdown mode: Best for 7+ languages

  3. Include in list_display

    Show localized fields in list view:

    list_display = ['title', 'created_at', 'published']
    
  4. Use Language-Specific Search

    Specify languages in search_fields:

    search_fields = ['title__en', 'title__es', 'content__en']
    
  5. Order Explicitly

    Use L() for consistent ordering:

    def get_queryset(self, request):
        return super().get_queryset(request).order_by(L('title', 'en'))
    

Troubleshooting

Widgets Not Showing

Problem: Localized field widgets not appearing

Solution:

  1. Ensure mixin is included and comes first:

    class ArticleAdmin(LocalizedFieldsAdminMixin, admin.ModelAdmin):
        pass
    
  2. Check static files are collected:

    python manage.py collectstatic
    

JavaScript Not Working

Problem: Tabs/dropdowns not switching

Solution:

  1. Check browser console for errors

  2. Ensure jQuery is loaded (required by Django admin)

  3. Clear browser cache

Readonly Fields Not Displaying

Problem: Readonly localized fields showing as plain text

Solution:

Ensure the mixin is included - it handles readonly field display automatically.

See Also