Пример #1
0
def handle_translate(obj, request, user_locked, this_unit_url, next_unit_url):
    '''
    Saves translation or suggestion to database and backend.
    '''
    # Antispam protection
    antispam = AntispamForm(request.POST)
    if not request.user.is_authenticated() and not antispam.is_valid():
        # Silently redirect to next entry
        return HttpResponseRedirect(next_unit_url)

    form = TranslationForm(request.POST)
    if not form.is_valid():
        return

    # Check whether translation is not outdated
    obj.check_sync()

    try:
        unit = Unit.objects.get_checksum(
            request,
            obj,
            form.cleaned_data['checksum'],
        )
    except (Unit.DoesNotExist, IndexError):
        return

    if 'suggest' in request.POST:
        # Handle suggesion saving
        if form.cleaned_data['target'][0] == '':
            messages.error(request, _('Your suggestion is empty!'))
            # Stay on same entry
            return HttpResponseRedirect(this_unit_url)
        # Invite user to become translator if there is nobody else
        recent_changes = Change.objects.content().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,
        )
    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!')
        )
    elif (unit.only_vote_suggestions()
            and not request.user.has_perm('trans.save_translation')):
        messages.error(
            request,
            _('Only suggestions are allowed in this translation!')
        )
    elif not user_locked:
        # Remember old checks
        oldchecks = set(
            unit.active_checks().values_list('check', flat=True)
        )

        # Save
        saved, fixups = unit.translate(
            request,
            form.cleaned_data['target'],
            form.cleaned_data['fuzzy']
        )

        # Warn about applied fixups
        if len(fixups) > 0:
            messages.info(
                request,
                _('Following fixups were applied to translation: %s') %
                ', '.join([unicode(f) for f in fixups])
            )

        # Get new set of checks
        newchecks = set(
            unit.active_checks().values_list('check', flat=True)
        )

        # Did we introduce any new failures?
        if saved and newchecks > oldchecks:
            # Show message to user
            messages.error(
                request,
                _('Some checks have failed on your translation!')
            )
            # Stay on same entry
            return HttpResponseRedirect(this_unit_url)

    # Redirect to next entry
    return HttpResponseRedirect(next_unit_url)
Пример #2
0
def translate(request, project, subproject, lang):
    '''
    Generic entry point for translating, suggesting and searching.
    '''
    obj = get_translation(request, project, subproject, lang)

    # Check locks
    project_locked, user_locked, own_lock = obj.is_locked(request, True)
    locked = project_locked or user_locked

    # Search results
    search_result = search(obj, request)

    # Handle redirects
    if isinstance(search_result, HttpResponse):
        return search_result

    # Get numer of results
    num_results = len(search_result['ids'])

    # Search offset
    try:
        offset = int(request.GET.get('offset', search_result.get('offset', 0)))
    except ValueError:
        offset = 0

    # Check boundaries
    if offset < 0 or offset >= num_results:
        messages.info(request, _('You have reached end of translating.'))
        # Delete search
        del request.session['search_%s' % search_result['search_id']]
        # Redirect to translation
        return HttpResponseRedirect(obj.get_absolute_url())

    # Some URLs we will most likely use
    base_unit_url = '%s?sid=%s&offset=' % (
        obj.get_translate_url(),
        search_result['search_id'],
    )
    this_unit_url = base_unit_url + str(offset)
    next_unit_url = base_unit_url + str(offset + 1)

    response = None

    # Any form submitted?
    if request.method == 'POST' and not project_locked:
        response = handle_translate(
            obj, request, user_locked, this_unit_url, next_unit_url
        )

    # Handle translation merging
    elif 'merge' in request.GET and not locked:
        response = handle_merge(obj, request, next_unit_url)

    # Handle accepting/deleting suggestions
    elif not locked and ('accept' in request.GET or 'delete' in request.GET):
        response = handle_suggestions(obj, request, this_unit_url)

    # Pass possible redirect further
    if response is not None:
        return response

    # Grab actual unit
    try:
        unit = obj.unit_set.get(pk=search_result['ids'][offset])
    except Unit.DoesNotExist:
        # Can happen when using SID for other translation
        messages.error(request, _('Invalid search string!'))
        return HttpResponseRedirect(obj.get_absolute_url())

    # Show secondary languages for logged in users
    if request.user.is_authenticated():
        profile = request.user.get_profile()
        secondary_langs = profile.secondary_languages.exclude(
            id=unit.translation.language.id
        )
        project = unit.translation.subproject.project
        secondary = get_distinct_translations(
            Unit.objects.filter(
                checksum=unit.checksum,
                translated=True,
                translation__subproject__project=project,
                translation__language__in=secondary_langs,
            )
        )
        antispam = None
    else:
        secondary = None
        antispam = AntispamForm()

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

    return render_to_response(
        'translate.html',
        RequestContext(
            request,
            {
                'this_unit_url': this_unit_url,
                'first_unit_url': base_unit_url + '0',
                'last_unit_url': base_unit_url + str(num_results - 1),
                'next_unit_url': next_unit_url,
                'prev_unit_url': base_unit_url + str(offset - 1),
                'object': obj,
                'unit': unit,
                'last_changes': unit.change_set.all()[:10],
                'last_changes_rss': reverse(
                    'rss-translation',
                    kwargs=obj.get_kwargs(),
                ),
                'last_changes_url': urlencode(obj.get_kwargs()),
                'total': obj.unit_set.all().count(),
                'search_id': search_result['search_id'],
                'offset': offset,
                'filter_name': search_result['name'],
                'filter_count': num_results,
                'filter_pos': offset + 1,
                'form': form,
                'antispam': antispam,
                'comment_form': CommentForm(),
                'search_form': SearchForm(),
                'update_lock': own_lock,
                'secondary': secondary,
                'locked': locked,
                'user_locked': user_locked,
                'project_locked': project_locked,
            },
        )
    )
Пример #3
0
def handle_translate(obj, request, user_locked, this_unit_url, next_unit_url):
    '''
    Saves translation or suggestion to database and backend.
    '''
    # Antispam protection
    if not request.user.is_authenticated():
        antispam = AntispamForm(request.POST)
        if not antispam.is_valid():
            # Silently redirect to next entry
            return HttpResponseRedirect(next_unit_url)

    form = TranslationForm(request.POST)
    if not form.is_valid():
        return

    # Check whether translation is not outdated
    obj.check_sync()

    try:
        unit = Unit.objects.get_checksum(
            request,
            obj,
            form.cleaned_data['checksum'],
        )
    except Unit.DoesNotExist:
        return

    if 'suggest' in request.POST:
        # Handle suggesion saving
        user = request.user
        if form.cleaned_data['target'][0] == '':
            messages.error(request, _('Your suggestion is empty!'))
            # Stay on same entry
            return HttpResponseRedirect(this_unit_url)
        # Invite user to become translator if there is nobody else
        recent_changes = Change.objects.content().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']),
            user,
        )
    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!')
        )
    elif not user_locked:
        # 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']
        saved = unit.save_backend(request)

        if saved:
            # 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(this_unit_url)

    # Redirect to next entry
    return HttpResponseRedirect(next_unit_url)
Пример #4
0
def handle_translate(translation, request, user_locked,
                     this_unit_url, next_unit_url):
    '''
    Saves translation or suggestion to database and backend.
    '''
    # Antispam protection
    antispam = AntispamForm(request.POST)
    if not antispam.is_valid():
        # Silently redirect to next entry
        return HttpResponseRedirect(next_unit_url)

    # Check whether translation is not outdated
    translation.check_sync()

    form = TranslationForm(translation, None, request.POST)
    if not form.is_valid():
        return

    unit = form.cleaned_data['unit']

    if 'suggest' in request.POST:
        return handle_translate_suggest(
            unit, form, request, this_unit_url, next_unit_url
        )
    elif not request.user.has_perm('trans.save_translation'):
        # Need privilege to save
        messages.error(
            request,
            _('You don\'t have privileges to save translations!')
        )
    elif (unit.only_vote_suggestions()
            and not request.user.has_perm('trans.save_translation')):
        messages.error(
            request,
            _('Only suggestions are allowed in this translation!')
        )
    elif not user_locked:
        # Remember old checks
        oldchecks = set(
            unit.active_checks().values_list('check', flat=True)
        )

        # Custom commit message
        if 'commit_message' in request.POST and request.POST['commit_message']:
            unit.translation.commit_message = request.POST['commit_message']
            unit.translation.save()

        # Save
        saved, fixups = unit.translate(
            request,
            form.cleaned_data['target'],
            form.cleaned_data['fuzzy']
        )

        # Warn about applied fixups
        if len(fixups) > 0:
            messages.info(
                request,
                _('Following fixups were applied to translation: %s') %
                ', '.join([unicode(f) for f in fixups])
            )

        # Get new set of checks
        newchecks = set(
            unit.active_checks().values_list('check', flat=True)
        )

        # Did we introduce any new failures?
        if saved and newchecks > oldchecks:
            # Show message to user
            messages.error(
                request,
                _('Some checks have failed on your translation!')
            )
            # Stay on same entry
            return HttpResponseRedirect(this_unit_url)

    # Redirect to next entry
    return HttpResponseRedirect(next_unit_url)
Пример #5
0
def translate(request, project, subproject, lang):
    obj = get_translation(request, project, subproject, lang)

    # Check locks
    project_locked, user_locked, own_lock = obj.is_locked(request, True)
    locked = project_locked or user_locked

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

    secondary = None
    unit = None

    search_options = SearchOptions(request)

    # Any form submitted?
    if request.method == 'POST':

        # Antispam protection
        if not request.user.is_authenticated():
            antispam = AntispamForm(request.POST)
            if not antispam.is_valid():
                # Silently redirect to next entry
                return HttpResponseRedirect('%s?type=%s&pos=%d%s' % (
                    obj.get_translate_url(),
                    search_options.rqtype,
                    search_options.pos,
                    search_options.url
                ))

        form = TranslationForm(request.POST)
        if form.is_valid() and not project_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(),
                                search_options.rqtype,
                                search_options.pos,
                                search_options.url
                            )
                        )
                    # Create the suggestion
                    sug = Suggestion.objects.create(
                        target=join_plural(form.cleaned_data['target']),
                        checksum=unit.checksum,
                        language=unit.translation.language,
                        project=unit.translation.subproject.project,
                        user=user
                    )
                    # Record in change
                    Change.objects.create(
                        unit=unit,
                        action=Change.ACTION_SUGGESTION,
                        translation=unit.translation,
                        user=user
                    )
                    # Invalidate counts cache
                    unit.translation.invalidate_cache('suggestions')
                    # Invite user to become translator if there is nobody else
                    recent_changes = Change.objects.content().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.')
                        )
                    # Notify subscribed users
                    subscriptions = Profile.objects.subscribed_new_suggestion(
                        obj.subproject.project,
                        obj.language,
                        request.user
                    )
                    for subscription in subscriptions:
                        subscription.notify_new_suggestion(obj, sug, unit)
                    # 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!')
                    )
                elif not user_locked:
                    # 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']
                    saved = unit.save_backend(request)

                    if saved:
                        # 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(),
                                    search_options.rqtype,
                                    search_options.pos,
                                    search_options.url
                                )
                            )

                # Redirect to next entry
                return HttpResponseRedirect('%s?type=%s&pos=%d%s' % (
                    obj.get_translate_url(),
                    search_options.rqtype,
                    search_options.pos,
                    search_options.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 and not locked:
        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:
                        # Store unit
                        unit.target = merged.target
                        unit.fuzzy = merged.fuzzy
                        saved = unit.save_backend(request)
                        # Update stats if there was change
                        if saved:
                            profile.translated += 1
                            profile.save()
                        # Redirect to next entry
                        return HttpResponseRedirect('%s?type=%s&pos=%d%s' % (
                            obj.get_translate_url(),
                            search_options.rqtype,
                            search_options.pos,
                            search_options.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 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(),
                search_options.rqtype,
                search_options.pos,
                search_options.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(),
                    search_options.rqtype,
                    search_options.pos,
                    search_options.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(),
                    search_options.rqtype,
                    search_options.pos,
                    search_options.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)
            # Invalidate caches
            for unit in Unit.objects.filter(checksum=suggestion.checksum):
                unit.translation.invalidate_cache('suggestions')
            # 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(),
            search_options.rqtype,
            search_options.pos,
            search_options.url
        ))

    reviewform = ReviewForm(request.GET)

    if reviewform.is_valid():
        allunits = obj.unit_set.review(
            reviewform.cleaned_data['date'],
            request.user
        )
        # Review
        if search_options.direction == 'stay':
            units = allunits.filter(
                position=search_options.pos
            )
        elif search_options.direction == 'back':
            units = allunits.filter(
                position__lt=search_options.pos
            ).order_by('-position')
        else:
            units = allunits.filter(
                position__gt=search_options.pos
            )
    elif search_options.query != '':
        # Apply search conditions
        if search_options.type == 'exact':
            query = Q()
            if search_options.source:
                query |= Q(source=search_options.query)
            if search_options.target:
                query |= Q(target=search_options.query)
            if search_options.context:
                query |= Q(context=search_options.query)
            allunits = obj.unit_set.filter(query)
        elif search_options.type == 'substring':
            query = Q()
            if search_options.source:
                query |= Q(source__icontains=search_options.query)
            if search_options.target:
                query |= Q(target__icontains=search_options.query)
            if search_options.context:
                query |= Q(context__icontains=search_options.query)
            allunits = obj.unit_set.filter(query)
        else:
            allunits = obj.unit_set.search(
                search_options.query,
                search_options.source,
                search_options.context,
                search_options.target
            )
        if search_options.direction == 'stay':
            units = obj.unit_set.filter(
                position=search_options.pos
            )
        elif search_options.direction == 'back':
            units = allunits.filter(
                position__lt=search_options.pos
            ).order_by('-position')
        else:
            units = allunits.filter(
                position__gt=search_options.pos
            )
    elif 'checksum' in request.GET:
        allunits = obj.unit_set.filter(checksum=request.GET['checksum'])
        units = allunits
    else:
        allunits = obj.unit_set.filter_type(search_options.rqtype, obj)
        # What unit set is about to show
        if search_options.direction == 'stay':
            units = obj.unit_set.filter(
                position=search_options.pos
            )
        elif search_options.direction == 'back':
            units = allunits.filter(
                position__lt=search_options.pos
            ).order_by('-position')
        else:
            units = allunits.filter(
                position__gt=search_options.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_langs = profile.secondary_languages.exclude(
                id=unit.translation.language.id
            )
            project = unit.translation.subproject.project
            secondary = Unit.objects.filter(
                checksum=unit.checksum,
                translated=True,
                translation__subproject__project=project,
                translation__language__in=secondary_langs,
            )
            # 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 lang in secondary:
                if lang.target in targets:
                    continue
                targets[lang.target] = 1
                res.append(lang)
            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,
                'last_changes': unit.change_set.all()[:10],
                'total': total,
                'type': search_options.rqtype,
                'filter_name': get_filter_name(
                    search_options.rqtype, search_options.query
                ),
                'filter_count': filter_count,
                'filter_pos': filter_count + 1 - units.count(),
                'form': form,
                'antispam': antispam,
                'comment_form': CommentForm(),
                'target_language': obj.language.code.replace('_', '-').lower(),
                'update_lock': own_lock,
                'secondary': secondary,
                'search_query': search_options.query,
                'search_url': search_options.url,
                'search_source': bool2str(search_options.source),
                'search_type': search_options.type,
                'search_target': bool2str(search_options.target),
                'search_context': bool2str(search_options.context),
                'locked': locked,
                'user_locked': user_locked,
                'project_locked': project_locked,
            },
        )
    )
Пример #6
0
def handle_translate(obj, request, user_locked, this_unit_url, next_unit_url):
    """
    Saves translation or suggestion to database and backend.
    """
    # Antispam protection
    antispam = AntispamForm(request.POST)
    if not request.user.is_authenticated() and not antispam.is_valid():
        # Silently redirect to next entry
        return HttpResponseRedirect(next_unit_url)

    form = TranslationForm(request.POST)
    if not form.is_valid():
        return

    # Check whether translation is not outdated
    obj.check_sync()

    try:
        unit = Unit.objects.get_checksum(request, obj, form.cleaned_data["checksum"])
    except (Unit.DoesNotExist, IndexError):
        return

    if "suggest" in request.POST:
        # Handle suggesion saving
        user = request.user
        if form.cleaned_data["target"][0] == "":
            messages.error(request, _("Your suggestion is empty!"))
            # Stay on same entry
            return HttpResponseRedirect(this_unit_url)
        # Invite user to become translator if there is nobody else
        recent_changes = Change.objects.content().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"]), user)
    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!"))
    elif not user_locked:
        # Run AutoFixes on user input
        new_target = form.cleaned_data["target"]
        new_target, fixups = fix_target(new_target, unit)

        if len(fixups) > 0:
            messages.info(
                request, _("Following fixups were applied to translation: %s") % ", ".join([unicode(f) for f in fixups])
            )

        # Remember old checks
        oldchecks = set(unit.active_checks().values_list("check", flat=True))
        # Update unit and save it
        unit.target = join_plural(new_target)
        unit.fuzzy = form.cleaned_data["fuzzy"]
        saved = unit.save_backend(request)

        if saved:
            # 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(this_unit_url)

    # Redirect to next entry
    return HttpResponseRedirect(next_unit_url)