Translates Django models using a registration approach without modifying original model classes.
—
The foundation of django-modeltranslation's translation system. Provides decorators and classes for registering Django models to enable field translation without modifying original model definitions.
Register Django models for translation using the decorator pattern, similar to Django's admin registration.
def register(model_or_iterable, **options):
"""
Decorator for registering model(s) with translation options.
Parameters:
- model_or_iterable: Model class or iterable of model classes
- **options: Additional registration options
Returns:
- Decorator function that accepts TranslationOptions subclass
Raises:
- AlreadyRegistered: If model is already registered
- DescendantRegistered: If descendant model is already registered
"""Usage Example:
from modeltranslation.translator import register, TranslationOptions
from myapp.models import Article, Category
@register(Article)
class ArticleTranslationOptions(TranslationOptions):
fields = ('title', 'content', 'summary')
# Register multiple models at once
@register([Category, Article])
class MultipleTranslationOptions(TranslationOptions):
fields = ('name', 'description')Base class for defining which fields should be translatable and configuring translation behavior.
class TranslationOptions:
"""Base class for defining translation field options."""
fields: tuple = ()
"""Tuple of field names to make translatable."""
empty_values: dict | None = None
"""Dict mapping field names to empty values."""
required_languages: tuple | None = None
"""Languages required for these fields."""
fallback_languages: dict | None = None
"""Custom fallback languages for these fields."""
fallback_values: str | None = None
"""Fallback value handling strategy."""
fallback_undefined: str | None = None
"""Handling for undefined fallback values."""Configuration Options:
@register(News)
class NewsTranslationOptions(TranslationOptions):
fields = ('title', 'content')
empty_values = {
'title': 'both', # Allow both None and empty string
'content': '' # Only empty string is considered empty
}
required_languages = ('en', 'fr') # These languages are required
fallback_languages = {
'default': ('en',),
'fr': ('en', 'de')
}Central translator instance that manages model registrations and provides access to translation options.
class Translator:
"""Main translator class managing model registrations."""
def register(self, model_or_iterable, opts_class, **options):
"""
Register model(s) with translation options.
Parameters:
- model_or_iterable: Model class or iterable of models
- opts_class: TranslationOptions subclass
- **options: Additional options
"""
def unregister(self, model_or_iterable):
"""
Unregister model(s) from translation.
Parameters:
- model_or_iterable: Model class or iterable of models
"""
def get_options_for_model(self, model):
"""
Get translation options for a model.
Parameters:
- model: Model class
Returns:
- TranslationOptions instance
Raises:
- NotRegistered: If model is not registered
"""
def get_registered_models(self):
"""
Get all registered models.
Returns:
- List of registered model classes
"""
def is_registered(self, model):
"""
Check if model is registered for translation.
Parameters:
- model: Model class
Returns:
- bool: True if registered
"""
translator: Translator
"""Global translator instance for managing registrations."""Usage Example:
from modeltranslation.translator import translator
# Check if model is registered
if translator.is_registered(MyModel):
options = translator.get_options_for_model(MyModel)
print(f"Translatable fields: {options.fields}")
# Get all registered models
registered = translator.get_registered_models()
print(f"Registered models: {[m.__name__ for m in registered]}")Translation fields are inherited from parent classes, allowing for flexible model hierarchies.
# Base model with translations
@register(BaseContent)
class BaseContentTranslationOptions(TranslationOptions):
fields = ('title', 'description')
# Child model automatically inherits parent translations
class Article(BaseContent):
content = models.TextField()
author = models.CharField(max_length=100)
@register(Article)
class ArticleTranslationOptions(TranslationOptions):
fields = ('content', 'author') # In addition to inherited fieldsThe registration system validates configuration and prevents common errors.
class AlreadyRegistered(Exception):
"""Raised when attempting to register an already registered model."""
class NotRegistered(Exception):
"""Raised when accessing options for unregistered model."""
class DescendantRegistered(Exception):
"""Raised when child model is registered before parent."""Error Handling:
from modeltranslation.translator import AlreadyRegistered, NotRegistered
try:
translator.get_options_for_model(UnregisteredModel)
except NotRegistered:
print("Model is not registered for translation")
try:
@register(MyModel)
class DuplicateOptions(TranslationOptions):
fields = ('name',)
except AlreadyRegistered:
print("Model is already registered")Configure how empty values are handled for different field types:
@register(Product)
class ProductTranslationOptions(TranslationOptions):
fields = ('name', 'description', 'price')
empty_values = {
'name': 'both', # Both None and '' are empty
'description': '', # Only '' is empty
'price': None # Only None is empty
}Define different fallback strategies per language:
@register(Article)
class ArticleTranslationOptions(TranslationOptions):
fields = ('title', 'content')
fallback_languages = {
'default': ('en',), # Default fallback to English
'fr': ('en', 'de'), # French falls back to English, then German
'es': ('en',), # Spanish falls back to English
}
required_languages = ('en', 'fr') # These languages must have valuesDjango-modeltranslation automatically discovers translation.py modules in installed apps, similar to Django's admin autodiscovery. This happens when the app is ready and can be controlled via settings.
# In your app's translation.py
from modeltranslation.translator import register, TranslationOptions
from .models import MyModel
@register(MyModel)
class MyModelTranslationOptions(TranslationOptions):
fields = ('title', 'description')Install with Tessl CLI
npx tessl i tessl/pypi-django-modeltranslation