0
# Field Management
1
2
Translation field types, descriptors, and factory functions for creating and managing multilingual model fields. Handles the dynamic creation of language-specific fields and their integration with Django's model system.
3
4
## Capabilities
5
6
### Translation Field Factory
7
8
Factory functions for dynamically creating translation fields based on original Django field types.
9
10
```python { .api }
11
def create_translation_field(model, field_name, lang, empty_value):
12
"""
13
Create a translation field for a specific language.
14
15
Parameters:
16
- model: Model class containing the original field
17
- field_name: Name of the original field to translate
18
- lang: Language code for this translation field
19
- empty_value: How to handle empty values ('', 'both', None, NONE)
20
21
Returns:
22
- TranslationField instance
23
24
Raises:
25
- ImproperlyConfigured: If field type is not supported
26
"""
27
28
def field_factory(baseclass):
29
"""
30
Create a translation field class based on Django field type.
31
32
Parameters:
33
- baseclass: Django field class to base translation field on
34
35
Returns:
36
- TranslationField subclass
37
"""
38
```
39
40
**Usage Example:**
41
42
```python
43
from modeltranslation.fields import create_translation_field
44
from myapp.models import Article
45
46
# Create French translation field for title
47
title_fr_field = create_translation_field(
48
model=Article,
49
field_name='title',
50
lang='fr',
51
empty_value=''
52
)
53
```
54
55
### Translation Field Base
56
57
Base class for all translation fields, providing common functionality and field proxying.
58
59
```python { .api }
60
class TranslationField:
61
"""
62
Base class for translation fields that proxy to original fields.
63
64
Attributes:
65
- translated_field: Original field being translated
66
- language: Language code for this translation
67
- empty_value: Empty value handling strategy
68
"""
69
70
def __init__(self, translated_field, language, empty_value):
71
"""
72
Initialize translation field.
73
74
Parameters:
75
- translated_field: Original Django field
76
- language: Language code (e.g., 'en', 'fr')
77
- empty_value: Empty value handling
78
"""
79
80
def contribute_to_class(self, cls, name):
81
"""Add this field to the model class."""
82
83
def formfield(self, **kwargs):
84
"""Create form field for this translation field."""
85
```
86
87
### Field Descriptors
88
89
Descriptors that handle field access and provide language-aware field behavior.
90
91
```python { .api }
92
class TranslationFieldDescriptor:
93
"""
94
Descriptor for accessing translation fields with language awareness.
95
Handles fallback logic and value resolution.
96
"""
97
98
def __init__(self, field):
99
"""
100
Initialize descriptor for translation field.
101
102
Parameters:
103
- field: TranslationField instance
104
"""
105
106
def __get__(self, instance, owner):
107
"""Get field value with language-aware fallback."""
108
109
def __set__(self, instance, value):
110
"""Set field value for current language."""
111
112
class TranslatedRelationIdDescriptor:
113
"""Descriptor for translated foreign key ID fields."""
114
115
class TranslatedManyToManyDescriptor:
116
"""Descriptor for translated many-to-many relationships."""
117
```
118
119
### Supported Field Types
120
121
Django field types that can be translated by modeltranslation.
122
123
```python { .api }
124
SUPPORTED_FIELDS: tuple = (
125
# Text fields
126
fields.CharField,
127
fields.TextField,
128
fields.json.JSONField,
129
130
# Numeric fields
131
fields.IntegerField,
132
fields.FloatField,
133
fields.DecimalField,
134
135
# Boolean fields
136
fields.BooleanField,
137
fields.NullBooleanField,
138
139
# Date/time fields
140
fields.DateField,
141
fields.DateTimeField,
142
fields.TimeField,
143
144
# File fields
145
fields.files.FileField,
146
fields.files.ImageField,
147
148
# Network fields
149
fields.IPAddressField,
150
fields.GenericIPAddressField,
151
152
# Relationship fields
153
fields.related.ForeignKey,
154
fields.related.ManyToManyField,
155
)
156
"""Tuple of Django field types supported for translation."""
157
```
158
159
**Custom Field Support:**
160
161
```python
162
# In Django settings.py
163
MODELTRANSLATION_CUSTOM_FIELDS = ('MyCustomField', 'AnotherField')
164
165
# Now MyCustomField can be used in translation
166
@register(MyModel)
167
class MyModelTranslationOptions(TranslationOptions):
168
fields = ('my_custom_field',) # Works if MyCustomField is in CUSTOM_FIELDS
169
```
170
171
### Empty Value Handling
172
173
Sentinel class and strategies for handling empty and undefined translation values.
174
175
```python { .api }
176
class NONE:
177
"""
178
Sentinel class for undefined translation values.
179
Used when fallback value is not yet known and needs computation.
180
"""
181
```
182
183
**Empty Value Strategies:**
184
185
```python
186
@register(Article)
187
class ArticleTranslationOptions(TranslationOptions):
188
fields = ('title', 'content', 'summary')
189
empty_values = {
190
'title': '', # Only empty string is considered empty
191
'content': 'both', # Both None and empty string are empty
192
'summary': None, # Only None is considered empty
193
}
194
```
195
196
### Field Attribute Management
197
198
Automatic handling of field attributes across translation fields.
199
200
```python
201
# Original field
202
class Article(models.Model):
203
title = models.CharField(max_length=255, help_text="Article title")
204
content = models.TextField(blank=True, null=True)
205
206
# After registration, translation fields inherit attributes:
207
# title_en = CharField(max_length=255, help_text="Article title (English)")
208
# title_fr = CharField(max_length=255, help_text="Article title (French)")
209
# content_en = TextField(blank=True, null=True)
210
# content_fr = TextField(blank=True, null=True)
211
```
212
213
### Relationship Field Translation
214
215
Special handling for foreign key and many-to-many field translations.
216
217
```python { .api }
218
# For ForeignKey fields
219
class TranslatedRelationIdDescriptor:
220
"""
221
Handles translated foreign key relationships.
222
Manages the _id suffix and related object access.
223
"""
224
225
# For ManyToManyField fields
226
class TranslatedManyToManyDescriptor:
227
"""
228
Handles translated many-to-many relationships.
229
Creates intermediate models for each language.
230
"""
231
```
232
233
**Relationship Translation Example:**
234
235
```python
236
class Article(models.Model):
237
title = models.CharField(max_length=255)
238
category = models.ForeignKey(Category, on_delete=models.CASCADE)
239
tags = models.ManyToManyField(Tag)
240
241
@register(Article)
242
class ArticleTranslationOptions(TranslationOptions):
243
fields = ('title', 'category', 'tags')
244
245
# Creates fields:
246
# title_en, title_fr, title_de
247
# category_en, category_fr, category_de (ForeignKey fields)
248
# tags_en, tags_fr, tags_de (ManyToMany fields with intermediate models)
249
```
250
251
### Field Validation
252
253
Translation field validation and constraint handling.
254
255
```python
256
class CustomTranslationField(TranslationField):
257
def validate(self, value, model_instance):
258
"""Custom validation for translation field."""
259
super().validate(value, model_instance)
260
261
# Add custom validation logic
262
if value and len(value) < 5:
263
raise ValidationError("Translation must be at least 5 characters")
264
265
def clean(self, value, model_instance):
266
"""Clean and prepare field value."""
267
value = super().clean(value, model_instance)
268
269
# Add custom cleaning logic
270
if isinstance(value, str):
271
value = value.strip()
272
273
return value
274
```
275
276
## Advanced Usage
277
278
### Dynamic Field Creation
279
280
Programmatically create translation fields at runtime.
281
282
```python
283
from modeltranslation.fields import create_translation_field
284
285
def add_translation_field(model, field_name, language):
286
"""Dynamically add translation field to model."""
287
trans_field = create_translation_field(
288
model=model,
289
field_name=field_name,
290
lang=language,
291
empty_value=''
292
)
293
294
localized_name = f"{field_name}_{language}"
295
trans_field.contribute_to_class(model, localized_name)
296
297
return trans_field
298
```
299
300
### Custom Field Descriptors
301
302
Create custom descriptors for specialized translation behavior.
303
304
```python
305
class CustomTranslationDescriptor:
306
def __init__(self, field_name, language):
307
self.field_name = field_name
308
self.language = language
309
310
def __get__(self, instance, owner):
311
if instance is None:
312
return self
313
314
# Custom logic for getting translated value
315
return getattr(instance, f"{self.field_name}_{self.language}", None)
316
317
def __set__(self, instance, value):
318
# Custom logic for setting translated value
319
setattr(instance, f"{self.field_name}_{self.language}", value)
320
```
321
322
### Field Migration Support
323
324
Handle field migrations when adding or modifying translations.
325
326
```python
327
# Migration support for adding translation fields
328
from django.db import migrations
329
from modeltranslation.fields import TranslationField
330
331
class Migration(migrations.Migration):
332
operations = [
333
migrations.AddField(
334
model_name='article',
335
name='title_fr',
336
field=TranslationField(original_field='title', language='fr'),
337
),
338
]
339
```
340
341
### Performance Optimization
342
343
Optimize field access and memory usage for translation fields.
344
345
```python
346
class OptimizedTranslationDescriptor:
347
def __init__(self, field):
348
self.field = field
349
self._cache_key = f"_{field.name}_cache"
350
351
def __get__(self, instance, owner):
352
if instance is None:
353
return self
354
355
# Use caching to improve performance
356
cache_key = self._cache_key
357
if hasattr(instance, cache_key):
358
return getattr(instance, cache_key)
359
360
value = self._get_translated_value(instance)
361
setattr(instance, cache_key, value)
362
return value
363
```