def populate_translation_fields(sender, kwargs):
    """
    When models are created or loaded from fixtures, replicates values
    provided for translatable fields to some / all empty translation fields,
    according to the current population mode.

    Population is performed only on keys (field names) present in kwargs.
    Nothing is returned, but passed kwargs dictionary is altered.

    With ``mode`` set to:
    -- ``all``: fills all translation fields, skipping just those for
       which a translated value is also provided;
    -- ``default``: fills only the default translation (unless it is
       additionally provided);
    -- ``required``: like ``default``, but only if the original field is
       non-nullable;

    At least the ``required`` mode should be used when loading untranslated
    fixtures to keep the database consistent (note that Django management
    commands are normally forced to run with hardcoded ``en-us`` language
    active). The ``default`` mode is useful if you need to ensure fallback
    values are available, and ``all`` if you need to have all translations
    defined (for example to make lookups / filtering without resorting to
    query fallbacks).
    """
    populate = mt_settings.AUTO_POPULATE
    if not populate:
        return
    if populate is True:
        # What was meant by ``True`` is now called ``all``.
        populate = 'all'

    opts = translator.get_options_for_model(sender)
    for key, val in list(kwargs.items()):
        if key in opts.fields:
            if populate == 'all':
                # Set the value for every language.
                for translation_field in opts.fields[key]:
                    kwargs.setdefault(translation_field.name, val)
            elif populate == 'default':
                default = build_localized_fieldname(
                    key, mt_settings.DEFAULT_LANGUAGE)
                kwargs.setdefault(default, val)
            elif populate == 'required':
                default = build_localized_fieldname(
                    key, mt_settings.DEFAULT_LANGUAGE)
                if not sender._meta.get_field(key).null:
                    kwargs.setdefault(default, val)
            else:
                raise AttributeError("Unknown population mode '%s'." %
                                     populate)
def populate_translation_fields(sender, kwargs):
    """
    When models are created or loaded from fixtures, replicates values
    provided for translatable fields to some / all empty translation fields,
    according to the current population mode.

    Population is performed only on keys (field names) present in kwargs.
    Nothing is returned, but passed kwargs dictionary is altered.

    With ``mode`` set to:
    -- ``all``: fills all translation fields, skipping just those for
       which a translated value is also provided;
    -- ``default``: fills only the default translation (unless it is
       additionally provided);
    -- ``required``: like ``default``, but only if the original field is
       non-nullable;

    At least the ``required`` mode should be used when loading untranslated
    fixtures to keep the database consistent (note that Django management
    commands are normally forced to run with hardcoded ``en-us`` language
    active). The ``default`` mode is useful if you need to ensure fallback
    values are available, and ``all`` if you need to have all translations
    defined (for example to make lookups / filtering without resorting to
    query fallbacks).
    """
    populate = mt_settings.AUTO_POPULATE
    if not populate:
        return
    if populate is True:
        # What was meant by ``True`` is now called ``all``.
        populate = 'all'

    opts = translator.get_options_for_model(sender)
    for key, val in list(kwargs.items()):
        if key in opts.fields:
            if populate == 'all':
                # Set the value for every language.
                for translation_field in opts.fields[key]:
                    kwargs.setdefault(translation_field.name, val)
            elif populate == 'default':
                default = build_localized_fieldname(key, mt_settings.DEFAULT_LANGUAGE)
                kwargs.setdefault(default, val)
            elif populate == 'required':
                default = build_localized_fieldname(key, mt_settings.DEFAULT_LANGUAGE)
                if not sender._meta.get_field(key).null:
                    kwargs.setdefault(default, val)
            else:
                raise AttributeError("Unknown population mode '%s'." % populate)
Пример #3
0
 def __get__(self, instance, owner):
     """
     Returns value from the translation field for the current language, or
     value for some another language according to fallback languages, or the
     custom fallback value, or field's default value.
     """
     if instance is None:
         return self
     default = NONE
     undefined = self.fallback_undefined
     if undefined is NONE:
         default = self.field.get_default()
         undefined = default
     langs = resolution_order(get_language(), self.fallback_languages)
     for lang in langs:
         loc_field_name = build_localized_fieldname(self.field.name, lang)
         val = getattr(instance, loc_field_name, None)
         if self.meaningful_value(val, undefined):
             return val
     if mt_settings.ENABLE_FALLBACKS and self.fallback_value is not NONE:
         return self.fallback_value
     else:
         if default is NONE:
             default = self.field.get_default()
         # Some fields like FileField behave strange, as their get_default() doesn't return
         # instance of attr_class, but rather None or ''.
         # Normally this case is handled in the descriptor, but since we have overridden it, we
         # must mock it up.
         if (isinstance(self.field, fields.files.FileField) and
                 not isinstance(default, self.field.attr_class)):
             return self.field.attr_class(instance, self.field, default)
         return default
 def __get__(self, instance, owner):
     """
     Returns value from the translation field for the current language, or
     value for some another language according to fallback languages, or the
     custom fallback value, or field's default value.
     """
     if instance is None:
         return self
     default = NONE
     undefined = self.fallback_undefined
     if undefined is NONE:
         default = self.field.get_default()
         undefined = default
     langs = resolution_order(get_language(), self.fallback_languages)
     for lang in langs:
         loc_field_name = build_localized_fieldname(self.field.name, lang)
         val = getattr(instance, loc_field_name, None)
         if self.meaningful_value(val, undefined):
             return val
     if mt_settings.ENABLE_FALLBACKS and self.fallback_value is not NONE:
         return self.fallback_value
     else:
         if default is NONE:
             default = self.field.get_default()
         # Some fields like FileField behave strange, as their get_default() doesn't return
         # instance of attr_class, but rather None or ''.
         # Normally this case is handled in the descriptor, but since we have overridden it, we
         # must mock it up.
         if (isinstance(self.field, fields.files.FileField)
                 and not isinstance(default, self.field.attr_class)):
             return self.field.attr_class(instance, self.field, default)
         return default
def add_translation_fields(model, opts):
    """
    Monkey patches the original model class to provide additional fields for
    every language.

    Adds newly created translation fields to the given translation options.
    """
    model_empty_values = getattr(opts, 'empty_values', NONE)
    for field_name in opts.local_fields.keys():
        field_empty_value = parse_field(model_empty_values, field_name, NONE)
        for l in mt_settings.AVAILABLE_LANGUAGES:
            # Create a dynamic translation field
            translation_field = create_translation_field(
                model=model, field_name=field_name, lang=l, empty_value=field_empty_value)
            # Construct the name for the localized field
            localized_field_name = build_localized_fieldname(field_name, l)
            # Check if the model already has a field by that name
            if hasattr(model, localized_field_name):
                raise ValueError(
                    "Error adding translation field. Model '%s' already contains a field named"
                    "'%s'." % (model._meta.object_name, localized_field_name))
            # This approach implements the translation fields as full valid
            # django model fields and therefore adds them via add_to_class
            model.add_to_class(localized_field_name, translation_field)
            opts.add_translation_field(field_name, translation_field)

    # Rebuild information about parents fields. If there are opts.local_fields, field cache would be
    # invalidated (by model._meta.add_field() function). Otherwise, we need to do it manually.
    if len(opts.local_fields) == 0:
        try:
            model._meta._fill_fields_cache()
        except AttributeError:
            # Django 1.8 removed _fill_fields_cache
            model._meta._expire_cache()
            model._meta.get_fields()
Пример #6
0
    def handle_noargs(self, **options):
        verbosity = int(options['verbosity'])
        if verbosity > 0:
            self.stdout.write("Using default language: %s\n" %
                              DEFAULT_LANGUAGE)
        models = translator.get_registered_models(abstract=False)
        for model in models:
            if verbosity > 0:
                self.stdout.write("Updating data of model '%s'\n" % model)
            opts = translator.get_options_for_model(model)
            for field_name in opts.fields.keys():
                def_lang_fieldname = build_localized_fieldname(
                    field_name, DEFAULT_LANGUAGE)

                # We'll only update fields which do not have an existing value
                q = Q(**{def_lang_fieldname: None})
                field = model._meta.get_field(field_name)
                if field.empty_strings_allowed:
                    q |= Q(**{def_lang_fieldname: ''})

                if issubclass(model, Page):
                    for obj in model._default_manager.filter(q):
                        # Get table description in order to know if field is
                        # in child or parent table
                        # TODO: Tested only on PostgreSQL engine
                        db_table = model._meta.db_table
                        db_table_desc = connection.introspection.\
                            get_table_description(
                                connection.cursor(), db_table)
                        # original field in child class
                        if field_name in [x.name for x in db_table_desc]:
                            raw = model._default_manager.raw(
                                'SELECT *, %s AS original_field FROM %s \
                                 WHERE page_ptr_id=%d LIMIT 1' %
                                (field_name, db_table, obj.page_ptr_id))[0]
                            setattr(obj, def_lang_fieldname,
                                    raw.original_field)
                        # field is a foreign key
                        elif (field_name + '_id') in\
                                [x.name for x in db_table_desc]:
                            raw = model._default_manager.raw(
                                'SELECT *, %s AS original_field FROM %s \
                                 WHERE page_ptr_id=%d LIMIT 1' %
                                (field_name + '_id', db_table,
                                 obj.page_ptr_id))[0]
                            setattr(obj, def_lang_fieldname + '_id',
                                    raw.original_field)
                        # original field parent class
                        else:
                            raw = Page._default_manager.raw(
                                'SELECT *, %s AS original_field FROM \
                                 wagtailcore_page WHERE id=%d LIMIT 1' %
                                (field_name, obj.page_ptr_id))[0]
                            setattr(obj, def_lang_fieldname,
                                    raw.original_field)
                        obj.save(update_fields=[def_lang_fieldname])
                else:
                    model._default_manager.filter(q).rewrite(False).update(
                        **{def_lang_fieldname: F(field_name)})
 def __set__(self, instance, value):
     lang = get_language()
     loc_field_name = build_localized_fieldname(self.field_name, lang)
     # Localized field name with '_id'
     loc_attname = instance._meta.get_field(loc_field_name).get_attname()
     setattr(instance, loc_attname, value)
     base_attname = instance._meta.get_field(self.field_name).get_attname()
     instance.__dict__[base_attname] = value
 def get_missing_languages(self, field_name, db_table):
     """
     Gets only missings fields.
     """
     db_table_fields = self.get_table_fields(db_table)
     for lang_code in AVAILABLE_LANGUAGES:
         if build_localized_fieldname(field_name, lang_code) not in db_table_fields:
             yield lang_code
Пример #9
0
 def get_missing_languages(self, field_name, db_table):
     """
     Gets only missings fields.
     """
     db_table_fields = self.get_table_fields(db_table)
     for lang_code in AVAILABLE_LANGUAGES:
         if build_localized_fieldname(field_name,
                                      lang_code) not in db_table_fields:
             yield lang_code
Пример #10
0
 def __set__(self, instance, value):
     """
     Updates the translation field for the current language.
     """
     if getattr(instance, '_mt_init', False):
         # When assignment takes place in model instance constructor, don't set value.
         # This is essential for only/defer to work, but I think it's sensible anyway.
         return
     loc_field_name = build_localized_fieldname(self.field.name, get_language())
     setattr(instance, loc_field_name, value)
Пример #11
0
 def __get__(self, instance, owner):
     if instance is None:
         return self
     langs = resolution_order(get_language(), self.fallback_languages)
     for lang in langs:
         loc_field_name = build_localized_fieldname(self.field_name, lang)
         # Localized field name with '_id'
         loc_attname = instance._meta.get_field(loc_field_name).get_attname()
         val = getattr(instance, loc_attname, None)
         if val is not None:
             return val
     return None
    def handle_noargs(self, **options):
        verbosity = int(options['verbosity'])
        if verbosity > 0:
            self.stdout.write(
                "Using default language: %s\n" % DEFAULT_LANGUAGE)
        models = translator.get_registered_models(abstract=False)
        for model in models:
            if verbosity > 0:
                self.stdout.write("Updating data of model '%s'\n" % model)
            opts = translator.get_options_for_model(model)
            for field_name in opts.fields.keys():
                def_lang_fieldname = build_localized_fieldname(
                    field_name, DEFAULT_LANGUAGE)

                # We'll only update fields which do not have an existing value
                q = Q(**{def_lang_fieldname: None})
                field = model._meta.get_field(field_name)
                if field.empty_strings_allowed:
                    q |= Q(**{def_lang_fieldname: ''})

                if issubclass(model, Page):
                    for obj in model._default_manager.filter(q):
                        # Get table description in order to know if field is
                        # in child or parent table
                        # TODO: Tested only on PostgreSQL engine
                        db_table = model._meta.db_table
                        db_table_desc = connection.introspection.\
                            get_table_description(
                                connection.cursor(), db_table)
                        # original field in child class
                        if field_name in [x.name for x in db_table_desc]:
                            raw = model._default_manager.raw(
                                'SELECT *, %s AS original_field FROM %s \
                                 WHERE page_ptr_id=%d LIMIT 1' % (
                                    field_name, db_table, obj.page_ptr_id))[0]
                            setattr(
                                obj, def_lang_fieldname, raw.original_field)
                        # original field parent class
                        else:
                            raw = Page._default_manager.raw(
                                'SELECT *, %s AS original_field FROM \
                                 wagtailcore_page WHERE id=%d LIMIT 1' % (
                                    field_name, obj.page_ptr_id))[0]
                            setattr(
                                obj, def_lang_fieldname, raw.original_field)
                        obj.save(update_fields=[def_lang_fieldname])
                else:
                    model._default_manager.filter(q).rewrite(False).update(
                        **{def_lang_fieldname: F(field_name)})
Пример #13
0
def append_fallback(model, fields):
    """
    If translated field is encountered, add also all its fallback fields.
    Returns tuple: (set_of_new_fields_to_use, set_of_translated_field_names)
    """
    fields = set(fields)
    trans = set()
    from wagtail_modeltranslation.translator import translator
    opts = translator.get_options_for_model(model)
    for key, _ in opts.fields.items():
        if key in fields:
            langs = resolution_order(get_language(), getattr(model, key).fallback_languages)
            fields = fields.union(build_localized_fieldname(key, lang) for lang in langs)
            fields.remove(key)
            trans.add(key)
    return fields, trans
 def __set__(self, instance, value):
     """
     Updates the translation field for the current language.
     """
     # In order for deferred fields to work, we also need to set the base value
     instance.__dict__[self.field.name] = value
     if isinstance(self.field, fields.related.ForeignKey):
         instance.__dict__[
             self.field.get_attname()] = None if value is None else value.pk
     if getattr(instance, '_mt_init', False):
         # When assignment takes place in model instance constructor, don't set value.
         # This is essential for only/defer to work, but I think it's sensible anyway.
         return
     loc_field_name = build_localized_fieldname(self.field.name,
                                                get_language())
     setattr(instance, loc_field_name, value)
 def get_sync_sql(self, field_name, missing_langs, model):
     """
     Returns SQL needed for sync schema for a new translatable field.
     """
     qn = connection.ops.quote_name
     style = no_style()
     sql_output = []
     db_table = model._meta.db_table
     for lang in missing_langs:
         new_field = build_localized_fieldname(field_name, lang)
         f = model._meta.get_field(new_field)
         col_type = f.db_type(connection=connection)
         field_sql = [style.SQL_FIELD(qn(f.column)), style.SQL_COLTYPE(col_type)]
         # column creation
         stmt = "ALTER TABLE %s ADD COLUMN %s" % (qn(db_table), ' '.join(field_sql))
         if not f.null:
             stmt += " " + style.SQL_KEYWORD('NOT NULL')
         sql_output.append(stmt + ";")
     return sql_output
Пример #16
0
def rewrite_lookup_key(model, lookup_key):
    pieces = lookup_key.split('__', 1)
    original_key = pieces[0]

    translatable_fields = get_translatable_fields_for_model(model)
    if translatable_fields is not None:
        # If we are doing a lookup on a translatable field,
        # we want to rewrite it to the actual field name
        # For example, we want to rewrite "name__startswith" to "name_fr__startswith"
        if pieces[0] in translatable_fields:
            pieces[0] = build_localized_fieldname(pieces[0], get_language())

    if len(pieces) > 1:
        # Check if we are doing a lookup to a related trans model
        fields_to_trans_models = get_fields_to_translatable_models(model)
        # Check ``original key``, as pieces[0] may have been already rewritten.
        if original_key in fields_to_trans_models:
            transmodel = fields_to_trans_models[original_key]
            pieces[1] = rewrite_lookup_key(transmodel, pieces[1])
    return '__'.join(pieces)
    def handle_noargs(self, **options):
        verbosity = int(options['verbosity'])
        if verbosity > 0:
            self.stdout.write("Using default language: %s\n" % DEFAULT_LANGUAGE)
        models = translator.get_registered_models(abstract=False)
        for model in models:
            if verbosity > 0:
                self.stdout.write("Updating data of model '%s'\n" % model)
            opts = translator.get_options_for_model(model)
            for field_name in opts.fields.keys():
                def_lang_fieldname = build_localized_fieldname(field_name, DEFAULT_LANGUAGE)

                # We'll only update fields which do not have an existing value
                q = Q(**{def_lang_fieldname: None})
                field = model._meta.get_field(field_name)
                if field.empty_strings_allowed:
                    q |= Q(**{def_lang_fieldname: ""})

                model._default_manager.filter(q).rewrite(False).update(
                    **{def_lang_fieldname: F(field_name)})
Пример #18
0
def add_translation_fields(model, opts):
    """
    Monkey patches the original model class to provide additional fields for
    every language.
    Adds newly created translation fields to the given translation options.
    """
    model_empty_values = getattr(opts, 'empty_values', NONE)
    for field_name in opts.local_fields.keys():
        field_empty_value = parse_field(model_empty_values, field_name, NONE)
        for l in mt_settings.AVAILABLE_LANGUAGES:
            # Create a dynamic translation field
            translation_field = create_translation_field(
                model=model, field_name=field_name, lang=l, empty_value=field_empty_value)
            # Construct the name for the localized field
            localized_field_name = build_localized_fieldname(field_name, l)
            # Check if the model already has a field by that name

            if hasattr(model, localized_field_name):
                # Check if are not dealing with abstract field inherited.
                for cls in model.__mro__:
                    if hasattr(cls, '_meta') and cls.__dict__.get(localized_field_name, None):
                        cls_opts = translator._get_options_for_model(cls)
                        if not cls._meta.abstract or field_name not in cls_opts.local_fields:
                            raise ValueError("Error adding translation field. Model '%s' already"
                                             " contains a field named '%s'." %
                                             (model._meta.object_name, localized_field_name))
            # This approach implements the translation fields as full valid
            # django model fields and therefore adds them via add_to_class
            model.add_to_class(localized_field_name, translation_field)
            opts.add_translation_field(field_name, translation_field)

    # Rebuild information about parents fields. If there are opts.local_fields, field cache would be
    # invalidated (by model._meta.add_field() function). Otherwise, we need to do it manually.
    if len(opts.local_fields) == 0:
        try:
            model._meta._fill_fields_cache()
        except AttributeError:
            # Django 1.8 removed _fill_fields_cache
            model._meta._expire_cache()
            model._meta.get_fields()
    def handle_noargs(self, **options):
        verbosity = int(options['verbosity'])
        if verbosity > 0:
            self.stdout.write("Using default language: %s\n" %
                              DEFAULT_LANGUAGE)
        models = translator.get_registered_models(abstract=False)
        for model in models:
            if verbosity > 0:
                self.stdout.write("Updating data of model '%s'\n" % model)
            opts = translator.get_options_for_model(model)
            for field_name in opts.fields.keys():
                def_lang_fieldname = build_localized_fieldname(
                    field_name, DEFAULT_LANGUAGE)

                # We'll only update fields which do not have an existing value
                q = Q(**{def_lang_fieldname: None})
                field = model._meta.get_field(field_name)
                if field.empty_strings_allowed:
                    q |= Q(**{def_lang_fieldname: ""})

                model._default_manager.filter(q).rewrite(False).update(
                    **{def_lang_fieldname: F(field_name)})
Пример #20
0
 def get_sync_sql(self, field_name, missing_langs, model):
     """
     Returns SQL needed for sync schema for a new translatable field.
     """
     qn = connection.ops.quote_name
     style = no_style()
     sql_output = []
     db_table = model._meta.db_table
     for lang in missing_langs:
         new_field = build_localized_fieldname(field_name, lang)
         f = model._meta.get_field(new_field)
         col_type = f.db_type(connection=connection)
         field_sql = [
             style.SQL_FIELD(qn(f.column)),
             style.SQL_COLTYPE(col_type)
         ]
         # column creation
         stmt = "ALTER TABLE %s ADD COLUMN %s" % (qn(db_table),
                                                  ' '.join(field_sql))
         if not f.null:
             stmt += " " + style.SQL_KEYWORD('NOT NULL')
         sql_output.append(stmt + ";")
     return sql_output
 def cache_name(self):
     lang = get_language()
     cache = build_localized_fieldname(self.accessor, lang)
     return "_%s_cache" % cache
Пример #22
0
 def cache_name(self):
     lang = get_language()
     cache = build_localized_fieldname(self.accessor, lang)
     return "_%s_cache" % cache
    def __init__(self, translated_field, language, empty_value, *args,
                 **kwargs):
        from wagtail_modeltranslation.translator import translator

        # Update the dict of this field with the content of the original one
        # This might be a bit radical?! Seems to work though...
        self.__dict__.update(translated_field.__dict__)

        # Store the originally wrapped field for later
        self.translated_field = translated_field
        self.language = language
        self.empty_value = empty_value
        if empty_value is NONE:
            self.empty_value = None if translated_field.null else ''

        # Default behaviour is that all translations are optional
        if not isinstance(self, fields.BooleanField):
            # TODO: Do we really want to enforce null *at all*? Shouldn't this
            # better honour the null setting of the translated field?
            self.null = True
        self.blank = True

        # Take required_languages translation option into account
        trans_opts = translator.get_options_for_model(self.model)
        if trans_opts.required_languages:
            required_languages = trans_opts.required_languages
            if isinstance(trans_opts.required_languages, (tuple, list)):
                # All fields
                if self.language in required_languages:
                    # self.null = False
                    self.blank = False
            else:
                # Certain fields only
                # Try current language - if not present, try 'default' key
                try:
                    req_fields = required_languages[self.language]
                except KeyError:
                    req_fields = required_languages.get('default', ())
                if self.name in req_fields:
                    # TODO: We might have to handle the whole thing through the
                    # FieldsAggregationMetaClass, as fields can be inherited.
                    # self.null = False
                    self.blank = False

        # Adjust the name of this field to reflect the language
        self.attname = build_localized_fieldname(self.translated_field.name,
                                                 language)
        self.name = self.attname
        if self.translated_field.db_column:
            self.db_column = build_localized_fieldname(
                self.translated_field.db_column, language)
            self.column = self.db_column

        # Copy the verbose name and append a language suffix
        # (will show up e.g. in the admin).
        self.verbose_name = build_localized_verbose_name(
            translated_field.verbose_name, language)

        # ForeignKey support - rewrite related_name
        if not NEW_RELATED_API and self.rel and self.related and not self.rel.is_hidden(
        ):
            import copy
            current = self.related.get_accessor_name()
            self.rel = copy.copy(
                self.rel)  # Since fields cannot share the same rel object.
            # self.related doesn't need to be copied, as it will be recreated in
            # ``RelatedField.do_related_class``

            if self.rel.related_name is None:
                # For implicit related_name use different query field name
                loc_related_query_name = build_localized_fieldname(
                    self.related_query_name(), self.language)
                self.related_query_name = lambda: loc_related_query_name
            self.rel.related_name = build_localized_fieldname(
                current, self.language)
            self.rel.field = self  # Django 1.6
            if hasattr(self.rel.to._meta, '_related_objects_cache'):
                del self.rel.to._meta._related_objects_cache
        elif NEW_RELATED_API and self.remote_field and not self.remote_field.is_hidden(
        ):
            import copy
            current = self.remote_field.get_accessor_name()
            # Since fields cannot share the same rel object:
            self.remote_field = copy.copy(self.remote_field)

            if self.remote_field.related_name is None:
                # For implicit related_name use different query field name
                loc_related_query_name = build_localized_fieldname(
                    self.related_query_name(), self.language)
                self.related_query_name = lambda: loc_related_query_name
            self.remote_field.related_name = build_localized_fieldname(
                current, self.language)
            self.remote_field.field = self  # Django 1.6
            if hasattr(self.remote_field.to._meta, '_related_objects_cache'):
                del self.remote_field.to._meta._related_objects_cache
Пример #24
0
 def __set__(self, instance, value):
     lang = get_language()
     loc_field_name = build_localized_fieldname(self.field_name, lang)
     # Localized field name with '_id'
     loc_attname = instance._meta.get_field(loc_field_name).get_attname()
     setattr(instance, loc_attname, value)
Пример #25
0
    def __init__(self, translated_field, language, empty_value, *args, **kwargs):
        from wagtail_modeltranslation.translator import translator

        # Update the dict of this field with the content of the original one
        # This might be a bit radical?! Seems to work though...
        self.__dict__.update(translated_field.__dict__)

        # Store the originally wrapped field for later
        self.translated_field = translated_field
        self.language = language
        self.empty_value = empty_value
        if empty_value is NONE:
            self.empty_value = None if translated_field.null else ''

        # Default behaviour is that all translations are optional
        if not isinstance(self, fields.BooleanField):
            # TODO: Do we really want to enforce null *at all*? Shouldn't this
            # better honour the null setting of the translated field?
            self.null = True
        self.blank = True

        # Take required_languages translation option into account
        trans_opts = translator.get_options_for_model(self.model)
        if trans_opts.required_languages:
            required_languages = trans_opts.required_languages
            if isinstance(trans_opts.required_languages, (tuple, list)):
                # All fields
                if self.language in required_languages:
                    # self.null = False
                    self.blank = False
            else:
                # Certain fields only
                # Try current language - if not present, try 'default' key
                try:
                    req_fields = required_languages[self.language]
                except KeyError:
                    req_fields = required_languages.get('default', ())
                if self.name in req_fields:
                    # TODO: We might have to handle the whole thing through the
                    # FieldsAggregationMetaClass, as fields can be inherited.
                    # self.null = False
                    self.blank = False

        # Adjust the name of this field to reflect the language
        self.attname = build_localized_fieldname(self.translated_field.name, language)
        self.name = self.attname
        if self.translated_field.db_column:
            self.db_column = build_localized_fieldname(self.translated_field.db_column, language)
            self.column = self.db_column

        # Copy the verbose name and append a language suffix
        # (will show up e.g. in the admin).
        self.verbose_name = build_localized_verbose_name(translated_field.verbose_name, language)

        # ForeignKey support - rewrite related_name
        if not NEW_RELATED_API and self.rel and self.related and not self.rel.is_hidden():
            import copy
            current = self.related.get_accessor_name()
            self.rel = copy.copy(self.rel)  # Since fields cannot share the same rel object.
            # self.related doesn't need to be copied, as it will be recreated in
            # ``RelatedField.do_related_class``

            if self.rel.related_name is None:
                # For implicit related_name use different query field name
                loc_related_query_name = build_localized_fieldname(
                    self.related_query_name(), self.language)
                self.related_query_name = lambda: loc_related_query_name
            self.rel.related_name = build_localized_fieldname(current, self.language)
            self.rel.field = self  # Django 1.6
            if hasattr(self.rel.to._meta, '_related_objects_cache'):
                del self.rel.to._meta._related_objects_cache
        elif NEW_RELATED_API and self.remote_field and not self.remote_field.is_hidden():
            import copy
            current = self.remote_field.get_accessor_name()
            # Since fields cannot share the same rel object:
            self.remote_field = copy.copy(self.remote_field)

            if self.remote_field.related_name is None:
                # For implicit related_name use different query field name
                loc_related_query_name = build_localized_fieldname(
                    self.related_query_name(), self.language)
                self.related_query_name = lambda: loc_related_query_name
            self.remote_field.related_name = build_localized_fieldname(current, self.language)
            self.remote_field.field = self  # Django 1.6
            if hasattr(self.remote_field.to._meta, '_related_objects_cache'):
                del self.remote_field.to._meta._related_objects_cache