def rewrite_lookup_key(model, lookup_key):
    translatable_fields = get_translatable_fields_for_model(model)
    if translatable_fields is not None:
        pieces = lookup_key.split('__')
        # 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:
            lookup_key = build_localized_fieldname(pieces[0], get_language())

            remaining_lookup = '__'.join(pieces[1:])
            if remaining_lookup:
                lookup_key = '%s__%s' % (lookup_key, remaining_lookup)

    pieces = lookup_key.split('__')
    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)
        for field_to_trans, transmodel in fields_to_trans_models:
            if pieces[0] == field_to_trans:
                sub_lookup = '__'.join(pieces[1:])
                if sub_lookup:
                    sub_lookup = rewrite_lookup_key(transmodel, sub_lookup)
                    lookup_key = '%s__%s' % (pieces[0], sub_lookup)
                break

    return lookup_key
Example #2
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 cache_name(self):
     """
     Used in django 1.x
     """
     lang = get_language()
     cache = build_localized_fieldname(self.accessor, lang)
     return "_%s_cache" % cache
 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 val is not None and 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()
         return default
Example #5
0
def formfield_exclude_irrelevant(db_field, **kwargs):
    """ only localized fields """
    from modeltranslation.translator import translator
    from modeltranslation.utils import get_language
    trans_opts = translator.get_options_for_model(db_field.model)
    if db_field.name in trans_opts.fields:
        return None
    if 'field' in kwargs:
        field = kwargs['field']
    else:
        field = db_field.formfield(**kwargs)
    if hasattr(db_field, 'translated_field'):
        if db_field.name.endswith('_{0}'.format(get_language())):
            field.required = True
            field.widget.attrs['class'] = '{0} {1}'.format(
                getattr(field.widget.attrs, 'class', ''),
                'language-depended'
            )
            field.help_text = string_concat(
                field.help_text,
                _(' '),
                _('This field dependent on current language.')
            )
        else:
            return None
    return field
Example #6
0
def _validate_slugs(page):
    """
    Determine whether the given slug is available for use on a child page of
    parent_page.
    """
    parent_page = page.get_parent()

    if parent_page is None:
        # the root page's slug can be whatever it likes...
        return {}

    # Save the current active language
    current_language = get_language()

    siblings = page.get_siblings(inclusive=False).specific()

    errors = {}

    for language in mt_settings.AVAILABLE_LANGUAGES:
        # Temporarily activate every language because even though there might
        # be no repeated value for slug_pt the fallback of an empty slug could
        # already be in use

        trans_real.activate(language)

        siblings_slugs = [sibling.slug for sibling in siblings]

        if page.specific.slug in siblings_slugs:
            errors[build_localized_fieldname('slug', language)] = _("This slug is already in use")

    # Re-enable the original language
    trans_real.activate(current_language)

    return errors
def _validate_slugs(page):
    """
    Determine whether the given slug is available for use on a child page of
    parent_page.
    """
    parent_page = page.get_parent()

    if parent_page is None:
        # the root page's slug can be whatever it likes...
        return {}

    # Save the current active language
    current_language = get_language()

    siblings = page.get_siblings(inclusive=False).specific()

    errors = {}

    for language in mt_settings.AVAILABLE_LANGUAGES:
        # Temporarily activate every language because even though there might
        # be no repeated value for slug_pt the fallback of an empty slug could
        # already be in use

        trans_real.activate(language)

        siblings_slugs = [sibling.slug for sibling in siblings]

        if page.specific.slug in siblings_slugs:
            errors[build_localized_fieldname('slug', language)] = _("This slug is already in use")

    # Re-enable the original language
    trans_real.activate(current_language)

    return errors
 def pre_save(self, model_instance, add):
     val = super(TranslationField, self).pre_save(model_instance, add)
     if get_language() == self.language and not add:
         # Rule is: 3. Assigning a value to a translation field of the
         # default language also updates the original field
         model_instance.__dict__[self.translated_field.name] = val
     return val
Example #9
0
 def keywords_list_language(self, lang=None):
     if not lang:
         lang = get_language() or DEFAULT_LANGUAGE
     keywords = []
     list = self.keywords_list()
     for k in list:
         keywords.append([k[0][lang], k[1], k[2], k[0][lang].split('>')[-1].strip()])
     return keywords
Example #10
0
 def __set__(self, instance, value):
     lang = get_language()
     loc_field_name = build_localized_fieldname(self.name, lang)
     # also update the translation field of the current language
     setattr(instance, loc_field_name, value)
     # update the original field via the __dict__ to prevent calling the
     # descriptor
     instance.__dict__[self.name] = value
Example #11
0
 def keywords_list_language(self, lang=None):
     if not lang:
         lang = get_language() or DEFAULT_LANGUAGE
     keywords = []
     list = self.keywords_list()
     for k in list:
         keywords.append([k[0][lang], k[1], k[2], k[0][lang].split('>')[-1].strip()])
     return keywords
 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 __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 __set__(self, instance, value):
     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
     lang = get_language()
     loc_field_name = build_localized_fieldname(self.field.name, lang)
     # also update the translation field of the current language
     setattr(instance, loc_field_name, value)
Example #15
0
 def keywords_list_clean(self, lang=None):
     if not lang:
         lang = get_language() or DEFAULT_LANGUAGE
     keywords = []
     if self.gemetkeywords is not None and self.gemetkeywords != '':
         list = json.loads(self.gemetkeywords)
         for k in list:
             keywords.append(k[0][lang].split('>')[-1].strip())
     return keywords
Example #16
0
 def keywords_list_clean(self, lang=None):
     if not lang:
         lang = get_language() or DEFAULT_LANGUAGE
     keywords = []
     if self.gemetkeywords is not None and self.gemetkeywords != '':
         list = json.loads(self.gemetkeywords)
         for k in list:
             keywords.append(k[0][lang].split('>')[-1].strip())
     return keywords
Example #17
0
 def __set__(self, instance, value):
     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
     lang = get_language()
     loc_field_name = build_localized_fieldname(self.field.name, lang)
     # also update the translation field of the current language
     setattr(instance, loc_field_name, value)
Example #18
0
 def save_form_data(self, instance, data):
     # Allow 3rd-party apps forms to be saved using only translated field name.
     # When translated field (e.g. 'name') is specified and translation field (e.g. 'name_en')
     # not, we assume that form was saved without knowledge of modeltranslation and we make
     # things right:
     # Translated field is saved first, settings respective translation field value. Then
     # translation field is being saved without value - and we handle this here (only for
     # active language).
     if self.language == get_language() and getattr(instance, self.name) and not data:
         return
     super(TranslationField, self).save_form_data(instance, data)
Example #19
0
def lbyl(terms, lang_priority = None):
    terms_dict = {}
    if not lang_priority:
        lang_priority = [get_language(), DEFAULT_LANGUAGE]
    for i in terms:
        terms_dict[i.language] = i
    for lang in lang_priority:
        value = terms_dict.get(lang)
        if value is not None:
            return value
    return terms.first
Example #20
0
def lbyl(terms, lang_priority = None):
    terms_dict = {}
    if not lang_priority:
        lang_priority = [get_language(), DEFAULT_LANGUAGE]
    for i in terms:
        terms_dict[i.language] = i
    for lang in lang_priority:
        value = terms_dict.get(lang)
        if value is not None:
            return value
    return terms.first
Example #21
0
 def pre_save(self, model_instance, add):
     """
     Returns slug field's value using the language set by `WAGTAILMODELTRANSLATION_ORIGINAL_SLUG_LANGUAGE`
     just before saving.
     """
     current_language = get_language()
     # using ORIGINAL_SLUG_LANGUAGE makes Page's slug value consistent
     trans_real.activate(reference_slug_language)
     value = getattr(model_instance, self.attname)
     trans_real.activate(current_language)
     return value
Example #22
0
 def save_form_data(self, instance, data):
     # Allow 3rd-party apps forms to be saved using only translated field name.
     # When translated field (e.g. 'name') is specified and translation field (e.g. 'name_en')
     # not, we assume that form was saved without knowledge of modeltranslation and we make
     # things right:
     # Translated field is saved first, settings respective translation field value. Then
     # translation field is being saved without value - and we handle this here (only for
     # active language).
     if self.language == get_language() and getattr(instance, self.name) and not data:
         return
     super(TranslationField, self).save_form_data(instance, data)
 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
Example #24
0
 def __get__(self, instance, owner):
     if not instance:
         raise ValueError(u"Translation field '%s' can only be accessed "
                          "via an instance not via a class." % self.name)
     loc_field_name = build_localized_fieldname(self.name, get_language())
     if hasattr(instance, loc_field_name):
         if getattr(instance, loc_field_name):
             return getattr(instance, loc_field_name)
         elif self.fallback_value is None:
             return self.get_default_instance(instance)
         else:
             return self.fallback_value
Example #25
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
Example #26
0
 def _patch_prepopulated_fields(self):
     if self.prepopulated_fields:
         # TODO: Perhaps allow to configure which language the slug should be based on?
         lang = get_language()
         prepopulated_fields_new = dict(self.prepopulated_fields)
         translation_fields = []
         for k, v in self.prepopulated_fields.items():
             for i in v:
                 if i in self.trans_opts.fields.keys():
                     translation_fields.append(build_localized_fieldname(i, lang))
             prepopulated_fields_new[k] = tuple(translation_fields)
         self.prepopulated_fields = prepopulated_fields_new
Example #27
0
 def _patch_prepopulated_fields(self):
     if self.prepopulated_fields:
         # Default to the active language, unless explicitly configured
         lang = PREPOPULATE_LANGUAGE or get_language()
         prepopulated_fields_new = dict(self.prepopulated_fields)
         translation_fields = []
         for k, v in self.prepopulated_fields.items():
             for i in v:
                 if i in self.trans_opts.fields.keys():
                     translation_fields.append(build_localized_fieldname(i, lang))
             prepopulated_fields_new[k] = tuple(translation_fields)
         self.prepopulated_fields = prepopulated_fields_new
Example #28
0
 def render_change_form(self,
                        request,
                        context,
                        add=False,
                        change=False,
                        form_url='',
                        obj=None):
     context['selected_language'] = get_language()
     context['languages'] = self.get_language_tabs(request)
     #context['base_template'] = self.get_change_form_base_template()
     return super(ContentAdmin,
                  self).render_change_form(request, context, add,
                                           change, form_url, obj)
Example #29
0
 def __get__(self, instance, owner):
     if not instance:
         raise ValueError(u"Translation field '%s' can only be accessed "
                           "via an instance not via a class." % self.name)
     loc_field_name = build_localized_fieldname(self.name,
                                                get_language())
     if hasattr(instance, loc_field_name):
         if getattr(instance, loc_field_name):
             return getattr(instance, loc_field_name)
         elif self.fallback_value is None:
             return self.get_default_instance(instance)
         else:
             return self.fallback_value
Example #30
0
 def _patch_prepopulated_fields(self):
     if self.prepopulated_fields:
         # TODO: Perhaps allow to configure which language the slug should be based on?
         lang = get_language()
         prepopulated_fields_new = dict(self.prepopulated_fields)
         translation_fields = []
         for k, v in self.prepopulated_fields.items():
             for i in v:
                 if i in self.trans_opts.fields.keys():
                     translation_fields.append(
                         build_localized_fieldname(i, lang))
             prepopulated_fields_new[k] = tuple(translation_fields)
         self.prepopulated_fields = prepopulated_fields_new
Example #31
0
def currency_rates():
    current_lang = get_language()
    currencies = Currency.objects.all()
    currencies_other = []
    currency_current = None
    for currency in currencies:
        if currency.lang == current_lang:
            currency_current = currency
        else:
            currencies_other.append(currency)
    if currency_current is None:
        currency_current = currencies_other.pop(0)
    return dict(current=currency_current, currencies=currencies_other)
 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)
         val = getattr(instance, loc_field_name, None)
         # Here we check only for None and '', because e.g. 0 should not fall back.
         if val is not None and val != '':
             return val
     if self.fallback_value is None or not mt_settings.ENABLE_FALLBACKS:
         return self.field.get_default()
     else:
         return self.fallback_value
def _new_get_site_root_paths(self, request=None):
    """
    Return localized site_root_paths, using the cached copy on the
    request object if available and if language is the same.
    """
    # if we have a request, use that to cache site_root_paths; otherwise, use self
    current_language = get_language()
    cache_object = request if request else self
    if not hasattr(cache_object, '_wagtail_cached_site_root_paths_language') or \
            cache_object._wagtail_cached_site_root_paths_language != current_language:
        cache_object._wagtail_cached_site_root_paths_language = current_language
        cache_object._wagtail_cached_site_root_paths = _localized_site_get_site_root_paths()

    return cache_object._wagtail_cached_site_root_paths
Example #34
0
 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 _new_get_site_root_paths(self, request=None):
    """
    Return localized site_root_paths, using the cached copy on the
    request object if available and if language is the same.
    """
    # if we have a request, use that to cache site_root_paths; otherwise, use self
    current_language = get_language()
    cache_object = request if request else self
    if not hasattr(cache_object, '_wagtail_cached_site_root_paths_language') or \
            cache_object._wagtail_cached_site_root_paths_language != current_language:
        cache_object._wagtail_cached_site_root_paths_language = current_language
        cache_object._wagtail_cached_site_root_paths = _localized_site_get_site_root_paths()

    return cache_object._wagtail_cached_site_root_paths
Example #36
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)
         val = getattr(instance, loc_field_name, None)
         # Here we check only for None and '', because e.g. 0 should not fall back.
         if val is not None and val != '':
             return val
     if self.fallback_value is None or not mt_settings.ENABLE_FALLBACKS:
         return self.field.get_default()
     else:
         return self.fallback_value
    def __call__(self, instance, *args, **kwargs):
        # when updating, save doesn't check if slug_xx has changed so it can only detect changes in slug
        # from current language. We need to ensure that if a given localized slug changes we call set_url_path
        if not instance.id:  # creating a record, wagtail will call set_url_path, nothing to do.
            return self.func(instance, *args, **kwargs)

        old_record = None
        change_url_path = change_descendant_url_path = False
        for language in mt_settings.AVAILABLE_LANGUAGES:
            localized_slug = build_localized_fieldname('slug', language)
            # similar logic used in save
            if not ('update_fields' in kwargs
                    and localized_slug not in kwargs['update_fields']):
                old_record = old_record or Page.objects.get(id=instance.id)
                if getattr(old_record, localized_slug) != getattr(
                        instance, localized_slug):
                    change_descendant_url_path = True
                    if language != get_language():
                        change_url_path = True
                        break

            # Pages may have have their url_path_xx changed upstream when a parent has its url_path changed.
            # If that's the case let's propagate the change to children
            if not change_descendant_url_path:
                localized_url_path = build_localized_fieldname(
                    'url_path', language)
                if not ('update_fields' in kwargs
                        and localized_url_path not in kwargs['update_fields']):
                    old_record = old_record or Page.objects.get(id=instance.id)
                    if getattr(old_record, localized_url_path) != getattr(
                            instance, localized_url_path):
                        change_descendant_url_path = True

        # if any language other than current language had it slug changed set_url_path will be executed
        if change_url_path:
            instance.set_url_path(instance.get_parent())

        result = self.func(instance, *args, **kwargs)

        # update children localized paths if any language had it slug changed
        if change_descendant_url_path:
            _update_translation_descendant_url_paths(old_record, instance)

        # Check if this is a root page of any sites and clear the 'wagtail_site_root_paths_XX' key if so
        if Site.objects.filter(root_page=instance).exists():
            for language in mt_settings.AVAILABLE_LANGUAGES:
                cache.delete('wagtail_site_root_paths_{}'.format(language))

        return result
def _localized_site_get_site_root_paths():
    """
    Localized version of ``Site.get_site_root_paths()``
    """
    current_language = get_language()
    cache_key = 'wagtail_site_root_paths_{}'.format(current_language)
    result = cache.get(cache_key)

    if result is None:
        result = [(site.id, site.root_page.url_path, site.root_url)
                  for site in Site.objects.select_related(
                      'root_page').order_by('-root_page__url_path')]
        cache.set(cache_key, result, 3600)

    return result
Example #39
0
 def __get__(self, instance, owner):
     if not instance:
         raise ValueError(
             "Translation field '%s' can only be accessed via an instance "
             "not via a class." % self.field.name)
     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)
         # Here we check only for None and '', because e.g. 0 should not fall back.
         if val is not None and val != '':
             return val
     if self.fallback_value is None:
         return self.field.get_default()
     else:
         return self.fallback_value
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 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
Example #41
0
 def __get__(self, instance, owner):
     if not instance:
         raise ValueError(
             "Translation field '%s' can only be accessed via an instance "
             "not via a class." % self.field.name)
     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)
         # Here we check only for None and '', because e.g. 0 should not fall back.
         if val is not None and val != '':
             return val
     if self.fallback_value is None:
         return self.field.get_default()
     else:
         return self.fallback_value
def _localized_site_get_site_root_paths():
    """
    Localized version of ``Site.get_site_root_paths()``
    """
    current_language = get_language()
    cache_key = 'wagtail_site_root_paths_{}'.format(current_language)
    result = cache.get(cache_key)

    if result is None:
        result = [
            (site.id, site.root_page.url_path, site.root_url)
            for site in Site.objects.select_related('root_page').order_by('-root_page__url_path')
        ]
        cache.set(cache_key, result, 3600)

    return result
Example #43
0
 def save_form_data(self, instance, data, check=True):
     # Allow 3rd-party apps forms to be saved using only translated field name.
     # When translated field (e.g. 'name') is specified and translation field (e.g. 'name_en')
     # not, we assume that form was saved without knowledge of modeltranslation and we make
     # things right:
     # Translated field is saved first, settings respective translation field value. Then
     # translation field is being saved without value - and we handle this here (only for
     # active language).
     # Questionable fields are stored in special variable, which is later handled by clean_fields
     # method on the model.
     if check and self.language == get_language() and getattr(instance, self.name) and not data:
         if not hasattr(instance, '_mt_form_pending_clear'):
             instance._mt_form_pending_clear = {}
         instance._mt_form_pending_clear[self.name] = data
     else:
         super(TranslationField, self).save_form_data(instance, data)
Example #44
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 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 save_form_data(self, instance, data, check=True):
     # Allow 3rd-party apps forms to be saved using only translated field name.
     # When translated field (e.g. 'name') is specified and translation field (e.g. 'name_en')
     # not, we assume that form was saved without knowledge of modeltranslation and we make
     # things right:
     # Translated field is saved first, settings respective translation field value. Then
     # translation field is being saved without value - and we handle this here (only for
     # active language).
     # Questionable fields are stored in special variable, which is later handled by clean_fields
     # method on the model.
     if check and self.language == get_language() and getattr(instance, self.name) and not data:
         if not hasattr(instance, '_mt_form_pending_clear'):
             instance._mt_form_pending_clear = {}
         instance._mt_form_pending_clear[self.name] = data
     else:
         super(TranslationField, self).save_form_data(instance, data)
Example #46
0
def formfield_exclude_original(db_field, **kwargs):
    """ only localized fields """
    from modeltranslation.translator import translator
    from modeltranslation.utils import get_language
    trans_opts = translator.get_options_for_model(db_field.model)
    if db_field.name in trans_opts.fields:
        return None
    if 'field' in kwargs:
        field = kwargs['field']
    else:
        field = db_field.formfield(**kwargs)
    if hasattr(db_field, 'translated_field'):
        if db_field.name.endswith('_{0}'.format(get_language())):
            field.required = True
        else:
            field.required = False
    return field
    def regex(self):
        """
        For non-default language always returns regex with langauge prefix.
        For default language returns either '', eigher '^{lang_code}/',
        depending on SOLID_I18N_HANDLE_DEFAULT_PREFIX and request url.

        If SOLID_I18N_HANDLE_DEFAULT_PREFIX == True and default langauge
        prefix is present in url, all other urls will be reversed with default
        prefix.
        Otherwise, all other urls will be reversed without default langauge
        prefix.
        """
        language_code = get_language()
        handle_default_prefix = getattr(settings, 'SOLID_I18N_HANDLE_DEFAULT_PREFIX', False)
        if language_code not in self._regex_dict:
            if language_code != settings.LANGUAGE_CODE:
                regex = '^%s/' % language_code
            elif handle_default_prefix:
                if get_language_from_path() == settings.LANGUAGE_CODE:
                    self.compiled_with_default = True
                    regex = '^%s/' % language_code
                else:
                    self.compiled_with_default = False
                    regex = ''
            else:
                regex = ''
            self._regex_dict[language_code] = re.compile(regex, re.UNICODE)
        elif handle_default_prefix and language_code == settings.LANGUAGE_CODE:
            language_from_path = get_language_from_path()
            regex = None
            if self.compiled_with_default and not language_from_path:
                # default language is compiled with prefix, but now client
                # requests the url without prefix. So compile other urls
                # without prefix.
                regex = ''
                self.compiled_with_default = False
            elif not self.compiled_with_default and language_from_path == settings.LANGUAGE_CODE:
                # default language is compiled without prefix, but now client
                # requests the url with prefix. So compile other urls
                # with prefix.
                regex = '^%s/' % language_code
                self.compiled_with_default = True
            if regex is not None:
                clear_url_caches()
                self._regex_dict[language_code] = re.compile(regex, re.UNICODE)
        return self._regex_dict[language_code]
Example #48
0
def formfield_exclude_original(db_field, **kwargs):
    """Filter form and keep only localized fields"""
    trans_opts = translator.get_options_for_model(db_field.model)
    if db_field.name in trans_opts.fields:
        return None

    if 'field' in kwargs:
        field = kwargs['field']
    else:
        field = db_field.formfield(**kwargs)

    if hasattr(db_field, 'translated_field'):
        if db_field.name.endswith('_{0}'.format(get_language())):
            field.required = True
        else:
            field.required = False

    return field
    def _compose_query_for_translated(self, lang=None):
        """
        Returns query expression for translated objects.

        If model has registered required (i.e. blank=False) fields then if all required
        translation field values of an instance are non-empty,
        the instance is considered translated. Values of non-required fields (blank=True)
        are ignored in this case.
        If all fields registered for translation are non-required, then the instance
        is considered translated if any field value is non-empty.

        Boolean fields are ignored. Of course, we might have such very rare (and unimaginable)
        case when we have only one required translation Boolean field, and if we ignore it
        for check, then the instance will be considered translated if any non-required field
        is not empty.
        """
        if not lang:
            lang = get_language()
        model_fieldnames = get_translatable_fields_for_model(self.model)
        required_fields_query = Q()
        non_required_fields_query = Q()
        for fieldname in model_fieldnames:
            localized_fieldname = build_localized_fieldname(fieldname, lang)
            field = self.model._meta.get_field(fieldname)

            if isinstance(field, (BooleanField, NullBooleanField)):
                field_q = Q()
            elif field.empty_strings_allowed:
                field_q = (~Q(**{localized_fieldname: ''}) & ~Q(**{localized_fieldname: None}))
            else:
                field_q = (~Q(**{localized_fieldname: None}))
            # Objects are considered translated if all required fields are non-empty.
            if not field.blank:
                required_fields_query &= field_q
            # If we have no required fields for translation, we should check non-required fields and
            # In this case objects are regarded as translated if any of non-required translation
            # field is non-empty.
            else:
                non_required_fields_query |= field_q

        if required_fields_query:
            return required_fields_query
        else:
            return non_required_fields_query
    def __call__(self, instance, *args, **kwargs):
        # when updating, save doesn't check if slug_xx has changed so it can only detect changes in slug
        # from current language. We need to ensure that if a given localized slug changes we call set_url_path
        if not instance.id:  # creating a record, wagtail will call set_url_path, nothing to do.
            return self.func(instance, *args, **kwargs)

        old_record = None
        change_url_path = change_descendant_url_path = False
        for language in mt_settings.AVAILABLE_LANGUAGES:
            localized_slug = build_localized_fieldname('slug', language)
            # similar logic used in save
            if not ('update_fields' in kwargs and localized_slug not in kwargs['update_fields']):
                old_record = old_record or Page.objects.get(id=instance.id)
                if getattr(old_record, localized_slug) != getattr(instance, localized_slug):
                    change_descendant_url_path = True
                    if language != get_language():
                        change_url_path = True
                        break

            # Pages may have have their url_path_xx changed upstream when a parent has its url_path changed.
            # If that's the case let's propagate the change to children
            if not change_descendant_url_path:
                localized_url_path = build_localized_fieldname('url_path', language)
                if not ('update_fields' in kwargs and localized_url_path not in kwargs['update_fields']):
                    old_record = old_record or Page.objects.get(id=instance.id)
                    if getattr(old_record, localized_url_path) != getattr(instance, localized_url_path):
                        change_descendant_url_path = True

        # if any language other than current language had it slug changed set_url_path will be executed
        if change_url_path:
            instance.set_url_path(instance.get_parent())

        result = self.func(instance, *args, **kwargs)

        # update children localized paths if any language had it slug changed
        if change_descendant_url_path:
            _update_translation_descendant_url_paths(old_record, instance)

        # Check if this is a root page of any sites and clear the 'wagtail_site_root_paths_XX' key if so
        if Site.objects.filter(root_page=instance).exists():
            for language in mt_settings.AVAILABLE_LANGUAGES:
                cache.delete('wagtail_site_root_paths_{}'.format(language))

        return result
Example #51
0
    def _patch_prepopulated_fields(self):
        def localize(sources, lang):
            "Append lang suffix (if applicable) to field list"
            def append_lang(source):
                if source in self.trans_opts.fields:
                    return build_localized_fieldname(source, lang)
                return source
            return tuple(map(append_lang, sources))

        prepopulated_fields = {}
        for dest, sources in self.prepopulated_fields.items():
            if dest in self.trans_opts.fields:
                for lang in mt_settings.AVAILABLE_LANGUAGES:
                    key = build_localized_fieldname(dest, lang)
                    prepopulated_fields[key] = localize(sources, lang)
            else:
                lang = mt_settings.PREPOPULATE_LANGUAGE or get_language()
                prepopulated_fields[dest] = localize(sources, lang)
        self.prepopulated_fields = prepopulated_fields
Example #52
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 translate(string):
    lang = get_language()

    cache_key = 'translations_{}'.format(lang)

    collect = getattr(settings, 'COLLECT_I18N_STATS', True)

    if collect:
        StringTranslation.objects.filter(key=string).update(last_used=now())

    trans_map = cache.get(cache_key, None)
    if not trans_map:
        try:
            trans_map = {
                x.key: getattr(x, 'translation_{}'.format(lang))
                or x.translation
                for x in StringTranslation.objects.all()
            }

            cache.set(cache_key, trans_map)
        except (ProgrammingError, OperationalError, AttributeError):
            return string

    # if key exist
    if string in trans_map:
        result = trans_map[string]
    else:
        try:
            StringTranslation(key=string).save()
        except IntegrityError as e:
            print('Insert failed: {}'.format(e))
        trans_map[string] = string

        cache.set(cache_key, trans_map)

        result = string

    if not isinstance(result, str):
        return string

    return result
Example #54
0
    def __mangle_field(self, name):
        model = self._model
        results = field_mangling.send(sender=self, field=name, model=model)
        results = [i[1] for i in results if i[1]]
        if results:
            # response in format tuple(priority: int, mangled_field_name: str)
            results.sort(key=lambda x: x[0], reverse=True)  # Sort by priority
            return results[0][1]

        # Backward compatibility. Deprecated:
        result = {
            'field': name,
        }
        field_conversion.send(sender=self,
                              result=result,
                              field=name,
                              model=model)
        mangled_field_name = result['field']
        if mangled_field_name != name:
            return mangled_field_name

        # django-multilingual-ext support
        if 'modeltranslation' in settings.INSTALLED_APPS:
            from modeltranslation.translator import translator, NotRegistered
            from modeltranslation.utils import get_language, build_localized_fieldname
        else:
            translator = None
        if translator:
            try:
                trans_opts = translator.get_options_for_model(model)
                if name in trans_opts.fields:
                    return build_localized_fieldname(name, get_language())
            except NotRegistered:
                pass

        if hasattr(model.objects, 'localize_fieldname'):
            return model.objects.localize_fieldname(name)

        return name
Example #55
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
     from modeltranslation.translator import translator
     current_language = get_language()
     default = NONE
     undefined = self.fallback_undefined
     if undefined is NONE:
         default = self.field.get_default()
         undefined = default
     langs = resolution_order(current_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):
             if lang != current_language and self.field.get_internal_type() in ["TextField", "CharField"]:
                 opts = translator.get_options_for_model(self.field.model)
                 if hasattr(opts, "fallback_prepend") and self.field.name in opts.fallback_prepend:
                     val = "{}{}".format(opts.fallback_prepend[self.field.name], val)
             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
Example #56
0
    def to_internal_value(self, data):
        try:
            translation_options = translator.get_options_for_model(
                self.Meta.model)
        except NotRegistered:
            return super().to_internal_value(data)

        current_language = get_language()

        for field_name in translation_options.fields.keys():
            if field_name not in data.keys():
                continue

            if not isinstance(data.get(field_name), dict):
                continue

            for lang in mt_settings.AVAILABLE_LANGUAGES:
                key = f"{field_name}_{lang}"
                data[key] = data.get(field_name, {}).get(lang, None)

            data[field_name] = data[f"{field_name}_{current_language}"]

        return super().to_internal_value(data)
 def cache_name(self):
     lang = get_language()
     cache = build_localized_fieldname(self.accessor, lang)
     return "_%s_cache" % cache