1 # -*- coding: utf-8 -*-
2 from django.conf import settings
3 from django.db.models.fields import Field, CharField
4 from django.utils.translation import string_concat
6 from modeltranslation.utils import get_language, build_localized_fieldname
9 class TranslationField(Field):
11 The translation field functions as a proxy to the original field which is
14 For every field defined in the model's ``TranslationOptions`` localized
15 versions of that field are added to the model depending on the languages
16 given in ``settings.LANGUAGES``.
18 If for example there is a model ``News`` with a field ``title`` which is
19 registered for translation and the ``settings.LANGUAGES`` contains the
20 ``de`` and ``en`` languages, the fields ``title_de`` and ``title_en`` will
21 be added to the model class. These fields are realized using this
24 The translation field needs to know which language it contains therefore
25 that needs to be specified when the field is created.
27 def __init__(self, translated_field, language, *args, **kwargs):
28 # Store the originally wrapped field for later
29 self.translated_field = translated_field
30 self.language = language
32 # Update the dict of this field with the content of the original one
33 # This might be a bit radical?! Seems to work though...
34 self.__dict__.update(translated_field.__dict__)
36 # Translation are always optional (for now - maybe add some parameters
37 # to the translation options for configuring this)
41 # Adjust the name of this field to reflect the language
42 self.attname = build_localized_fieldname(translated_field.name,
44 self.name = self.attname
46 # Copy the verbose name and append a language suffix (will e.g. in the
47 # admin). This might be a proxy function so we have to check that here.
48 self.verbose_name = string_concat(translated_field.verbose_name,
49 ' [%s]' % (language, ))
51 def pre_save(self, model_instance, add):
52 val = super(TranslationField, self).pre_save(model_instance, add)
53 if get_language() == self.language and not add:
54 # Rule is: 3. Assigning a value to a translation field of the
55 # default language also updates the original field
56 model_instance.__dict__[self.translated_field.name] = val
59 def get_internal_type(self):
60 return self.translated_field.get_internal_type()
62 #def contribute_to_class(self, cls, name):
63 #super(TranslationField, self).contribute_to_class(cls, name)
64 ##setattr(cls, 'get_%s_display' % self.name,
65 ##curry(cls._get_FIELD_display, field=self))
67 def south_field_triple(self):
68 """Returns a suitable description of this field for South."""
69 # We'll just introspect the _actual_ field.
70 from south.modelsinspector import introspector
71 field_class = '%s.%s' % (self.translated_field.__class__.__module__,
72 self.translated_field.__class__.__name__)
73 args, kwargs = introspector(self.translated_field)
75 # This is patched in init and so should be here! -- lqc
76 kwargs['blank'], kwargs['null'] = True, True
78 # That's our definition!
79 return (field_class, args, kwargs)
81 def formfield(self, *args, **kwargs):
82 """Preserves the widget of the translated field."""
83 trans_formfield = self.translated_field.formfield(*args, **kwargs)
84 defaults = {'widget': type(trans_formfield.widget)}
85 defaults.update(kwargs)
86 return super(TranslationField, self).formfield(*args, **defaults)
89 #class CurrentLanguageField(CharField):
90 #def __init__(self, **kwargs):
91 #super(CurrentLanguageField, self).__init__(null=True, max_length=5,
94 #def contribute_to_class(self, cls, name):
95 #super(CurrentLanguageField, self).contribute_to_class(cls, name)
96 #registry = CurrentLanguageFieldRegistry()
97 #registry.add_field(cls, self)
100 #class CurrentLanguageFieldRegistry(object):
103 #def add_field(self, model, field):
104 #reg = self.__class__._registry.setdefault(model, [])
107 #def get_fields(self, model):
108 #return self.__class__._registry.get(model, [])
110 #def __contains__(self, model):
111 #return model in self.__class__._registry