|
1 |
|
2 from django.conf import settings |
|
3 from django.db.models.fields import Field, CharField |
|
4 from django.utils.translation import get_language |
|
5 |
|
6 from modeltranslation.utils import build_localized_fieldname |
|
7 |
|
8 class TranslationField(Field): |
|
9 """ |
|
10 The translation field functions as a proxy to the original field which is |
|
11 wrapped. |
|
12 |
|
13 For every field defined in the model's ``TranslationOptions`` localized |
|
14 versions of that field are added to the model depending on the languages |
|
15 given in ``settings.LANGUAGES``. |
|
16 |
|
17 If for example there is a model ``News`` with a field ``title`` which is |
|
18 registered for translation and the ``settings.LANGUAGES`` contains the |
|
19 ``de`` and ``en`` languages, the fields ``title_de`` and ``title_en`` will |
|
20 be added to the model class. These fields are realized using this |
|
21 descriptor. |
|
22 |
|
23 The translation field needs to know which language it contains therefore |
|
24 that needs to be specified when the field is created. |
|
25 """ |
|
26 def __init__(self, translated_field, language, *args, **kwargs): |
|
27 # Store the originally wrapped field for later |
|
28 self.translated_field = translated_field |
|
29 self.language = language |
|
30 |
|
31 # Update the dict of this field with the content of the original one |
|
32 # This might be a bit radical?! Seems to work though... |
|
33 self.__dict__.update(translated_field.__dict__) |
|
34 |
|
35 # Translation are always optional (for now - maybe add some parameters |
|
36 # to the translation options for configuring this) |
|
37 self.null = True |
|
38 self.blank = True |
|
39 |
|
40 # Adjust the name of this field to reflect the language |
|
41 self.attname = build_localized_fieldname(translated_field.name, language) |
|
42 self.name = self.attname |
|
43 |
|
44 # Copy the verbose name and append a language suffix (will e.g. in the |
|
45 # admin). This might be a proxy function so we have to check that here. |
|
46 if hasattr(translated_field.verbose_name, '_proxy____unicode_cast'): |
|
47 verbose_name = translated_field.verbose_name._proxy____unicode_cast() |
|
48 else: |
|
49 verbose_name = translated_field.verbose_name |
|
50 self.verbose_name = '%s [%s]' % (verbose_name, language) |
|
51 |
|
52 def pre_save(self, model_instance, add): |
|
53 val = super(TranslationField, self).pre_save(model_instance, add) |
|
54 if get_language() == self.language and not add: |
|
55 # Rule is: 3. Assigning a value to a translation field of the default language |
|
56 # also updates the original field |
|
57 model_instance.__dict__[self.translated_field.name] = val |
|
58 #setattr(model_instance, self.attname, orig_val) |
|
59 # Also return the original value |
|
60 #return orig_val |
|
61 return val |
|
62 |
|
63 #def get_attname(self): |
|
64 #return self.attname |
|
65 |
|
66 def get_internal_type(self): |
|
67 return self.translated_field.get_internal_type() |
|
68 |
|
69 def contribute_to_class(self, cls, name): |
|
70 |
|
71 super(TranslationField, self).contribute_to_class(cls, name) |
|
72 |
|
73 #setattr(cls, 'get_%s_display' % self.name, curry(cls._get_FIELD_display, field=self)) |
|
74 |
|
75 #class CurrentLanguageField(CharField): |
|
76 #def __init__(self, **kwargs): |
|
77 #super(CurrentLanguageField, self).__init__(null=True, max_length=5, **kwargs) |
|
78 |
|
79 #def contribute_to_class(self, cls, name): |
|
80 #super(CurrentLanguageField, self).contribute_to_class(cls, name) |
|
81 #registry = CurrentLanguageFieldRegistry() |
|
82 #registry.add_field(cls, self) |
|
83 |
|
84 |
|
85 #class CurrentLanguageFieldRegistry(object): |
|
86 #_registry = {} |
|
87 |
|
88 #def add_field(self, model, field): |
|
89 #reg = self.__class__._registry.setdefault(model, []) |
|
90 #reg.append(field) |
|
91 |
|
92 #def get_fields(self, model): |
|
93 #return self.__class__._registry.get(model, []) |
|
94 |
|
95 #def __contains__(self, model): |
|
96 #return model in self.__class__._registry |
|
97 |
|
98 |