From 4132374a347219755f457a4d9319caf0928cd90b Mon Sep 17 00:00:00 2001 From: Erik Stein Date: Fri, 10 Nov 2017 16:55:09 +0100 Subject: [PATCH] Use shared.utils.lang_suffix for translated field names; allow translatable fields also for abstract classes; added TranslatableJSONField. --- shared/multilingual/utils/fields.py | 183 ++++++++++++++++++---------- 1 file changed, 117 insertions(+), 66 deletions(-) diff --git a/shared/multilingual/utils/fields.py b/shared/multilingual/utils/fields.py index 0ca9492..a6bad7a 100644 --- a/shared/multilingual/utils/fields.py +++ b/shared/multilingual/utils/fields.py @@ -2,10 +2,11 @@ from __future__ import unicode_literals from django.conf import settings +from django.contrib.postgres.fields import JSONField from django.db import models from django.utils.translation import string_concat -from shared.utils.translation import get_language +from shared.utils.translation import get_language, lang_suffix class TranslatableCharField(models.CharField): @@ -16,44 +17,43 @@ class TranslatableCharField(models.CharField): super(TranslatableCharField, self).__init__(verbose_name, **kwargs) - def contribute_to_class(self, cls, name, virtual_only=False): - if not cls._meta.abstract: - for lang_code, lang_name in settings.LANGUAGES: - if lang_code == settings.LANGUAGE_CODE: - _blank = self._blank - else: - _blank = True - - localized_field = models.CharField( - string_concat(self.verbose_name, " (%s)" % lang_code), - name=self.name, - primary_key=self.primary_key, - max_length=self.max_length, - unique=self.unique, - blank=_blank, - null=False, # intentionally ignored - db_index=self.db_index, - rel=self.rel, - default=self.default or "", - editable=self._editable, - serialize=self.serialize, - choices=self.choices, - help_text=self.help_text, - db_column=None, - db_tablespace=self.db_tablespace - ) - - localized_field.contribute_to_class( - cls, - "%s_%s" % (name, lang_code), - ) + def contribute_to_class(self, cls, name, private_only=False): + for lang_code, lang_name in settings.LANGUAGES: + if lang_code == settings.LANGUAGE_CODE: + _blank = self._blank + else: + _blank = True + + localized_field = models.CharField( + string_concat(self.verbose_name, " (%s)" % lang_code), + name=self.name, + primary_key=self.primary_key, + max_length=self.max_length, + unique=self.unique, + blank=_blank, + null=False, # intentionally ignored + db_index=self.db_index, + rel=self.rel, + default=self.default or "", + editable=self._editable, + serialize=self.serialize, + choices=self.choices, + help_text=self.help_text, + db_column=None, + db_tablespace=self.db_tablespace + ) + + localized_field.contribute_to_class( + cls, + "%s%s" % (name, lang_suffix(lang_code)), + ) def translated_value(self): # For empty / non-existing translation fall back to main field language = get_language() - val = self.__dict__["%s_%s" % (name, language)] + val = self.__dict__["%s%s" % (name, lang_suffix(language))] if not val: - val = self.__dict__["%s_%s" % (name, settings.LANGUAGE_CODE)] + val = self.__dict__["%s%s" % (name, lang_suffix(settings.LANGUAGE_CODE))] return val setattr(cls, name, property(translated_value)) @@ -67,42 +67,93 @@ class TranslatableTextField(models.TextField): super(TranslatableTextField, self).__init__(verbose_name, **kwargs) - def contribute_to_class(self, cls, name, virtual_only=False): - if not cls._meta.abstract: - for lang_code, lang_name in settings.LANGUAGES: - if lang_code == settings.LANGUAGE_CODE: - _blank = self._blank - else: - _blank = True - - localized_field = models.TextField( - string_concat(self.verbose_name, " (%s)" % lang_code), - name=self.name, - primary_key=self.primary_key, - max_length=self.max_length, - unique=self.unique, - blank=_blank, - null=False, # intentionally ignored - db_index=self.db_index, - rel=self.rel, - default=self.default or "", - editable=self._editable, - serialize=self.serialize, - choices=self.choices, - help_text=self.help_text, - db_column=None, - db_tablespace=self.db_tablespace - ) - - localized_field.contribute_to_class( - cls, "%s_%s" % (name, lang_code), - ) + def contribute_to_class(self, cls, name, private_only=False): + for lang_code, lang_name in settings.LANGUAGES: + if lang_code == settings.LANGUAGE_CODE: + _blank = self._blank + else: + _blank = True + + localized_field = models.TextField( + string_concat(self.verbose_name, " (%s)" % lang_code), + name=self.name, + primary_key=self.primary_key, + max_length=self.max_length, + unique=self.unique, + blank=_blank, + null=False, # intentionally ignored + db_index=self.db_index, + rel=self.rel, + default=self.default or "", + editable=self._editable, + serialize=self.serialize, + choices=self.choices, + help_text=self.help_text, + db_column=None, + db_tablespace=self.db_tablespace + ) + + localized_field.contribute_to_class( + cls, + "%s%s" % (name, lang_suffix(lang_code)), + ) def translated_value(self): language = get_language() - val = self.__dict__["%s_%s" % (name, language)] + val = self.__dict__["%s%s" % (name, lang_suffix(language))] if not val: - val = self.__dict__["%s_%s" % (name, settings.LANGUAGE_CODE)] + val = self.__dict__["%s%s" % (name, lang_suffix(settings.LANGUAGE_CODE))] + return val + + setattr(cls, name, property(translated_value)) + + +class TranslatableJSONField(JSONField): + + def __init__(self, verbose_name=None, **kwargs): + self._blank = kwargs.get("blank", False) + self._editable = kwargs.get("editable", True) + + super().__init__(verbose_name, **kwargs) + + def contribute_to_class(self, cls, name, private_only=False): + print(self, cls) + for lang_code, lang_name in settings.LANGUAGES: + if lang_code == settings.LANGUAGE_CODE: + _blank = self._blank + else: + _blank = True + + localized_field = JSONField( + string_concat(self.verbose_name, " (%s)" % lang_code), + name=self.name, + primary_key=self.primary_key, + max_length=self.max_length, + unique=self.unique, + blank=_blank, + null=False, # intentionally ignored + db_index=self.db_index, + rel=self.rel, + default=self.default or "", + editable=self._editable, + serialize=self.serialize, + choices=self.choices, + help_text=self.help_text, + db_column=None, + db_tablespace=self.db_tablespace, + encoder=self.encoder + ) + + localized_field.contribute_to_class( + cls, + "%s%s" % (name, lang_suffix(lang_code)), + ) + + def translated_value(self): + language = get_language() + val = self.__dict__["%s%s" % (name, lang_suffix(language))] + if not val: + val = self.__dict__["%s%s" % (name, lang_suffix(settings.LANGUAGE_CODE))] return val setattr(cls, name, property(translated_value))