Ejemplo n.º 1
0
def handle_translate(request, translation, this_unit_url, next_unit_url):
    """Save 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)

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

    unit = form.cleaned_data['unit']
    go_next = True

    if 'suggest' in request.POST:
        go_next = perform_suggestion(unit, form, request)
    elif not request.user.has_perm('unit.edit', unit):
        messages.error(
            request,
            _('Insufficient privileges for saving translations.')
        )
    else:
        go_next = perform_translation(unit, form, request)

    # Redirect to next entry
    if go_next:
        return HttpResponseRedirect(next_unit_url)
    return HttpResponseRedirect(this_unit_url)
Ejemplo n.º 2
0
def search(translation, request):
    """Perform search or returns cached search results."""
    # Possible new search
    form = SearchForm(request.GET)

    # Process form
    form_valid = form.is_valid()
    if not form_valid:
        show_form_errors(request, form)

    search_result = {
        'form': form,
        'offset': form.cleaned_data.get('offset', 1),
        'checksum': form.cleaned_data.get('checksum'),
    }
    search_url = form.urlencode()
    session_key = 'search_{0}_{1}'.format(translation.pk, search_url)

    if (session_key in request.session and
            'offset' in request.GET and
            'items' in request.session[session_key]):
        search_result.update(request.session[session_key])
        return search_result

    allunits = translation.unit_set.search(
        form.cleaned_data,
        translation=translation,
    )

    search_query = form.get_search_query() if form_valid else ''
    name = form.get_name() if form_valid else ''

    # Grab unit IDs
    unit_ids = list(allunits.values_list('id', flat=True))

    # Check empty search results
    if not unit_ids:
        messages.warning(request, _('No string matched your search!'))
        return redirect(translation)

    # Remove old search results
    cleanup_session(request.session)

    store_result = {
        'query': search_query,
        'url': search_url,
        'items': form.items(),
        'key': session_key,
        'name': force_text(name),
        'ids': unit_ids,
        'ttl': int(time.time()) + 86400,
    }
    request.session[session_key] = store_result

    search_result.update(store_result)
    return search_result
Ejemplo n.º 3
0
def remove_translation(request, project, component, lang):
    obj = get_translation(request, project, component, lang)

    if not request.user.has_perm('translation.delete', obj):
        raise PermissionDenied()

    form = DeleteForm(obj, request.POST)
    if not form.is_valid():
        show_form_errors(request, form)
        return redirect_param(obj, '#delete')

    obj.remove(request.user)
    messages.success(request, _('Translation has been removed.'))

    return redirect(obj.component)
Ejemplo n.º 4
0
def whiteboard_project(request, project):
    obj = get_project(request, project)

    if not request.user.has_perm('project.edit', obj):
        raise PermissionDenied()

    form = WhiteboardForm(request.POST)
    if not form.is_valid():
        show_form_errors(request, form)
        return redirect_param(obj, '#whiteboard')

    WhiteboardMessage.objects.create(
        project=obj,
        **form.cleaned_data
    )

    return redirect(obj)
Ejemplo n.º 5
0
def perform_rename(form_cls, request, obj, perm, **kwargs):
    if not request.user.has_perm(perm, obj):
        raise PermissionDenied()

    form = form_cls(request, request.POST, instance=obj)
    if not form.is_valid():
        show_form_errors(request, form)
        return redirect_param(obj, '#delete')

    form.save()
    Change.objects.create(
        user=request.user,
        author=request.user,
        **kwargs
    )

    return redirect(obj)
Ejemplo n.º 6
0
def state_change(request, project, component=None, lang=None):
    obj, unit_set, context = parse_url(request, project, component, lang)

    if not request.user.has_perm('translation.auto', obj):
        raise PermissionDenied()

    form = MassStateForm(request.user, obj, request.POST)

    if not form.is_valid():
        messages.error(request, _('Failed to process form!'))
        show_form_errors(request, form)
        return redirect(obj)

    matching = unit_set.filter_type(
        form.cleaned_data['type'],
        context['project'],
        context['translation'].language if 'translation' in context else None,
    ).exclude(
        state=STATE_EMPTY
    )

    updated = 0
    with transaction.atomic():
        for unit in matching.select_for_update():
            if not request.user.has_perm('unit.edit', unit):
                continue
            unit.translate(
                request,
                unit.target,
                int(form.cleaned_data['state']),
                change_action=Change.ACTION_MASS_STATE,
            )
            updated += 1

    import_message(
        request, updated,
        _('Mass state change completed, no strings were updated.'),
        ungettext(
            'Mass state change completed, %d string was updated.',
            'Mass state change completed, %d strings were updated.',
            updated
        )
    )

    return redirect(obj)
Ejemplo n.º 7
0
def save_zen(request, project, component, lang):
    """Save handler for zen mode."""
    def render_mesage(message):
        return render_to_string(
            'message.html',
            {'tags': message.tags, 'message': message.message}
        )

    translation = get_translation(request, project, component, lang)

    form = TranslationForm(
        request.user, translation, None, request.POST
    )
    translationsum = ''
    if not form.is_valid():
        show_form_errors(request, form)
    elif not request.user.has_perm('unit.edit', form.cleaned_data['unit']):
        messages.error(
            request, _('Insufficient privileges for saving translations.')
        )
    else:
        unit = form.cleaned_data['unit']

        perform_translation(unit, form, request)

        translationsum = hash_to_checksum(unit.get_target_hash())

    response = {
        'messages': '',
        'state': 'success',
        'translationsum': translationsum,
    }

    storage = get_messages(request)
    if storage:
        response['messages'] = '\n'.join([render_mesage(m) for m in storage])
        tags = {m.tags for m in storage}
        if 'error' in tags:
            response['state'] = 'danger'
        elif 'warning' in tags:
            response['state'] = 'warning'
        elif 'info' in tags:
            response['state'] = 'info'

    return JsonResponse(data=response)
Ejemplo n.º 8
0
def download_translation(request, project, component, lang):
    obj = get_translation(request, project, component, lang)

    kwargs = {}

    if 'format' in request.GET or 'type' in request.GET:
        form = DownloadForm(request.GET)
        if not form.is_valid():
            show_form_errors(request, form)
            return redirect(obj)

        kwargs['units'] = obj.unit_set.search(
            form.cleaned_data,
            translation=obj,
        )
        kwargs['fmt'] = form.cleaned_data['format']

    return download_translation_file(obj, **kwargs)
Ejemplo n.º 9
0
def whiteboard_translation(request, project, component, lang):
    obj = get_translation(request, project, component, lang)

    if not request.user.has_perm('component.edit', obj):
        raise PermissionDenied()

    form = WhiteboardForm(request.POST)
    if not form.is_valid():
        show_form_errors(request, form)
        return redirect_param(obj, '#whiteboard')

    WhiteboardMessage.objects.create(
        project=obj.component.project,
        component=obj.component,
        language=obj.language,
        **form.cleaned_data
    )

    return redirect(obj)
Ejemplo n.º 10
0
def auto_translation(request, project, component, lang):
    translation = get_translation(request, project, component, lang)
    project = translation.component.project
    if not request.user.has_perm('translation.auto', project):
        raise PermissionDenied()

    autoform = AutoForm(request.user, translation, request.POST)

    if translation.component.locked or not autoform.is_valid():
        messages.error(request, _('Failed to process form!'))
        show_form_errors(request, autoform)
        return redirect(translation)

    auto = AutoTranslate(
        request.user,
        translation,
        autoform.cleaned_data['type'],
        request=request
    )

    if autoform.cleaned_data['auto_source'] == 'mt':
        auto.process_mt(
            autoform.cleaned_data['engines'],
            autoform.cleaned_data['threshold'],
        )
    else:
        auto.process_others(
            autoform.cleaned_data['component'],
        )

    import_message(
        request, auto.updated,
        _('Automatic translation completed, no strings were updated.'),
        ungettext(
            'Automatic translation completed, %d string was updated.',
            'Automatic translation completed, %d strings were updated.',
            auto.updated
        )
    )

    return redirect(translation)
Ejemplo n.º 11
0
def remove_project(request, project):
    obj = get_project(request, project)

    if not request.user.has_perm('project.edit', obj):
        raise PermissionDenied()

    form = DeleteForm(obj, request.POST)
    if not form.is_valid():
        show_form_errors(request, form)
        return redirect_param(obj, '#delete')

    project_removal.delay(obj.pk)
    messages.success(request, _('Project was scheduled for removal.'))
    Change.objects.create(
        action=Change.ACTION_REMOVE_PROJECT,
        target=obj.slug,
        user=request.user,
        author=request.user
    )

    return redirect('home')
Ejemplo n.º 12
0
def remove_component(request, project, component):
    obj = get_component(request, project, component)

    if not request.user.has_perm('component.edit', obj):
        raise PermissionDenied()

    form = DeleteForm(obj, request.POST)
    if not form.is_valid():
        show_form_errors(request, form)
        return redirect_param(obj, '#delete')

    obj.delete()
    messages.success(request, _('Translation component has been removed.'))
    Change.objects.create(
        project=obj.project,
        action=Change.ACTION_REMOVE_COMPONENT,
        target=obj.slug,
        user=request.user,
        author=request.user
    )

    return redirect(obj.project)
Ejemplo n.º 13
0
def new_unit(request, project, component, lang):
    translation = get_translation(request, project, component, lang)
    if not request.user.has_perm('unit.add', translation):
        raise PermissionDenied()

    form = NewUnitForm(request.user, request.POST)
    if not form.is_valid():
        show_form_errors(request, form)
    else:
        key = form.cleaned_data['key']
        value = form.cleaned_data['value'][0]

        if translation.unit_set.filter(context=key).exists():
            messages.error(
                request, _('Translation with this key seem to already exist!')
            )
        else:
            translation.new_unit(request, key, value)
            messages.success(
                request, _('New string has been added.')
            )

    return redirect(translation)
Ejemplo n.º 14
0
def get_credits(request, project=None, component=None):
    """View for credits"""
    if project is None:
        obj = None
        kwargs = {'translation__pk__gt': 0}
    elif component is None:
        obj = get_project(request, project)
        kwargs = {'translation__component__project': obj}
    else:
        obj = get_component(request, project, component)
        kwargs = {'translation__component': obj}

    form = ReportsForm(request.POST)

    if not form.is_valid():
        show_form_errors(request, form)
        return redirect_param(obj or 'home', '#reports')

    data = generate_credits(
        None if request.user.has_perm('reports.view', obj) else request.user,
        form.cleaned_data['start_date'], form.cleaned_data['end_date'],
        **kwargs)

    if form.cleaned_data['style'] == 'json':
        return JsonResponse(data=data, safe=False)

    if form.cleaned_data['style'] == 'html':
        start = '<table>'
        row_start = '<tr>'
        language_format = '<th>{0}</th>'
        translator_start = '<td><ul>'
        translator_format = '<li><a href="mailto:{0}">{1}</a></li>'
        translator_end = '</ul></td>'
        row_end = '</tr>'
        mime = 'text/html'
        end = '</table>'
    else:
        start = ''
        row_start = ''
        language_format = '* {0}\n'
        translator_start = ''
        translator_format = '    * {1} <{0}>'
        translator_end = ''
        row_end = ''
        mime = 'text/plain'
        end = ''

    result = []

    result.append(start)

    for language in data:
        name, translators = language.popitem()
        result.append(row_start)
        result.append(language_format.format(name))
        result.append(translator_start + '\n'.join(
            translator_format.format(*t)
            for t in translators) + translator_end)
        result.append(row_end)

    result.append(end)

    return HttpResponse('\n'.join(result),
                        content_type='{0}; charset=utf-8'.format(mime))
Ejemplo n.º 15
0
def get_credits(request, project, component):
    """View for credits"""
    obj = get_component(request, project, component)

    if not request.user.has_perm('reports.view', obj):
        raise PermissionDenied()

    form = ReportsForm(request.POST)

    if not form.is_valid():
        show_form_errors(request, form)
        return redirect_param(obj, '#reports')

    data = generate_credits(
        obj,
        form.cleaned_data['start_date'],
        form.cleaned_data['end_date'],
    )

    if form.cleaned_data['style'] == 'json':
        return JsonResponse(data=data, safe=False)

    if form.cleaned_data['style'] == 'html':
        start = '<table>'
        row_start = '<tr>'
        language_format = '<th>{0}</th>'
        translator_start = '<td><ul>'
        translator_format = '<li><a href="mailto:{0}">{1}</a></li>'
        translator_end = '</ul></td>'
        row_end = '</tr>'
        mime = 'text/html'
        end = '</table>'
    else:
        start = ''
        row_start = ''
        language_format = '* {0}\n'
        translator_start = ''
        translator_format = '    * {1} <{0}>'
        translator_end = ''
        row_end = ''
        mime = 'text/plain'
        end = ''

    result = []

    result.append(start)

    for language in data:
        name, translators = language.popitem()
        result.append(row_start)
        result.append(language_format.format(name))
        result.append(
            ''.join((
                translator_start,
                '\n'.join(
                    [translator_format.format(*t) for t in translators]
                ),
                translator_end,
            ))
        )
        result.append(row_end)

    result.append(end)

    return HttpResponse(
        '\n'.join(result),
        content_type='{0}; charset=utf-8'.format(mime),
    )
Ejemplo n.º 16
0
def search(request, project=None, component=None, lang=None):
    """Perform site-wide search on units."""
    is_ratelimited = not check_rate_limit('search', request)
    search_form = SiteSearchForm(request.GET)
    context = {
        'search_form': search_form,
    }
    search_kwargs = {}
    if component:
        obj = get_component(request, project, component)
        context['component'] = obj
        context['project'] = obj.project
        context['back_url'] = obj.get_absolute_url()
        search_kwargs = {'component': obj}
    elif project:
        obj = get_project(request, project)
        context['project'] = obj
        context['back_url'] = obj.get_absolute_url()
        search_kwargs = {'project': obj}
    else:
        obj = None
        context['back_url'] = None
    if lang:
        s_language = get_object_or_404(Language, code=lang)
        context['language'] = s_language
        search_kwargs = {'language': s_language}
        if obj:
            if component:
                context['back_url'] = obj.translation_set.get(
                    language=s_language).get_absolute_url()
            else:
                context['back_url'] = reverse('project-language',
                                              kwargs={
                                                  'project': project,
                                                  'lang': lang,
                                              })
        else:
            context['back_url'] = s_language.get_absolute_url()

    if not is_ratelimited and request.GET and search_form.is_valid():
        # Filter results by ACL
        if component:
            units = Unit.objects.filter(translation__component=obj)
        elif project:
            units = Unit.objects.filter(translation__component__project=obj)
        else:
            allowed_projects = request.user.allowed_projects
            units = Unit.objects.filter(
                translation__component__project__in=allowed_projects)
        units = units.search(search_form.cleaned_data, **search_kwargs)
        if lang:
            units = units.filter(translation__language=context['language'])

        units = get_paginator(request, units)

        context['show_results'] = True
        context['page_obj'] = units
        context['title'] = _('Search for %s') % (search_form.cleaned_data['q'])
        context['query_string'] = search_form.urlencode()
        context['search_query'] = search_form.cleaned_data['q']
    elif is_ratelimited:
        messages.error(request,
                       _('Too many search queries, please try again later.'))
    elif request.GET:
        messages.error(request, _('Invalid search query!'))
        show_form_errors(request, search_form)

    return render(request, 'search.html', context)
Ejemplo n.º 17
0
def search(request, project=None, component=None, lang=None):
    """Perform site-wide search on units."""
    is_ratelimited = not check_rate_limit('search', request)
    search_form = SiteSearchForm(request.GET)
    context = {
        'search_form': search_form,
    }
    search_kwargs = {}
    if component:
        obj = get_component(request, project, component)
        context['component'] = obj
        context['project'] = obj.project
        context['back_url'] = obj.get_absolute_url()
        search_kwargs = {'component': obj}
    elif project:
        obj = get_project(request, project)
        context['project'] = obj
        context['back_url'] = obj.get_absolute_url()
        search_kwargs = {'project': obj}
    else:
        obj = None
        context['back_url'] = None
    if lang:
        s_language = get_object_or_404(Language, code=lang)
        context['language'] = s_language
        search_kwargs = {'language': s_language}
        if obj:
            if component:
                context['back_url'] = obj.translation_set.get(
                    language=s_language
                ).get_absolute_url()
            else:
                context['back_url'] = reverse(
                    'project-language',
                    kwargs={
                        'project': project,
                        'lang': lang,
                    }
                )
        else:
            context['back_url'] = s_language.get_absolute_url()

    if not is_ratelimited and request.GET and search_form.is_valid():
        # Filter results by ACL
        if component:
            units = Unit.objects.filter(translation__component=obj)
        elif project:
            units = Unit.objects.filter(translation__component__project=obj)
        else:
            allowed_projects = request.user.allowed_projects
            units = Unit.objects.filter(
                translation__component__project__in=allowed_projects
            )
        units = units.search(
            search_form.cleaned_data,
            **search_kwargs
        )
        if lang:
            units = units.filter(
                translation__language=context['language']
            )

        units = get_paginator(request, units)

        context['show_results'] = True
        context['page_obj'] = units
        context['title'] = _('Search for %s') % (
            search_form.cleaned_data['q']
        )
        context['query_string'] = search_form.urlencode()
        context['search_query'] = search_form.cleaned_data['q']
    elif is_ratelimited:
        messages.error(
            request, _('Too many search queries, please try again later.')
        )
    elif request.GET:
        messages.error(request, _('Invalid search query!'))
        show_form_errors(request, search_form)

    return render(
        request,
        'search.html',
        context
    )
Ejemplo n.º 18
0
def search_replace(request, project, component=None, lang=None):
    obj, unit_set, context = parse_url(request, project, component, lang)

    form = ReplaceForm(request.POST)

    if not form.is_valid():
        messages.error(request, _('Failed to process form!'))
        show_form_errors(request, form)
        return redirect(obj)

    search_text = form.cleaned_data['search']
    replacement = form.cleaned_data['replacement']

    matching = unit_set.filter(target__contains=search_text)

    updated = 0
    if matching.exists():
        confirm = ReplaceConfirmForm(matching, request.POST)
        limited = False

        if matching.count() > 300:
            matching = matching.order_by('id')[:250]
            limited = True

        if not confirm.is_valid():
            for unit in matching:
                unit.replacement = unit.target.replace(
                    search_text, replacement
                )
            context.update({
                'matching': matching,
                'search_query': search_text,
                'replacement': replacement,
                'form': form,
                'limited': limited,
                'confirm': ReplaceConfirmForm(matching),
            })
            return render(
                request,
                'replace.html',
                context
            )

        matching = confirm.cleaned_data['units']

        with transaction.atomic():
            for unit in matching.select_for_update():
                if not request.user.has_perm('unit.edit', unit):
                    continue
                unit.translate(
                    request,
                    unit.target.replace(search_text, replacement),
                    unit.state,
                    change_action=Change.ACTION_REPLACE
                )
                updated += 1

    import_message(
        request, updated,
        _('Search and replace completed, no strings were updated.'),
        ungettext(
            'Search and replace completed, %d string was updated.',
            'Search and replace completed, %d strings were updated.',
            updated
        )
    )

    return redirect(obj)
Ejemplo n.º 19
0
def search_replace(request, project, component=None, lang=None):
    obj, unit_set, context = parse_url(request, project, component, lang)

    form = ReplaceForm(request.POST)

    if not form.is_valid():
        messages.error(request, _('Failed to process form!'))
        show_form_errors(request, form)
        return redirect(obj)

    search_text = form.cleaned_data['search']
    replacement = form.cleaned_data['replacement']

    matching = unit_set.filter(target__contains=search_text)

    updated = 0
    if matching.exists():
        confirm = ReplaceConfirmForm(matching, request.POST)
        limited = False

        if matching.count() > 300:
            matching = matching.order_by('id')[:250]
            limited = True

        if not confirm.is_valid():
            for unit in matching:
                unit.replacement = unit.target.replace(
                    search_text, replacement
                )
            context.update({
                'matching': matching,
                'search_query': search_text,
                'replacement': replacement,
                'form': form,
                'limited': limited,
                'confirm': ReplaceConfirmForm(matching),
            })
            return render(
                request,
                'replace.html',
                context
            )

        matching = confirm.cleaned_data['units']

        with transaction.atomic():
            for unit in matching.select_for_update():
                if not request.user.has_perm('unit.edit', unit):
                    continue
                unit.translate(
                    request,
                    unit.target.replace(search_text, replacement),
                    unit.state,
                    change_action=Change.ACTION_REPLACE
                )
                updated += 1

    import_message(
        request, updated,
        _('Search and replace completed, no strings were updated.'),
        ungettext(
            'Search and replace completed, %d string was updated.',
            'Search and replace completed, %d strings were updated.',
            updated
        )
    )

    return redirect(obj)
Ejemplo n.º 20
0
def upload_translation(request, project, component, lang):
    """Handling of translation uploads."""
    obj = get_translation(request, project, component, lang)

    if not request.user.has_perm("upload.perform", obj):
        raise PermissionDenied()

    # Check method and lock
    if obj.component.locked:
        messages.error(request, _("Access denied."))
        return redirect(obj)

    # Get correct form handler based on permissions
    form = get_upload_form(request.user, obj, request.POST, request.FILES)

    # Check form validity
    if not form.is_valid():
        messages.error(request, _("Please fix errors in the form."))
        show_form_errors(request, form)
        return redirect(obj)

    # Create author name
    author_name = None
    author_email = None
    if request.user.has_perm("upload.authorship", obj):
        author_name = form.cleaned_data["author_name"]
        author_email = form.cleaned_data["author_email"]

    # Check for overwriting
    conflicts = ""
    if request.user.has_perm("upload.overwrite", obj):
        conflicts = form.cleaned_data["conflicts"]

    # Do actual import
    try:
        not_found, skipped, accepted, total = obj.handle_upload(
            request,
            request.FILES["file"],
            conflicts,
            author_name,
            author_email,
            method=form.cleaned_data["method"],
            fuzzy=form.cleaned_data["fuzzy"],
        )
        if total == 0:
            message = _("No strings were imported from the uploaded file.")
        else:
            message = ngettext(
                "Processed {0} string from the uploaded files "
                "(skipped: {1}, not found: {2}, updated: {3}).",
                "Processed {0} strings from the uploaded files "
                "(skipped: {1}, not found: {2}, updated: {3}).",
                total,
            ).format(total, skipped, not_found, accepted)
        if accepted == 0:
            messages.warning(request, message)
        else:
            messages.success(request, message)
    except PluralFormsMismatch:
        messages.error(
            request,
            _("Plural forms in the uploaded file do not match current translation."
              ),
        )
    except Exception as error:
        messages.error(
            request,
            _("File upload has failed: %s") %
            str(error).replace(obj.component.full_path, ""),
        )
        report_error(cause="Upload error")

    return redirect(obj)
Ejemplo n.º 21
0
def search(request, project=None, component=None, lang=None):
    """Perform site-wide search on units."""
    is_ratelimited = not check_rate_limit("search", request)
    search_form = SearchForm(request.user, request.GET)
    sort = get_sort_name(request)
    context = {"search_form": search_form}
    if component:
        obj = get_component(request, project, component)
        context["component"] = obj
        context["project"] = obj.project
        context["back_url"] = obj.get_absolute_url()
    elif project:
        obj = get_project(request, project)
        context["project"] = obj
        context["back_url"] = obj.get_absolute_url()
    else:
        obj = None
        context["back_url"] = None
    if lang:
        s_language = get_object_or_404(Language, code=lang)
        context["language"] = s_language
        if obj:
            if component:
                context["back_url"] = obj.translation_set.get(
                    language=s_language
                ).get_absolute_url()
            else:
                context["back_url"] = reverse(
                    "project-language", kwargs={"project": project, "lang": lang}
                )
        else:
            context["back_url"] = s_language.get_absolute_url()

    if not is_ratelimited and request.GET and search_form.is_valid():
        # This is ugly way to hide query builder when showing results
        search_form = SearchForm(request.user, request.GET, show_builder=False)
        search_form.is_valid()
        # Filter results by ACL
        if component:
            units = Unit.objects.filter(translation__component=obj)
        elif project:
            units = Unit.objects.filter(translation__component__project=obj)
        else:
            units = Unit.objects.filter_access(request.user)
        units = units.search(search_form.cleaned_data.get("q", "")).distinct()
        if lang:
            units = units.filter(translation__language=context["language"])

        units = get_paginator(request, units.order_by_request(search_form.cleaned_data))
        # Rebuild context from scratch here to get new form
        context = {
            "search_form": search_form,
            "show_results": True,
            "page_obj": units,
            "title": _("Search for %s") % (search_form.cleaned_data["q"]),
            "query_string": search_form.urlencode(),
            "search_query": search_form.cleaned_data["q"],
            "search_items": search_form.items(),
            "filter_name": search_form.get_name(),
            "sort_name": sort["name"],
            "sort_query": sort["query"],
        }
    elif is_ratelimited:
        messages.error(request, _("Too many search queries, please try again later."))
    elif request.GET:
        messages.error(request, _("Invalid search query!"))
        show_form_errors(request, search_form)

    return render(request, "search.html", context)
Ejemplo n.º 22
0
def search(base, unit_set, request):
    """Perform search or returns cached search results."""
    # Possible new search
    form = PositionSearchForm(user=request.user,
                              data=request.GET,
                              show_builder=False)

    # Process form
    form_valid = form.is_valid()
    if form_valid:
        cleaned_data = form.cleaned_data
        search_url = form.urlencode()
        search_query = form.get_search_query()
        name = form.get_name()
        search_items = form.items()
    else:
        cleaned_data = {}
        show_form_errors(request, form)
        search_url = ""
        search_query = ""
        name = ""
        search_items = ()

    search_result = {
        "form": form,
        "offset": cleaned_data.get("offset", 1),
    }
    session_key = f"search_{base.cache_key}_{search_url}"

    if (session_key in request.session and "offset" in request.GET
            and "items" in request.session[session_key]):
        search_result.update(request.session[session_key])
        return search_result

    allunits = unit_set.search(cleaned_data.get("q", "")).distinct()

    # Grab unit IDs
    unit_ids = list(
        allunits.order_by_request(cleaned_data).values_list("id", flat=True))

    # Check empty search results
    if not unit_ids:
        messages.warning(request, _("No string matched your search!"))
        return redirect(base)

    # Remove old search results
    cleanup_session(request.session)

    store_result = {
        "query": search_query,
        "url": search_url,
        "items": search_items,
        "key": session_key,
        "name": force_str(name),
        "ids": unit_ids,
        "ttl": int(time.time()) + 86400,
    }
    request.session[session_key] = store_result

    search_result.update(store_result)
    return search_result
Ejemplo n.º 23
0
def upload_translation(request, project, component, lang):
    """Handling of translation uploads."""
    obj = get_translation(request, project, component, lang)

    if not request.user.has_perm('upload.perform', obj):
        raise PermissionDenied()

    # Check method and lock
    if obj.component.locked:
        messages.error(request, _('Access denied.'))
        return redirect(obj)

    # Get correct form handler based on permissions
    form = get_upload_form(request.user, obj, request.POST, request.FILES)

    # Check form validity
    if not form.is_valid():
        messages.error(request, _('Please fix errors in the form.'))
        show_form_errors(request, form)
        return redirect(obj)

    # Create author name
    author_name = None
    author_email = None
    if request.user.has_perm('upload.authorship', obj):
        author_name = form.cleaned_data['author_name']
        author_email = form.cleaned_data['author_email']

    # Check for overwriting
    overwrite = False
    if request.user.has_perm('upload.overwrite', obj):
        overwrite = form.cleaned_data['upload_overwrite']

    # Do actual import
    try:
        not_found, skipped, accepted, total = obj.merge_upload(
            request,
            request.FILES['file'],
            overwrite,
            author_name,
            author_email,
            method=form.cleaned_data['method'],
            fuzzy=form.cleaned_data['fuzzy'],
        )
        if total == 0:
            message = _('No strings were imported from the uploaded file.')
        else:
            message = ungettext(
                'Processed {0} string from the uploaded files '
                '(skipped: {1}, not found: {2}, updated: {3}).',
                'Processed {0} strings from the uploaded files '
                '(skipped: {1}, not found: {2}, updated: {3}).',
                total).format(total, skipped, not_found, accepted)
        if accepted == 0:
            messages.warning(request, message)
        else:
            messages.success(request, message)
    except Exception as error:
        messages.error(request,
                       _('File content merge failed: %s') % force_text(error))
        report_error(error, request, prefix='Failed to merge content')

    return redirect(obj)
Ejemplo n.º 24
0
def get_credits(request, project, component):
    """View for credits"""
    obj = get_component(request, project, component)

    if not request.user.has_perm('reports.view', obj):
        raise PermissionDenied()

    form = ReportsForm(request.POST)

    if not form.is_valid():
        show_form_errors(request, form)
        return redirect_param(obj, '#reports')

    data = generate_credits(
        obj,
        form.cleaned_data['start_date'],
        form.cleaned_data['end_date'],
    )

    if form.cleaned_data['style'] == 'json':
        return JsonResponse(data=data, safe=False)

    if form.cleaned_data['style'] == 'html':
        start = '<table>'
        row_start = '<tr>'
        language_format = '<th>{0}</th>'
        translator_start = '<td><ul>'
        translator_format = '<li><a href="mailto:{0}">{1}</a></li>'
        translator_end = '</ul></td>'
        row_end = '</tr>'
        mime = 'text/html'
        end = '</table>'
    else:
        start = ''
        row_start = ''
        language_format = '* {0}\n'
        translator_start = ''
        translator_format = '    * {1} <{0}>'
        translator_end = ''
        row_end = ''
        mime = 'text/plain'
        end = ''

    result = []

    result.append(start)

    for language in data:
        name, translators = language.popitem()
        result.append(row_start)
        result.append(language_format.format(name))
        result.append(''.join((
            translator_start,
            '\n'.join([translator_format.format(*t) for t in translators]),
            translator_end,
        )))
        result.append(row_end)

    result.append(end)

    return HttpResponse(
        '\n'.join(result),
        content_type='{0}; charset=utf-8'.format(mime),
    )
Ejemplo n.º 25
0
 def form_invalid(self, form):
     show_form_errors(self.request, form)
     return super().form_invalid(form)
Ejemplo n.º 26
0
def get_counts(request, project=None, component=None):
    """View for work counts."""
    if project is None:
        obj = None
        kwargs = {}
    elif component is None:
        obj = get_project(request, project)
        kwargs = {"project": obj}
    else:
        obj = get_component(request, project, component)
        kwargs = {"component": obj}

    form = ReportsForm(request.POST)

    if not form.is_valid():
        show_form_errors(request, form)
        return redirect_param(obj or "home", "#reports")

    data = generate_counts(
        None if request.user.has_perm("reports.view", obj) else request.user,
        form.cleaned_data["start_date"], form.cleaned_data["end_date"],
        **kwargs)

    if form.cleaned_data["style"] == "json":
        return JsonResponse(data=data, safe=False)

    headers = (
        "Name",
        "Email",
        "Count total",
        "Edits total",
        "Source words total",
        "Source chars total",
        "Target words total",
        "Target chars total",
        "Count new",
        "Edits new",
        "Source words new",
        "Source chars new",
        "Target words new",
        "Target chars new",
        "Count approved",
        "Edits approved",
        "Source words approved",
        "Source chars approved",
        "Target words approved",
        "Target chars approved",
        "Count edited",
        "Edits edited",
        "Source words edited",
        "Source chars edited",
        "Target words edited",
        "Target chars edited",
    )

    if form.cleaned_data["style"] == "html":
        start = HTML_HEADING.format("".join("<th>{0}</th>".format(h)
                                            for h in headers))
        row_start = "<tr>"
        cell_name = cell_count = "<td>{0}</td>\n"
        row_end = "</tr>"
        mime = "text/html"
        end = "</table>"
    else:
        start = "{0}\n{1} {2}\n{0}".format(
            RST_HEADING,
            " ".join("{0:40}".format(h) for h in headers[:2]),
            " ".join("{0:24}".format(h) for h in headers[2:]),
        )
        row_start = ""
        cell_name = "{0:40} "
        cell_count = "{0:24} "
        row_end = ""
        mime = "text/plain"
        end = RST_HEADING

    result = []

    result.append(start)

    for item in data:
        if row_start:
            result.append(row_start)
        result.append("".join((
            cell_name.format(item["name"] or "Anonymous"),
            cell_name.format(item["email"] or ""),
            cell_count.format(item["count"]),
            cell_count.format(item["edits"]),
            cell_count.format(item["words"]),
            cell_count.format(item["chars"]),
            cell_count.format(item["t_words"]),
            cell_count.format(item["t_chars"]),
            cell_count.format(item["count_new"]),
            cell_count.format(item["edits_new"]),
            cell_count.format(item["words_new"]),
            cell_count.format(item["chars_new"]),
            cell_count.format(item["t_words_new"]),
            cell_count.format(item["t_chars_new"]),
            cell_count.format(item["count_approve"]),
            cell_count.format(item["edits_approve"]),
            cell_count.format(item["words_approve"]),
            cell_count.format(item["chars_approve"]),
            cell_count.format(item["t_words_approve"]),
            cell_count.format(item["t_chars_approve"]),
            cell_count.format(item["count_edit"]),
            cell_count.format(item["edits_edit"]),
            cell_count.format(item["words_edit"]),
            cell_count.format(item["chars_edit"]),
            cell_count.format(item["t_words_edit"]),
            cell_count.format(item["t_chars_edit"]),
        )))
        if row_end:
            result.append(row_end)

    result.append(end)

    return HttpResponse("\n".join(result),
                        content_type="{0}; charset=utf-8".format(mime))
Ejemplo n.º 27
0
def get_counts(request, project, component):
    """View for work counts"""
    obj = get_component(request, project, component)

    if not request.user.has_perm('reports.view', obj):
        raise PermissionDenied()

    form = ReportsForm(request.POST)

    if not form.is_valid():
        show_form_errors(request, form)
        return redirect_param(obj, '#reports')

    data = generate_counts(
        obj,
        form.cleaned_data['start_date'],
        form.cleaned_data['end_date'],
    )

    if form.cleaned_data['style'] == 'json':
        return JsonResponse(data=data, safe=False)

    headers = (
        'Name',
        'Email',
        'Count total',
        'Source words total',
        'Source chars total',
        'Target words total',
        'Target chars total',

        'Count new',
        'Source words new',
        'Source chars new',
        'Target words new',
        'Target chars new',

        'Count approved',
        'Source words approved',
        'Source chars approved',
        'Target words approved',
        'Target chars approved',

        'Count edited',
        'Source words edited',
        'Source chars edited',
        'Target words edited',
        'Target chars edited',
    )

    if form.cleaned_data['style'] == 'html':
        start = HTML_HEADING.format(
            ''.join(['<th>{0}</th>'.format(h) for h in headers])
        )
        row_start = '<tr>'
        cell_name = cell_count = '<td>{0}</td>\n'
        row_end = '</tr>'
        mime = 'text/html'
        end = '</table>'
    else:
        start = '{0}\n{1} {2}\n{0}'.format(
            RST_HEADING,
            ' '.join(['{0:40}'.format(h) for h in headers[:2]]),
            ' '.join(['{0:24}'.format(h) for h in headers[2:]]),
        )
        row_start = ''
        cell_name = '{0:40} '
        cell_count = '{0:24} '
        row_end = ''
        mime = 'text/plain'
        end = RST_HEADING

    result = []

    result.append(start)

    for item in data:
        if row_start:
            result.append(row_start)
        result.append(
            ''.join((
                cell_name.format(item['name']),
                cell_name.format(item['email']),

                cell_count.format(item['count']),
                cell_count.format(item['words']),
                cell_count.format(item['chars']),
                cell_count.format(item['t_words']),
                cell_count.format(item['t_chars']),

                cell_count.format(item['count_new']),
                cell_count.format(item['words_new']),
                cell_count.format(item['chars_new']),
                cell_count.format(item['t_words_new']),
                cell_count.format(item['t_chars_new']),

                cell_count.format(item['count_approve']),
                cell_count.format(item['words_approve']),
                cell_count.format(item['chars_approve']),
                cell_count.format(item['t_words_approve']),
                cell_count.format(item['t_chars_approve']),

                cell_count.format(item['count_edit']),
                cell_count.format(item['words_edit']),
                cell_count.format(item['chars_edit']),
                cell_count.format(item['t_words_edit']),
                cell_count.format(item['t_chars_edit']),
            ))
        )
        if row_end:
            result.append(row_end)

    result.append(end)

    return HttpResponse(
        '\n'.join(result),
        content_type='{0}; charset=utf-8'.format(mime),
    )
Ejemplo n.º 28
0
def upload_translation(request, project, component, lang):
    """Handling of translation uploads."""
    obj = get_translation(request, project, component, lang)

    if not request.user.has_perm('upload.perform', obj):
        raise PermissionDenied()

    # Check method and lock
    if obj.component.locked:
        messages.error(request, _('Access denied.'))
        return redirect(obj)

    # Get correct form handler based on permissions
    form = get_upload_form(
        request.user, obj,
        request.POST, request.FILES
    )

    # Check form validity
    if not form.is_valid():
        messages.error(request, _('Please fix errors in the form.'))
        show_form_errors(request, form)
        return redirect(obj)

    # Create author name
    author = None
    if (request.user.has_perm('upload.authorship', obj) and
            form.cleaned_data['author_name'] != '' and
            form.cleaned_data['author_email'] != ''):
        author = '{0} <{1}>'.format(
            form.cleaned_data['author_name'],
            form.cleaned_data['author_email']
        )

    # Check for overwriting
    overwrite = False
    if request.user.has_perm('upload.overwrite', obj):
        overwrite = form.cleaned_data['upload_overwrite']

    # Do actual import
    try:
        not_found, skipped, accepted, total = obj.merge_upload(
            request,
            request.FILES['file'],
            overwrite,
            author,
            method=form.cleaned_data['method'],
            fuzzy=form.cleaned_data['fuzzy'],
        )
        if total == 0:
            message = _('No strings were imported from the uploaded file.')
        else:
            message = ungettext(
                'Processed {0} string from the uploaded files '
                '(skipped: {1}, not found: {2}, updated: {3}).',
                'Processed {0} strings from the uploaded files '
                '(skipped: {1}, not found: {2}, updated: {3}).',
                total
            ).format(total, skipped, not_found, accepted)
        if accepted == 0:
            messages.warning(request, message)
        else:
            messages.success(request, message)
    except Exception as error:
        messages.error(
            request, _('File content merge failed: %s') % force_text(error)
        )
        report_error(error, request)

    return redirect(obj)
Ejemplo n.º 29
0
def get_counts(request, project, component):
    """View for work counts"""
    obj = get_component(request, project, component)

    if not request.user.has_perm('reports.view', obj):
        raise PermissionDenied()

    form = ReportsForm(request.POST)

    if not form.is_valid():
        show_form_errors(request, form)
        return redirect_param(obj, '#reports')

    data = generate_counts(
        obj,
        form.cleaned_data['start_date'],
        form.cleaned_data['end_date'],
    )

    if form.cleaned_data['style'] == 'json':
        return JsonResponse(data=data, safe=False)

    headers = (
        'Name',
        'Email',
        'Count total',
        'Source words total',
        'Source chars total',
        'Target words total',
        'Target chars total',
        'Count new',
        'Source words new',
        'Source chars new',
        'Target words new',
        'Target chars new',
        'Count approved',
        'Source words approved',
        'Source chars approved',
        'Target words approved',
        'Target chars approved',
        'Count edited',
        'Source words edited',
        'Source chars edited',
        'Target words edited',
        'Target chars edited',
    )

    if form.cleaned_data['style'] == 'html':
        start = HTML_HEADING.format(''.join(
            ['<th>{0}</th>'.format(h) for h in headers]))
        row_start = '<tr>'
        cell_name = cell_count = '<td>{0}</td>\n'
        row_end = '</tr>'
        mime = 'text/html'
        end = '</table>'
    else:
        start = '{0}\n{1} {2}\n{0}'.format(
            RST_HEADING,
            ' '.join(['{0:40}'.format(h) for h in headers[:2]]),
            ' '.join(['{0:24}'.format(h) for h in headers[2:]]),
        )
        row_start = ''
        cell_name = '{0:40} '
        cell_count = '{0:24} '
        row_end = ''
        mime = 'text/plain'
        end = RST_HEADING

    result = []

    result.append(start)

    for item in data:
        if row_start:
            result.append(row_start)
        result.append(''.join((
            cell_name.format(item['name']),
            cell_name.format(item['email']),
            cell_count.format(item['count']),
            cell_count.format(item['words']),
            cell_count.format(item['chars']),
            cell_count.format(item['t_words']),
            cell_count.format(item['t_chars']),
            cell_count.format(item['count_new']),
            cell_count.format(item['words_new']),
            cell_count.format(item['chars_new']),
            cell_count.format(item['t_words_new']),
            cell_count.format(item['t_chars_new']),
            cell_count.format(item['count_approve']),
            cell_count.format(item['words_approve']),
            cell_count.format(item['chars_approve']),
            cell_count.format(item['t_words_approve']),
            cell_count.format(item['t_chars_approve']),
            cell_count.format(item['count_edit']),
            cell_count.format(item['words_edit']),
            cell_count.format(item['chars_edit']),
            cell_count.format(item['t_words_edit']),
            cell_count.format(item['t_chars_edit']),
        )))
        if row_end:
            result.append(row_end)

    result.append(end)

    return HttpResponse(
        '\n'.join(result),
        content_type='{0}; charset=utf-8'.format(mime),
    )
Ejemplo n.º 30
0
def search_replace(request, project, component=None, lang=None):
    obj, unit_set, context = parse_url(request, project, component, lang)

    form = ReplaceForm(request.POST)

    if not form.is_valid():
        messages.error(request, _("Failed to process form!"))
        show_form_errors(request, form)
        return redirect(obj)

    search_text = form.cleaned_data["search"]
    replacement = form.cleaned_data["replacement"]

    matching = unit_set.filter(target__contains=search_text)

    updated = 0
    if matching.exists():
        confirm = ReplaceConfirmForm(matching, request.POST)
        limited = False

        if matching.count() > 300:
            matching = matching.order_by("id")[:250]
            limited = True

        if not confirm.is_valid():
            for unit in matching:
                unit.replacement = unit.target.replace(search_text, replacement)
            context.update(
                {
                    "matching": matching,
                    "search_query": search_text,
                    "replacement": replacement,
                    "form": form,
                    "limited": limited,
                    "confirm": ReplaceConfirmForm(matching),
                }
            )
            return render(request, "replace.html", context)

        matching = confirm.cleaned_data["units"]

        with transaction.atomic():
            for unit in matching.select_for_update():
                if not request.user.has_perm("unit.edit", unit):
                    continue
                unit.translate(
                    request.user,
                    unit.target.replace(search_text, replacement),
                    unit.state,
                    change_action=Change.ACTION_REPLACE,
                )
                updated += 1

    import_message(
        request,
        updated,
        _("Search and replace completed, no strings were updated."),
        ngettext(
            "Search and replace completed, %d string was updated.",
            "Search and replace completed, %d strings were updated.",
            updated,
        ),
    )

    return redirect(obj)
Ejemplo n.º 31
0
def get_credits(request, project=None, component=None):
    """View for credits."""
    if project is None:
        obj = None
        kwargs = {"translation__pk__gt": 0}
    elif component is None:
        obj = get_project(request, project)
        kwargs = {"translation__component__project": obj}
    else:
        obj = get_component(request, project, component)
        kwargs = {"translation__component": obj}

    form = ReportsForm(request.POST)

    if not form.is_valid():
        show_form_errors(request, form)
        return redirect_param(obj or "home", "#reports")

    data = generate_credits(
        None if request.user.has_perm("reports.view", obj) else request.user,
        form.cleaned_data["start_date"], form.cleaned_data["end_date"],
        **kwargs)

    if form.cleaned_data["style"] == "json":
        return JsonResponse(data=data, safe=False)

    if form.cleaned_data["style"] == "html":
        start = "<table>"
        row_start = "<tr>"
        language_format = "<th>{0}</th>"
        translator_start = "<td><ul>"
        translator_format = '<li><a href="mailto:{0}">{1}</a> ({2})</li>'
        translator_end = "</ul></td>"
        row_end = "</tr>"
        mime = "text/html"
        end = "</table>"
    else:
        start = ""
        row_start = ""
        language_format = "* {0}\n"
        translator_start = ""
        translator_format = "    * {1} <{0}> ({2})"
        translator_end = ""
        row_end = ""
        mime = "text/plain"
        end = ""

    result = []

    result.append(start)

    for language in data:
        name, translators = language.popitem()
        result.append(row_start)
        result.append(language_format.format(name))
        result.append(translator_start + "\n".join(
            translator_format.format(*t)
            for t in translators) + translator_end)
        result.append(row_end)

    result.append(end)

    return HttpResponse("\n".join(result),
                        content_type="{0}; charset=utf-8".format(mime))
Ejemplo n.º 32
0
def search(request, project=None, component=None, lang=None):
    """Perform site-wide search on units."""
    is_ratelimited = not check_rate_limit("search", request)
    search_form = SearchForm(request.user, request.GET)
    context = {"search_form": search_form}
    if component:
        obj = get_component(request, project, component)
        context["component"] = obj
        context["project"] = obj.project
        context["back_url"] = obj.get_absolute_url()
    elif project:
        obj = get_project(request, project)
        context["project"] = obj
        context["back_url"] = obj.get_absolute_url()
    else:
        obj = None
        context["back_url"] = None
    if lang:
        s_language = get_object_or_404(Language, code=lang)
        context["language"] = s_language
        if obj:
            if component:
                context["back_url"] = obj.translation_set.get(
                    language=s_language).get_absolute_url()
            else:
                context["back_url"] = reverse("project-language",
                                              kwargs={
                                                  "project": project,
                                                  "lang": lang
                                              })
        else:
            context["back_url"] = s_language.get_absolute_url()

    if not is_ratelimited and request.GET and search_form.is_valid():
        # Filter results by ACL
        if component:
            units = Unit.objects.filter(translation__component=obj)
        elif project:
            units = Unit.objects.filter(translation__component__project=obj)
        else:
            units = Unit.objects.filter(
                translation__component__project_id__in=request.user.
                allowed_project_ids)
        units = units.search(search_form.cleaned_data.get("q", "")).distinct()
        if lang:
            units = units.filter(translation__language=context["language"])

        units = get_paginator(request, units.order())

        context["show_results"] = True
        context["page_obj"] = units
        context["title"] = _("Search for %s") % (search_form.cleaned_data["q"])
        context["query_string"] = search_form.urlencode()
        context["search_query"] = search_form.cleaned_data["q"]
    elif is_ratelimited:
        messages.error(request,
                       _("Too many search queries, please try again later."))
    elif request.GET:
        messages.error(request, _("Invalid search query!"))
        show_form_errors(request, search_form)

    return render(request, "search.html", context)