Example #1
0
 def get_source(self):
     '''
     Returns source string from a ttkit unit.
     '''
     if (isinstance(self.mainunit, tsunit) and
             self.template is None and
             self.mainunit.hasplural()):
         # Need to apply special magic for plurals here
         # as there is no singlular/plural in the source string
         return join_plural([
             self.unit.source,
             self.unit.source,
         ])
     if self.is_unit_key_value():
         # Need to decode property encoded string
         if isinstance(self.mainunit, propunit):
             if self.template is not None:
                 return quote.propertiesdecode(self.template.value)
             else:
                 return quote.propertiesdecode(self.unit.name)
         if self.template is not None:
             return self.template.value
         else:
             return self.unit.name
     else:
         if self.template is not None:
             return get_string(self.template.target)
         else:
             return get_string(self.unit.source)
Example #2
0
def perform_suggestion(unit, form, request):
    """Handle suggesion saving."""
    if form.cleaned_data['target'][0] == '':
        messages.error(request, _('Your suggestion is empty!'))
        # Stay on same entry
        return False
    if not request.user.has_perm('suggestion.add', unit.translation):
        # Need privilege to add
        messages.error(
            request,
            _('You don\'t have privileges to add suggestions!')
        )
        # Stay on same entry
        return False
    if not request.user.is_authenticated:
        # Spam check
        if is_spam('\n'.join(form.cleaned_data['target']), request):
            messages.error(
                request,
                _('Your suggestion has been identified as spam!')
            )
            return False

    # Create the suggestion
    result = Suggestion.objects.add(
        unit,
        join_plural(form.cleaned_data['target']),
        request,
        request.user.has_perm('suggestion.vote', unit)
    )
    if not result:
        messages.error(request, _('Your suggestion already exists!'))
    return result
Example #3
0
def perform_suggestion(unit, form, request):
    '''
    Handle suggesion saving.
    '''
    if form.cleaned_data['target'][0] == '':
        messages.error(request, _('Your suggestion is empty!'))
        # Stay on same entry
        return False
    elif not can_suggest(request.user, unit.translation):
        # Need privilege to add
        messages.error(
            request,
            _('You don\'t have privileges to add suggestions!')
        )
        # Stay on same entry
        return False
    # Invite user to become translator if there is nobody else
    recent_changes = Change.objects.content(True).filter(
        translation=unit.translation,
    ).exclude(
        user=None
    )
    if not recent_changes.exists():
        messages.info(request, _(
            'There is currently no active translator for this '
            'translation, please consider becoming a translator '
            'as your suggestion might otherwise remain unreviewed.'
        ))
    # Create the suggestion
    Suggestion.objects.add(
        unit,
        join_plural(form.cleaned_data['target']),
        request,
    )
    return True
Example #4
0
    def translate(self, request, new_target, new_state, change_action=None,
                  propagate=True):
        """Store new translation of a unit."""
        # Fetch current copy from database and lock it for update
        self.old_unit = Unit.objects.select_for_update().get(pk=self.pk)

        # Update unit and save it
        if isinstance(new_target, six.string_types):
            self.target = new_target
            not_empty = bool(new_target)
        else:
            self.target = join_plural(new_target)
            not_empty = bool(max(new_target))

        # Newlines fixup
        if 'dos-eol' in self.all_flags:
            self.target = NEWLINES.sub('\r\n', self.target)

        if not_empty:
            self.state = new_state
        else:
            self.state = STATE_EMPTY
        saved = self.save_backend(
            request,
            change_action=change_action,
            propagate=propagate
        )
        if (propagate and request and
                self.target != self.old_unit.target and
                self.state >= STATE_TRANSLATED):
            update_memory(request.user, self)

        return saved
Example #5
0
def perform_suggestion(unit, form, request):
    """
    Handle suggesion saving.
    """
    if form.cleaned_data["target"][0] == "":
        messages.error(request, _("Your suggestion is empty!"))
        # Stay on same entry
        return False
    elif not request.user.has_perm("trans.add_suggestion"):
        # Need privilege to add
        messages.error(request, _("You don't have privileges to add suggestions!"))
        # Stay on same entry
        return False
    # Invite user to become translator if there is nobody else
    recent_changes = Change.objects.content(True).filter(translation=unit.translation).exclude(user=None)
    if not recent_changes.exists():
        messages.info(
            request,
            _(
                "There is currently no active translator for this "
                "translation, please consider becoming a translator "
                "as your suggestion might otherwise remain unreviewed."
            ),
        )
    # Create the suggestion
    Suggestion.objects.add(unit, join_plural(form.cleaned_data["target"]), request)
    return True
Example #6
0
def perform_suggestion(unit, form, request):
    """Handle suggesion saving."""
    if form.cleaned_data['target'][0] == '':
        messages.error(request, _('Your suggestion is empty!'))
        # Stay on same entry
        return False
    elif not request.user.has_perm('suggestion.add', unit.translation):
        # Need privilege to add
        messages.error(
            request,
            _('You don\'t have privileges to add suggestions!')
        )
        # Stay on same entry
        return False
    elif not request.user.is_authenticated:
        # Spam check
        if is_spam('\n'.join(form.cleaned_data['target']), request):
            messages.error(
                request,
                _('Your suggestion has been identified as spam!')
            )
            return False

    # Invite user to become translator if there is nobody else
    # and the project is accepting translations
    translation = unit.translation
    if (not translation.component.suggestion_voting
            or not translation.component.suggestion_autoaccept):
        recent_changes = Change.objects.content(True).filter(
            translation=translation,
        ).exclude(
            user=None
        )
        if not recent_changes.exists():
            messages.info(request, _(
                'There is currently no active translator for this '
                'translation, please consider becoming a translator '
                'as your suggestion might otherwise remain unreviewed.'
            ))
            messages.info(request, mark_safe(
                '<a href="{0}">{1}</a>'.format(
                    escape(get_doc_url('user/translating')),
                    escape(_(
                        'See our documentation for more information '
                        'on translating using Weblate.'
                    )),
                )
            ))
    # Create the suggestion
    result = Suggestion.objects.add(
        unit,
        join_plural(form.cleaned_data['target']),
        request,
        request.user.has_perm('suggestion.vote', unit)
    )
    if not result:
        messages.error(request, _('Your suggestion already exists!'))
    return result
Example #7
0
    def translate(self, request, new_target, new_fuzzy):
        """
        Stores new translation of a unit.
        """
        # Update unit and save it
        self.target = join_plural(new_target)
        self.fuzzy = new_fuzzy
        saved = self.save_backend(request)

        return saved
Example #8
0
 def get_source(self):
     if self.template is None and self.mainunit.hasplural():
         # Need to apply special magic for plurals here
         # as there is no singlular/plural in the source string
         source = self.unit.source
         return join_plural([
             source,
             source.replace('(s)', 's'),
         ])
     return super(TSUnit, self).get_source()
Example #9
0
    def translate(self, request, new_target, new_fuzzy, change_action=None,
                  propagate=True):
        """Store new translation of a unit."""
        # Update unit and save it
        self.target = join_plural(new_target)
        self.fuzzy = new_fuzzy
        saved = self.save_backend(
            request,
            change_action=change_action,
            propagate=propagate
        )

        return saved
Example #10
0
    def translate(self, request, new_target, new_state, change_action=None,
                  propagate=True):
        """Store new translation of a unit."""
        # Fetch current copy from database and lock it for update
        self.old_unit = Unit.objects.select_for_update().get(pk=self.pk)

        # Update unit and save it
        if isinstance(new_target, six.string_types):
            self.target = new_target
            not_empty = bool(new_target)
        else:
            self.target = join_plural(new_target)
            not_empty = bool(max(new_target))
        if not_empty:
            self.state = new_state
        else:
            self.state = STATE_EMPTY
        saved = self.save_backend(
            request,
            change_action=change_action,
            propagate=propagate
        )

        return saved
Example #11
0
    def update_from_unit(self, unit, pos, created):
        """Update Unit from ttkit unit."""
        # Get unit attributes
        location = unit.get_locations()
        flags = unit.get_flags()
        target = unit.get_target()
        source = unit.get_source()
        comment = unit.get_comments()
        state = self.get_unit_state(unit, created)
        previous_source = unit.get_previous_source()
        content_hash = unit.get_content_hash()

        # Monolingual files handling (without target change)
        if unit.template is not None and target == self.target:
            if source != self.source and state == STATE_TRANSLATED:
                if self.previous_source == self.source and self.fuzzy:
                    # Source change was reverted
                    previous_source = ''
                    state = STATE_TRANSLATED
                else:
                    # Store previous source and fuzzy flag for monolingual
                    if previous_source == '':
                        previous_source = self.source
                    state = STATE_FUZZY
            else:
                # We should keep calculated flags if translation was
                # not changed outside
                previous_source = self.previous_source
                state = self.state

        # Update checks on fuzzy update or on content change
        same_content = (
            target == self.target and source == self.source
        )
        same_state = (state == self.state and not created)

        # Check if we actually need to change anything
        # pylint: disable=too-many-boolean-expressions
        if (not created and
                location == self.location and
                flags == self.flags and
                same_content and same_state and
                comment == self.comment and
                pos == self.position and
                content_hash == self.content_hash and
                previous_source == self.previous_source):
            return

        # Ensure we track source string
        source_info, source_created = Source.objects.get_or_create(
            id_hash=self.id_hash,
            component=self.translation.component
        )
        contentsum_changed = self.content_hash != content_hash

        # Store updated values
        self.position = pos
        self.location = location
        self.flags = flags
        self.source = source
        self.target = target
        self.state = state
        self.comment = comment
        self.content_hash = content_hash
        self.previous_source = previous_source
        self.priority = source_info.priority

        # Sanitize number of plurals
        if self.is_plural():
            self.target = join_plural(self.get_target_plurals())

        if created:
            unit_pre_create.send(sender=self.__class__, unit=self)

        # Save into database
        self.save(
            force_insert=created,
            backend=True,
            same_content=same_content,
            same_state=same_state,
        )

        # Create change object for new source string
        if source_created:
            Change.objects.create(
                action=Change.ACTION_NEW_SOURCE,
                unit=self,
            )
        if contentsum_changed:
            self.update_has_failing_check(recurse=False)
            self.update_has_comment()
            self.update_has_suggestion()
Example #12
0
    def update_from_unit(self, unit, pos, created):
        """Update Unit from ttkit unit."""
        component = self.translation.component
        self.is_batch_update = True
        # Get unit attributes
        location = unit.locations
        flags = unit.flags
        target = unit.target
        source = unit.source
        context = unit.context
        comment = unit.comments
        state = self.get_unit_state(unit)
        previous_source = unit.previous_source
        content_hash = unit.content_hash

        # Monolingual files handling (without target change)
        if not created and unit.template is not None and target == self.target:
            if source != self.source and state >= STATE_TRANSLATED:
                if self.previous_source == self.source and self.fuzzy:
                    # Source change was reverted
                    previous_source = ''
                    state = STATE_TRANSLATED
                else:
                    # Store previous source and fuzzy flag for monolingual
                    if previous_source == '':
                        previous_source = self.source
                    state = STATE_FUZZY
            else:
                # We should keep calculated flags if translation was
                # not changed outside
                previous_source = self.previous_source
                state = self.state

        # Update checks on fuzzy update or on content change
        same_target = target == self.target
        same_source = (source == self.source and context == self.context)
        same_state = (state == self.state and flags == self.flags)

        # Check if we actually need to change anything
        # pylint: disable=too-many-boolean-expressions
        if (location == self.location and
                flags == self.flags and
                same_source and same_target and same_state and
                comment == self.comment and
                pos == self.position and
                content_hash == self.content_hash and
                previous_source == self.previous_source):
            return

        # Ensure we track source string
        source_info, source_created = component.get_source(self.id_hash)

        self.__dict__['source_info'] = source_info

        # Store updated values
        self.position = pos
        self.location = location
        self.flags = flags
        self.source = source
        self.target = target
        self.state = state
        self.context = context
        self.comment = comment
        self.content_hash = content_hash
        self.previous_source = previous_source
        self.priority = source_info.priority

        # Sanitize number of plurals
        if self.is_plural():
            self.target = join_plural(self.get_target_plurals())

        if created:
            unit_pre_create.send(sender=self.__class__, unit=self)

        # Save into database
        self.save(
            force_insert=created,
            same_content=same_source and same_target,
            same_state=same_state,
        )

        # Create change object for new source string
        if source_created:
            Change.objects.create(
                action=Change.ACTION_NEW_SOURCE,
                unit=self,
            )

        # Track updated sources for source checks
        if source_created or not same_source:
            component.updated_sources[self.id_hash] = self
Example #13
0
def translate(request, project, subproject, lang):
    obj = get_object_or_404(Translation, language__code = lang, subproject__slug = subproject, subproject__project__slug = project, enabled = True)

    if obj.subproject.locked:
        messages.error(request, _('This translation is currently locked for updates!'))

    if request.user.is_authenticated():
        profile = request.user.get_profile()
    else:
        profile = None

    secondary = None
    unit = None

    rqtype, direction, pos, search_query, search_exact, search_source, search_target, search_context, search_url = parse_search_url(request)

    # Any form submitted?
    if request.method == 'POST':
        form = TranslationForm(request.POST)
        if form.is_valid() and not obj.subproject.locked:
            # Check whether translation is not outdated
            obj.check_sync()
            try:
                try:
                    unit = Unit.objects.get(checksum = form.cleaned_data['checksum'], translation = obj)
                except Unit.MultipleObjectsReturned:
                    # Possible temporary inconsistency caused by ongoing update of repo,
                    # let's pretend everyting is okay
                    unit = Unit.objects.filter(checksum = form.cleaned_data['checksum'], translation = obj)[0]
                if 'suggest' in request.POST:
                    # Handle suggesion saving
                    user = request.user
                    if isinstance(user, AnonymousUser):
                        user = None
                    if form.cleaned_data['target'] == len(form.cleaned_data['target']) * ['']:
                        messages.error(request, _('Your suggestion is empty!'))
                        # Stay on same entry
                        return HttpResponseRedirect('%s?type=%s&pos=%d&dir=stay%s' % (
                            obj.get_translate_url(),
                            rqtype,
                            pos,
                            search_url
                        ))
                    Suggestion.objects.create(
                        target = join_plural(form.cleaned_data['target']),
                        checksum = unit.checksum,
                        language = unit.translation.language,
                        project = unit.translation.subproject.project,
                        user = user)
                    # Update suggestion stats
                    if profile is not None:
                        profile.suggested += 1
                        profile.save()
                elif not request.user.is_authenticated():
                    # We accept translations only from authenticated
                    messages.error(request, _('You need to log in to be able to save translations!'))
                elif not request.user.has_perm('trans.save_translation'):
                    # Need privilege to save
                    messages.error(request, _('You don\'t have privileges to save translations!'))
                else:
                    # Remember old checks
                    oldchecks = set(unit.active_checks().values_list('check', flat = True))
                    # Update unit and save it
                    unit.target = join_plural(form.cleaned_data['target'])
                    unit.fuzzy = form.cleaned_data['fuzzy']
                    unit.save_backend(request)
                    # Update stats
                    profile.translated += 1
                    profile.save()
                    # Get new set of checks
                    newchecks = set(unit.active_checks().values_list('check', flat = True))
                    # Did we introduce any new failures?
                    if newchecks > oldchecks:
                        # Show message to user
                        messages.error(request, _('Some checks have failed on your translation!'))
                        # Stay on same entry
                        return HttpResponseRedirect('%s?type=%s&pos=%d&dir=stay%s' % (
                            obj.get_translate_url(),
                            rqtype,
                            pos,
                            search_url
                        ))

                # Redirect to next entry
                return HttpResponseRedirect('%s?type=%s&pos=%d%s' % (
                    obj.get_translate_url(),
                    rqtype,
                    pos,
                    search_url
                ))
            except Unit.DoesNotExist:
                logger.error('message %s disappeared!', form.cleaned_data['checksum'])
                messages.error(request, _('Message you wanted to translate is no longer available!'))

    # Handle translation merging
    if 'merge' in request.GET:
        if not request.user.has_perm('trans.save_translation'):
            # Need privilege to save
            messages.error(request, _('You don\'t have privileges to save translations!'))
        else:
            try:
                mergeform = MergeForm(request.GET)
                if mergeform.is_valid():
                    try:
                        unit = Unit.objects.get(checksum = mergeform.cleaned_data['checksum'], translation = obj)
                    except Unit.MultipleObjectsReturned:
                        # Possible temporary inconsistency caused by ongoing update of repo,
                        # let's pretend everyting is okay
                        unit = Unit.objects.filter(checksum = mergeform.cleaned_data['checksum'], translation = obj)[0]

                    merged = Unit.objects.get(pk = mergeform.cleaned_data['merge'])

                    if unit.checksum != merged.checksum:
                        messages.error(request, _('Can not merge different messages!'))
                    else:
                        unit.target = merged.target
                        unit.fuzzy = merged.fuzzy
                        unit.save_backend(request)
                        # Update stats
                        profile.translated += 1
                        profile.save()
                        # Redirect to next entry
                        return HttpResponseRedirect('%s?type=%s&pos=%d%s' % (
                            obj.get_translate_url(),
                            rqtype,
                            pos,
                            search_url
                        ))
            except Unit.DoesNotExist:
                logger.error('message %s disappeared!', form.cleaned_data['checksum'])
                messages.error(request, _('Message you wanted to translate is no longer available!'))

    # Handle accepting/deleting suggestions
    if not obj.subproject.locked and ('accept' in request.GET or 'delete' in request.GET):
        # Check for authenticated users
        if not request.user.is_authenticated():
            messages.error(request, _('You need to log in to be able to manage suggestions!'))
            return HttpResponseRedirect('%s?type=%s&pos=%d&dir=stay%s' % (
                obj.get_translate_url(),
                rqtype,
                pos,
                search_url
            ))

        # Parse suggestion ID
        if 'accept' in request.GET:
            if not request.user.has_perm('trans.accept_suggestion'):
                messages.error(request, _('You do not have privilege to accept suggestions!'))
                return HttpResponseRedirect('%s?type=%s&pos=%d&dir=stay%s' % (
                    obj.get_translate_url(),
                    rqtype,
                    pos,
                    search_url
                ))
            sugid = request.GET['accept']
        else:
            if not request.user.has_perm('trans.delete_suggestion'):
                messages.error(request, _('You do not have privilege to delete suggestions!'))
                return HttpResponseRedirect('%s?type=%s&pos=%d&dir=stay%s' % (
                    obj.get_translate_url(),
                    rqtype,
                    pos,
                    search_url
                ))
            sugid = request.GET['delete']
        try:
            sugid = int(sugid)
            suggestion = Suggestion.objects.get(pk = sugid)
        except:
            suggestion = None

        if suggestion is not None:
            if 'accept' in request.GET:
                # Accept suggesiont
                suggestion.accept(request)
            # Delete suggestion in both cases (accepted ones are no longer needed)
            suggestion.delete()
        else:
            messages.error(request, _('Invalid suggestion!'))

        # Redirect to same entry for possible editing
        return HttpResponseRedirect('%s?type=%s&pos=%d&dir=stay%s' % (
            obj.get_translate_url(),
            rqtype,
            pos,
            search_url
        ))

    reviewform = ReviewForm(request.GET)

    if reviewform.is_valid():
        allunits = obj.unit_set.review(reviewform.cleaned_data['date'], request.user)
        # Review
        if direction == 'stay':
            units = allunits.filter(position = pos)
        elif direction == 'back':
            units = allunits.filter(position__lt = pos).order_by('-position')
        else:
            units = allunits.filter(position__gt = pos)
    elif search_query != '':
        # Apply search conditions
        if search_exact:
            query = Q()
            if search_source:
                query |= Q(source = search_query)
            if search_target:
                query |= Q(target = search_query)
            if search_context:
                query |= Q(context = search_query)
            allunits = obj.unit_set.filter(query)
        else:
            allunits = obj.unit_set.search(search_query, search_source, search_context, search_target)
        if direction == 'stay':
            units = obj.unit_set.filter(position = pos)
        elif direction == 'back':
            units = allunits.filter(position__lt = pos).order_by('-position')
        else:
            units = allunits.filter(position__gt = pos)
    else:
        allunits = obj.unit_set.filter_type(rqtype)
        # What unit set is about to show
        if direction == 'stay':
            units = obj.unit_set.filter(position = pos)
        elif direction == 'back':
            units = allunits.filter(position__lt = pos).order_by('-position')
        else:
            units = allunits.filter(position__gt = pos)


    # If we failed to get unit above or on no POST
    if unit is None:
        # Grab actual unit
        try:
            unit = units[0]
        except IndexError:
            messages.info(request, _('You have reached end of translating.'))
            return HttpResponseRedirect(obj.get_absolute_url())

        # Show secondary languages for logged in users
        if profile:
            secondary = Unit.objects.filter(
                checksum = unit.checksum,
                translated = True,
                translation__subproject__project = unit.translation.subproject.project,
                translation__language__in = profile.secondary_languages.exclude(id = unit.translation.language.id)
            )
            # distinct('target') works with Django 1.4 so let's emulate that
            # based on presumption we won't get too many results
            targets = {}
            res = []
            for s in secondary:
                if s.target in targets:
                    continue
                targets[s.target] = 1
                res.append(s)
            secondary = res

        # Prepare form
        form = TranslationForm(initial = {
            'checksum': unit.checksum,
            'target': (unit.translation.language, unit.get_target_plurals()),
            'fuzzy': unit.fuzzy,
        })

    total = obj.unit_set.all().count()
    filter_count = allunits.count()

    return render_to_response('translate.html', RequestContext(request, {
        'object': obj,
        'unit': unit,
        'changes': unit.change_set.all()[:10],
        'total': total,
        'type': rqtype,
        'filter_name': get_filter_name(rqtype, search_query),
        'filter_count': filter_count,
        'filter_pos': filter_count + 1 - units.count(),
        'form': form,
        'target_language': obj.language.code,
        'secondary': secondary,
        'search_query': search_query,
        'search_url': search_url,
        'search_query': search_query,
        'search_source': bool2str(search_source),
        'search_exact': bool2str(search_exact),
        'search_target': bool2str(search_target),
        'search_context': bool2str(search_context),
    }))
Example #14
0
    def update_from_unit(self, unit, pos, created):
        """Update Unit from ttkit unit."""
        translation = self.translation
        component = translation.component
        self.is_batch_update = True
        self.source_updated = True
        # Get unit attributes
        try:
            location = unit.locations
            flags = unit.flags
            source = unit.source
            self.check_valid(split_plural(source))
            if not translation.is_template and translation.is_source:
                # Load target from source string for bilingual source translations
                target = source
            else:
                target = unit.target
                self.check_valid(split_plural(target))
            context = unit.context
            self.check_valid([context])
            note = unit.notes
            previous_source = unit.previous_source
            content_hash = unit.content_hash
        except Exception as error:
            report_error(cause="Unit update error")
            translation.component.handle_parse_error(error, translation)

        # Ensure we track source string for bilingual, this can not use
        # Unit.is_source as that depends on source_unit attribute, which
        # we set here
        if not translation.is_source:
            source_unit = component.get_source(
                self.id_hash,
                create={
                    "source": source,
                    "target": source,
                    "context": context,
                    "content_hash": calculate_hash(source, context),
                    "position": pos,
                    "note": note,
                    "location": location,
                    "flags": flags,
                },
            )
            if (
                not source_unit.source_updated
                and not component.has_template()
                and (
                    pos != source_unit.position
                    or location != source_unit.location
                    or flags != source_unit.flags
                    or note != source_unit.note
                )
            ):
                source_unit.position = pos
                source_unit.source_updated = True
                source_unit.location = location
                source_unit.flags = flags
                source_unit.note = note
                source_unit.save(
                    update_fields=["position", "location", "flags", "note"],
                    same_content=True,
                    same_state=True,
                )
            self.source_unit = source_unit

        # Calculate state
        state = self.get_unit_state(unit, flags)
        self.original_state = self.get_unit_state(unit, None)

        # Has source changed
        same_source = source == self.source and context == self.context

        # Monolingual files handling (without target change)
        if (
            not created
            and state != STATE_READONLY
            and unit.template is not None
            and target == self.target
        ):
            if not same_source and state in (STATE_TRANSLATED, STATE_APPROVED):
                if self.previous_source == self.source and self.fuzzy:
                    # Source change was reverted
                    previous_source = ""
                    state = STATE_TRANSLATED
                else:
                    # Store previous source and fuzzy flag for monolingual
                    if previous_source == "":
                        previous_source = self.source
                    state = STATE_FUZZY
            elif self.state in (STATE_FUZZY, STATE_APPROVED):
                # We should keep calculated flags if translation was
                # not changed outside
                previous_source = self.previous_source
                state = self.state

        # Update checks on fuzzy update or on content change
        same_target = target == self.target
        same_state = state == self.state and flags == self.flags

        # Check if we actually need to change anything
        # pylint: disable=too-many-boolean-expressions
        if (
            location == self.location
            and flags == self.flags
            and same_source
            and same_target
            and same_state
            and note == self.note
            and pos == self.position
            and content_hash == self.content_hash
            and previous_source == self.previous_source
        ):
            return

        # Store updated values
        self.position = pos
        self.location = location
        self.flags = flags
        self.source = source
        self.target = target
        self.state = state
        self.context = context
        self.note = note
        self.content_hash = content_hash
        self.previous_source = previous_source
        self.update_priority(save=False)

        # Sanitize number of plurals
        if self.is_plural:
            self.target = join_plural(self.get_target_plurals())

        if created:
            unit_pre_create.send(sender=self.__class__, unit=self)

        # Save into database
        self.save(
            force_insert=created,
            same_content=same_source and same_target,
            same_state=same_state,
        )
        # Track updated sources for source checks
        if translation.is_template:
            component.updated_sources[self.id_hash] = self
        # Indicate source string change
        if not same_source and previous_source:
            Change.objects.create(
                unit=self,
                action=Change.ACTION_SOURCE_CHANGE,
                old=previous_source,
                target=self.source,
            )
Example #15
0
    def update_from_unit(self, unit, pos, created):
        """Update Unit from ttkit unit."""
        # Get unit attributes
        location = unit.get_locations()
        flags = unit.get_flags()
        target = unit.get_target()
        source = unit.get_source()
        comment = unit.get_comments()
        state = self.get_unit_state(unit, created)
        previous_source = unit.get_previous_source()
        content_hash = unit.get_content_hash()

        # Monolingual files handling (without target change)
        if unit.template is not None and target == self.target:
            if source != self.source and state == STATE_TRANSLATED:
                if self.previous_source == self.source and self.fuzzy:
                    # Source change was reverted
                    previous_source = ''
                    state = STATE_TRANSLATED
                else:
                    # Store previous source and fuzzy flag for monolingual
                    if previous_source == '':
                        previous_source = self.source
                    state = STATE_FUZZY
            else:
                # We should keep calculated flags if translation was
                # not changed outside
                previous_source = self.previous_source
                state = self.state

        # Update checks on fuzzy update or on content change
        same_content = (target == self.target and source == self.source)
        same_state = (state == self.state and not created)

        # Check if we actually need to change anything
        # pylint: disable=too-many-boolean-expressions
        if (not created and location == self.location and flags == self.flags
                and same_content and same_state and comment == self.comment
                and pos == self.position and content_hash == self.content_hash
                and previous_source == self.previous_source):
            return

        # Ensure we track source string
        source_info, source_created = Source.objects.get_or_create(
            id_hash=self.id_hash, component=self.translation.component)
        contentsum_changed = self.content_hash != content_hash

        # Store updated values
        self.position = pos
        self.location = location
        self.flags = flags
        self.source = source
        self.target = target
        self.state = state
        self.comment = comment
        self.content_hash = content_hash
        self.previous_source = previous_source
        self.priority = source_info.priority

        # Sanitize number of plurals
        if self.is_plural():
            self.target = join_plural(self.get_target_plurals())

        if created:
            unit_pre_create.send(sender=self.__class__, unit=self)

        # Save into database
        self.save(
            force_insert=created,
            backend=True,
            same_content=same_content,
            same_state=same_state,
        )

        # Create change object for new source string
        if source_created:
            Change.objects.create(
                action=Change.ACTION_NEW_SOURCE,
                unit=self,
            )
        if contentsum_changed:
            self.update_has_failing_check(recurse=False)
            self.update_has_comment()
            self.update_has_suggestion()
Example #16
0
    def update_from_unit(self, unit, pos, created):
        """Update Unit from ttkit unit."""
        component = self.translation.component
        self.is_batch_update = True
        # Get unit attributes
        try:
            location = unit.locations
            flags = unit.flags
            target = unit.target
            source = unit.source
            context = unit.context
            note = unit.notes
            previous_source = unit.previous_source
            content_hash = unit.content_hash
        except Exception as error:
            self.translation.component.handle_parse_error(
                error, self.translation)

        # Ensure we track source string for bilingual
        if not self.translation.is_source:
            source_unit = component.get_source(
                self.id_hash,
                source=source,
                target=source,
                context=context,
                content_hash=calculate_hash(source, context),
                position=0,
                location=location,
                flags=flags,
            )
            self.extra_context = source_unit.extra_context
            self.extra_flags = source_unit.extra_flags

        # Calculate state
        state = self.get_unit_state(unit, flags)
        self.original_state = self.get_unit_state(unit, None)

        # Monolingual files handling (without target change)
        if not created and unit.template is not None and target == self.target:
            if source != self.source and state >= STATE_TRANSLATED:
                if self.previous_source == self.source and self.fuzzy:
                    # Source change was reverted
                    previous_source = ''
                    state = STATE_TRANSLATED
                else:
                    # Store previous source and fuzzy flag for monolingual
                    if previous_source == '':
                        previous_source = self.source
                    state = STATE_FUZZY
            elif self.state in (STATE_FUZZY, STATE_APPROVED):
                # We should keep calculated flags if translation was
                # not changed outside
                previous_source = self.previous_source
                state = self.state

        # Update checks on fuzzy update or on content change
        same_target = target == self.target
        same_source = source == self.source and context == self.context
        same_state = state == self.state and flags == self.flags

        # Check if we actually need to change anything
        # pylint: disable=too-many-boolean-expressions
        if (location == self.location and flags == self.flags and same_source
                and same_target and same_state and note == self.note
                and pos == self.position and content_hash == self.content_hash
                and previous_source == self.previous_source):
            return

        # Store updated values
        self.position = pos
        self.location = location
        self.flags = flags
        self.source = source
        self.target = target
        self.state = state
        self.context = context
        self.note = note
        self.content_hash = content_hash
        self.previous_source = previous_source
        self.update_priority(save=False)

        # Sanitize number of plurals
        if self.is_plural():
            self.target = join_plural(self.get_target_plurals())

        if created:
            unit_pre_create.send(sender=self.__class__, unit=self)

        # Save into database
        self.save(
            force_insert=created,
            same_content=same_source and same_target,
            same_state=same_state,
        )
        # Track updated sources for source checks
        if self.translation.is_template:
            component.updated_sources[self.id_hash] = self