CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-django-modeltranslation

Translates Django models using a registration approach without modifying original model classes.

Pending
Overview
Eval results
Files

query-interface.mddocs/

Query Interface

Multilingual managers and querysets that automatically handle language-specific database queries, field lookups, and provide fallback functionality for missing translations.

Capabilities

Multilingual Manager

Custom manager that automatically rewrites queries to use appropriate translation fields based on the current language.

class MultilingualManager(models.Manager):
    """
    Manager for multilingual models that handles language-aware queries.
    
    Automatically:
    - Rewrites field lookups to use current language fields
    - Handles fallback languages for queries
    - Manages related model query rewriting
    """
    
    def get_queryset(self):
        """Return queryset with translation field rewriting."""
    
    def filter(self, *args, **kwargs):
        """Filter with automatic translation field rewriting."""
    
    def exclude(self, *args, **kwargs):
        """Exclude with automatic translation field rewriting."""
    
    def order_by(self, *field_names):
        """Order by with translation field rewriting."""

Usage Example:

from modeltranslation.manager import MultilingualManager

class Article(models.Model):
    title = models.CharField(max_length=255)
    content = models.TextField()
    
    objects = MultilingualManager()

# Queries automatically use current language
articles = Article.objects.filter(title__icontains='django')
# Becomes: filter(title_en__icontains='django') if current language is 'en'

articles = Article.objects.order_by('title')
# Becomes: order_by('title_en') if current language is 'en'

Multilingual QuerySet

QuerySet that provides language-aware query operations and fallback handling.

class MultilingualQuerySet(models.QuerySet):
    """
    QuerySet with automatic translation field handling.
    
    Features:
    - Language-aware field lookups
    - Fallback language support
    - Translation field aggregation
    """
    
    def filter(self, *args, **kwargs):
        """Filter with translation field rewriting."""
    
    def exclude(self, *args, **kwargs):
        """Exclude with translation field rewriting."""
    
    def order_by(self, *field_names):
        """Order with translation field rewriting."""
    
    def values(self, *fields):
        """Values with translation and fallback field inclusion."""
    
    def values_list(self, *fields, **kwargs):
        """Values list with translation field handling."""

Combined Manager/QuerySet

Manager that provides both manager and queryset functionality in one class.

class MultilingualQuerysetManager(MultilingualManager):
    """
    Combined manager/queryset providing both manager and queryset methods.
    Enables method chaining while maintaining translation functionality.
    """
    
    def get_queryset(self):
        """Return MultilingualQuerySet instance."""
    
    # Inherits all QuerySet methods for chaining

Usage Example:

class Article(models.Model):
    title = models.CharField(max_length=255)
    content = models.TextField()
    published = models.BooleanField(default=False)
    
    objects = MultilingualQuerysetManager.from_queryset(MultilingualQuerySet)()

# Method chaining with translation support
recent_articles = (Article.objects
                  .filter(published=True)
                  .filter(title__icontains='django')
                  .order_by('-created_at')[:10])

Field Lookup Rewriting

Automatic rewriting of field lookups to use appropriate translation fields.

def rewrite_lookup_key(model, lookup_key):
    """
    Rewrite field lookup keys to use translation fields.
    
    Parameters:
    - model: Model class being queried
    - lookup_key: Original lookup key (e.g., 'title__icontains')
    
    Returns:
    - str: Rewritten lookup key (e.g., 'title_en__icontains')
    """

def get_translatable_fields_for_model(model):
    """
    Get list of translatable field names for a model.
    
    Parameters:
    - model: Model class
    
    Returns:
    - list: Field names that are translatable, or None if not registered
    """

Lookup Rewriting Examples:

# Simple field lookups
Article.objects.filter(title='Django')
# → filter(title_en='Django')

# Complex lookups with field transforms
Article.objects.filter(title__icontains='django', content__startswith='This')
# → filter(title_en__icontains='django', content_en__startswith='This')

# Related field lookups
Article.objects.filter(category__name='Technology')
# → filter(category__name_en='Technology') if Category.name is translatable

# Date/numeric fields work normally
Article.objects.filter(created_at__gte=date.today())
# → No rewriting needed for non-translatable fields

Fallback Field Handling

Automatic inclusion of fallback language fields in queries and values.

def append_fallback(model, fields):
    """
    Add fallback language fields to field list.
    
    Parameters:
    - model: Model class
    - fields: Sequence of field names
    
    Returns:
    - tuple: (expanded_fields_set, translated_field_names_set)
    """

def append_translated(model, fields):
    """
    Add all translation fields for given field names.
    
    Parameters:
    - model: Model class  
    - fields: Iterable of field names
    
    Returns:
    - set: All translation field names for given fields
    """

Fallback Usage:

# When querying values, fallback fields are automatically included
articles = Article.objects.values('title', 'content')

# If current language is 'fr' with fallback to 'en', this becomes:
# values('title_fr', 'title_en', 'content_fr', 'content_en')

# The model instance will show the French value if available, 
# otherwise the English fallback

Language-Aware Aggregation

Aggregation functions that work with translation fields and fallbacks.

from django.db.models import Count, Q
from modeltranslation.utils import get_language

# Count articles with non-empty titles in current language
current_lang = get_language()
Article.objects.aggregate(
    count=Count('id', filter=Q(**{f'title_{current_lang}__isnull': False}))
)

# Aggregate across all languages
from modeltranslation.settings import AVAILABLE_LANGUAGES

for lang in AVAILABLE_LANGUAGES:
    count = Article.objects.filter(**{f'title_{lang}__isnull': False}).count()
    print(f"Articles with {lang} title: {count}")

Custom QuerySet Methods

Extend querysets with translation-specific methods.

class ArticleQuerySet(MultilingualQuerySet):
    def published(self):
        """Filter for published articles."""
        return self.filter(published=True)
    
    def with_translation(self, language=None):
        """Filter articles that have translation in specified language."""
        from modeltranslation.utils import get_language
        lang = language or get_language()
        
        # Get translatable fields for this model
        from modeltranslation.translator import translator
        opts = translator.get_options_for_model(self.model)
        
        # Create filter conditions for non-empty translation fields
        conditions = Q()
        for field_name in opts.fields:
            field_lookup = f"{field_name}_{lang}__isnull"
            conditions &= ~Q(**{field_lookup: True})
        
        return self.filter(conditions)
    
    def missing_translation(self, language=None):
        """Filter articles missing translation in specified language."""
        from modeltranslation.utils import get_language
        lang = language or get_language()
        
        from modeltranslation.translator import translator
        opts = translator.get_options_for_model(self.model)
        
        conditions = Q()
        for field_name in opts.fields:
            field_lookup = f"{field_name}_{lang}__isnull"
            conditions |= Q(**{field_lookup: True})
        
        return self.filter(conditions)

class Article(models.Model):
    title = models.CharField(max_length=255)
    content = models.TextField()
    published = models.BooleanField(default=False)
    
    objects = MultilingualQuerysetManager.from_queryset(ArticleQuerySet)()

# Usage
published_with_french = Article.objects.published().with_translation('fr')
missing_german = Article.objects.missing_translation('de')

Related Model Queries

Handle translation fields in related model queries and joins.

# Related model lookups are automatically rewritten
Article.objects.filter(category__name='Technology')
# If Category.name is translatable:
# → filter(category__name_en='Technology')

# Prefetch related with translations
Article.objects.prefetch_related('category').filter(title__icontains='django')

# Select related with translation fields
Article.objects.select_related('category').values('title', 'category__name')
# Automatically includes appropriate translation fields

Advanced Usage

Custom Field Resolution

Override field resolution for complex translation scenarios.

class CustomMultilingualQuerySet(MultilingualQuerySet):
    def _rewrite_filter_args(self, *args, **kwargs):
        """Custom logic for rewriting filter arguments."""
        # Custom field resolution logic
        return super()._rewrite_filter_args(*args, **kwargs)

Performance Optimization

Optimize queries for large datasets with translations.

# Use only() and defer() with translation fields
Article.objects.only('title_en', 'title_fr').filter(published=True)

# Defer translation fields not needed immediately  
Article.objects.defer('content_de', 'content_es').filter(category__name='Tech')

# Use select_related for foreign key translations
Article.objects.select_related('category').filter(title__icontains='django')

Raw SQL with Translations

Handle raw SQL queries with translation field names.

from modeltranslation.utils import build_localized_fieldname, get_language

current_lang = get_language()
title_field = build_localized_fieldname('title', current_lang)

# Raw query with dynamic field names
Article.objects.extra(
    where=[f"{title_field} ILIKE %s"],
    params=['%django%']
)

Bulk Operations

Bulk create, update, and delete operations with translation fields.

# Bulk create with translation fields
articles = [
    Article(title_en='English Title', title_fr='Titre Français'),
    Article(title_en='Another Title', title_fr='Autre Titre'),
]
Article.objects.bulk_create(articles)

# Bulk update translation fields
Article.objects.filter(category_id=1).update(
    title_fr='Nouveau Titre',
    content_fr='Nouveau contenu'
)

Install with Tessl CLI

npx tessl i tessl/pypi-django-modeltranslation

docs

admin-integration.md

core-registration.md

field-management.md

forms-integration.md

index.md

query-interface.md

utils-configuration.md

tile.json