예제 #1
0
def process_modelformset(request, model_class, queryset, **kwargs):
    """With the Django model class `model_class` and the given `queryset`,
    construct a formset process its submission."""

    # Create a formset class for the model `model_class` (i.e. it will contain
    # forms whose contents are based on the fields of `model_class`);
    # parameters for the construction of the forms used in the formset should
    # be in kwargs.
    formset_class = modelformset_factory(model_class, **kwargs)

    if queryset is None:
        queryset = model_class.objects.all()

    # If the request is a POST, we want to possibly update our data
    if request.method == 'POST' and request.POST:
        # Create a formset from all the 'model_class' instances whose values
        # will be updated using the contents of request.POST
        objects = paginate(request, queryset)
        formset = formset_class(request.POST, queryset=objects.object_list)

        # Validate all the forms in the formset
        if formset.is_valid():
            # If all is well, Django can save all our data for us
            formset.save()
        else:
            # Otherwise, complain to the user that something went wrong
            return formset, _("There are errors in the form. Please review "
                              "the problems below."), objects

        # Hack to force reevaluation of same query
        queryset = queryset.filter()

    objects = paginate(request, queryset)

    return formset_class(queryset=objects.object_list), None, objects
예제 #2
0
파일: util.py 프로젝트: a-covar/pootle
def process_modelformset(request, model_class, queryset, **kwargs):
    """With the Django model class `model_class` and the given `queryset`,
    construct a formset process its submission."""

    # Create a formset class for the model `model_class` (i.e. it will contain
    # forms whose contents are based on the fields of `model_class`);
    # parameters for the construction of the forms used in the formset should
    # be in kwargs.
    formset_class = modelformset_factory(model_class, **kwargs)

    if queryset is None:
        queryset = model_class.objects.all()

    # If the request is a POST, we want to possibly update our data
    if request.method == 'POST' and request.POST:
        # Create a formset from all the 'model_class' instances whose values
        # will be updated using the contents of request.POST
        objects = paginate(request, queryset)
        formset = formset_class(request.POST, queryset=objects.object_list)

        # Validate all the forms in the formset
        if formset.is_valid():
            # If all is well, Django can save all our data for us
            formset.save()
        else:
            # Otherwise, complain to the user that something went wrong
            return formset, _("There are errors in the form. Please review "
                              "the problems below."), objects

        # Hack to force reevaluation of same query
        queryset = queryset.filter()

    objects = paginate(request, queryset)

    return formset_class(queryset=objects.object_list), None, objects
예제 #3
0
def get_view_units(request, units_queryset, store, limit=0):
    """Gets source and target texts excluding the editing unit.

    :return: An object in JSON notation that contains the source and target
             texts for units that will be displayed before and after editing
             unit.

             If asked by using the ``meta`` and ``pager`` parameters,
             metadata and pager information will be calculated and returned
             too.
    """
    current_unit = None
    json = {}

    try:
        limit = int(limit)
    except ValueError:
        limit = None

    if not limit:
        limit = request.profile.get_unit_rows()

    step_queryset = get_step_query(request, units_queryset)

    # Return metadata it has been explicitely requested
    if request.GET.get('meta', False):
        tp = request.translation_project
        json["meta"] = {"source_lang": tp.project.source_language.code,
                        "source_dir": tp.project.source_language.get_direction(),
                        "target_lang": tp.language.code,
                        "target_dir": tp.language.get_direction(),
                        "project_style": tp.project.checkstyle}

    # Maybe we are trying to load directly a specific unit, so we have
    # to calculate its page number
    uid = request.GET.get('uid', None)
    if uid:
        current_unit = units_queryset.get(id=uid)
        preceding = _get_index_in_qs(step_queryset, current_unit, store)
        page = preceding / limit + 1
    else:
        page = None

    pager = paginate(request, step_queryset, items=limit, page=page)

    json["units"] = _build_units_list(pager.object_list)

    # Return paging information if requested to do so
    if request.GET.get('pager', False):
        json["pager"] = _build_pager_dict(pager)
        if not current_unit:
            try:
                json["uid"] = json["units"][0]["id"]
            except IndexError:
                pass
        else:
            json["uid"] = current_unit.id

    response = jsonify(json)
    return HttpResponse(response, mimetype="application/json")
예제 #4
0
파일: views.py 프로젝트: mellterm/pootle
def get_current_units(request, step_queryset, units_queryset):
    """returns current active unit, and in case of POST previously active unit"""
    edit_unit = None
    prev_unit = None
    pager = None
    # GET gets priority
    if 'unit' in request.GET:
        # load a specific unit in GET
        try:
            edit_id = int(request.GET['unit'])
            edit_unit = step_queryset.get(id=edit_id)
        except (Unit.DoesNotExist, ValueError):
            pass
    elif 'page' in request.GET:
        # load first unit in a specific page
        profile = get_profile(request.user)
        unit_rows = profile.get_unit_rows()
        pager = paginate(request, units_queryset, items=unit_rows)
        edit_unit = pager.object_list[0]
    elif 'id' in request.POST and 'index' in request.POST:
        # GET doesn't specify a unit try POST
        prev_id = int(request.POST['id'])
        prev_index = int(request.POST['index'])
        pootle_path = request.POST['pootle_path']
        back = request.POST.get('back', False)
        if back:
            queryset = (step_queryset.filter(store__pootle_path=pootle_path, index__lte=prev_index) | \
                        step_queryset.filter(store__pootle_path__lt=pootle_path)
                        ).order_by('-store__pootle_path', '-index')
        else:
            queryset = (step_queryset.filter(store__pootle_path=pootle_path, index__gte=prev_index) | \
                        step_queryset.filter(store__pootle_path__gt=pootle_path)
                        ).order_by('store__pootle_path', 'index')

        for unit in queryset.iterator():
            if edit_unit is None and prev_unit is not None:
                edit_unit = unit
                break
            if unit.id == prev_id:
                prev_unit = unit
            elif unit.index > prev_index or back and unit.index < prev_index:
                logging.debug("submitting to a unit no longer part of step query, %s:%d", (pootle_path, prev_id))
                # prev_unit no longer part of the query, load it directly
                edit_unit = unit
                prev_unit = Unit.objects.get(store__pootle_path=pootle_path, id=prev_id)
                break

    if edit_unit is None:
        if prev_unit is not None:
            # probably prev_unit was last unit in chain.
            if back:
                edit_unit = prev_unit
        else:
            # all methods failed, get first unit in queryset
            try:
                edit_unit = step_queryset.iterator().next()
            except StopIteration:
                pass

    return prev_unit, edit_unit, pager
예제 #5
0
def get_edit_unit(request, pootle_path, uid):
    """
    Given a store path C{pootle_path} and unit id C{uid}, gathers all the
    necessary information to build the editing widget.

    @return: A templatised editing widget is returned within the C{editor}
    variable and paging information is also returned if the page number has
    changed.
    """
    if pootle_path[0] != '/':
        pootle_path = '/' + pootle_path

    unit = get_object_or_404(Unit, id=uid, store__pootle_path=pootle_path)
    translation_project = unit.store.translation_project
    language = translation_project.language
    form_class = unit_form_factory(language, len(unit.source.strings))
    form = form_class(instance=unit)
    store = unit.store
    directory = store.parent
    profile = get_profile(request.user)
    alt_src_langs = get_alt_src_langs(request, profile, translation_project)
    project = translation_project.project
    template_vars = {'unit': unit,
                     'form': form,
                     'store': store,
                     'profile': profile,
                     'user': request.user,
                     'language': language,
                     'source_language': translation_project.project.source_language,
                     'cantranslate': check_profile_permission(profile, "translate", directory),
                     'cansuggest': check_profile_permission(profile, "suggest", directory),
                     'canreview': check_profile_permission(profile, "review", directory),
                     'altsrcs': find_altsrcs(unit, alt_src_langs, store=store, project=project),
                     'suggestions': get_sugg_list(unit)}

    t = loader.get_template('unit/edit.html')
    c = RequestContext(request, template_vars)
    json = {'success': True,
            'editor': t.render(c)}

    current_page = int(request.GET.get('page', 1))
    all_units = unit.store.units
    units_qs = _filter_queryset(request.GET, all_units)
    unit_rows = profile.get_unit_rows()
    current_unit = unit
    if current_unit is not None:
        current_index = _get_index_in_qs(units_qs, current_unit)
        preceding = units_qs[:current_index].count()
        page = preceding / unit_rows + 1
        if page != current_page:
            pager = paginate(request, units_qs, items=unit_rows, page=page)
            json["pager"] = _build_pager_dict(pager)
        # Return context rows if filtering is applied
        if 'filter' in request.GET and request.GET.get('filter', 'all') != 'all':
            edit_index = _get_index_in_qs(all_units, current_unit)
            json["ctxt"] = _filter_ctxt_units(all_units, edit_index, 2)

    response = simplejson.dumps(json)
    return HttpResponse(response, mimetype="application/json")
예제 #6
0
def get_tp_metadata(request, pootle_path, uid=None):
    """
    @return: An object in JSON notation that contains the metadata information
    about the current translation project: source/target language codes,
    the direction of the text and also a initial pager.

    Success status that indicates if the information has been succesfully
    retrieved or not is returned as well.
    """
    if pootle_path[0] != '/':
        pootle_path = '/' + pootle_path
    profile = get_profile(request.user)
    json = {}

    try:
        store = Store.objects.select_related('translation_project', 'parent').get(pootle_path=pootle_path)
        if not check_profile_permission(profile, 'view', store.parent):
            json["success"] = False
            json["msg"] = _("You do not have rights to access translation mode.")
        else:
            units_qs = _filter_queryset(request.GET, store.units)
            unit_rows = profile.get_unit_rows()

            try:
                if uid is None:
                    try:
                        current_unit = units_qs[0]
                        json["uid"] = units_qs[0].id
                    except IndexError:
                        current_unit = None
                else:
                    current_unit = units_qs.get(id=uid, store__pootle_path=pootle_path)
                if current_unit is not None:
                    current_index = _get_index_in_qs(units_qs, current_unit)
                    preceding = units_qs[:current_index].count()
                    page = preceding / unit_rows + 1
                    pager = paginate(request, units_qs, items=unit_rows, page=page)
                    json["pager"] = _build_pager_dict(pager)
                tp = store.translation_project
                json["meta"] = {"source_lang": tp.project.source_language.code,
                                "source_dir": tp.project.source_language.get_direction(),
                                "target_lang": tp.language.code,
                                "target_dir": tp.language.get_direction()}
                json["success"] = True
            except Unit.DoesNotExist:
                json["success"] = False
                json["msg"] = _("Unit %(uid)s does not exist on %(path)s." %
                                {'uid': uid, 'path': pootle_path})
    except Store.DoesNotExist:
        json["success"] = False
        json["msg"] = _("Store %(path)s does not exist." %
                        {'path': pootle_path})

    response = simplejson.dumps(json)
    return HttpResponse(response, mimetype="application/json")
예제 #7
0
파일: views.py 프로젝트: cmpitg/pootle
def get_units(request):
    """Gets source and target texts and its metadata.

    :return: A JSON-encoded object containing the source and target texts
        grouped by the store they belong to.

        When the ``pager`` GET parameter is present, pager information
        will be returned too.
    """
    pootle_path = request.GET.get('path', None)
    if pootle_path is None:
        raise Http400(_('Arguments missing.'))

    page = None

    request.profile = get_profile(request.user)
    limit = request.profile.get_unit_rows()

    units_qs = Unit.objects.get_for_path(pootle_path, request.profile)
    step_queryset = get_step_query(request, units_qs)

    # Maybe we are trying to load directly a specific unit, so we have
    # to calculate its page number
    uid = request.GET.get('uid', None)
    if uid is not None:
        try:
            # XXX: Watch for performance, might want to drop into raw SQL
            # at some stage
            uid_list = list(step_queryset.values_list('id', flat=True))
            preceding = uid_list.index(int(uid))
            page = preceding / limit + 1
        except ValueError:
            pass  # uid wasn't a number or not present in the results

    pager = paginate(request, step_queryset, items=limit, page=page)

    unit_groups = []
    units_by_path = groupby(pager.object_list, lambda x: x.store.pootle_path)
    for pootle_path, units in units_by_path:
        unit_groups.append(_path_units_with_meta(pootle_path, units))

    response = {
        'unit_groups': unit_groups,
    }

    if request.GET.get('pager', False):
        response['pager'] = {
            'count': pager.paginator.count,
            'number': pager.number,
            'num_pages': pager.paginator.num_pages,
            'per_page': pager.paginator.per_page,
        }

    return HttpResponse(jsonify(response), mimetype="application/json")
예제 #8
0
def get_units(request):
    """Gets source and target texts and its metadata.

    :return: A JSON-encoded object containing the source and target texts
        grouped by the store they belong to.

        When the ``pager`` GET parameter is present, pager information
        will be returned too.
    """
    pootle_path = request.GET.get('path', None)
    if pootle_path is None:
        raise Http400(_('Arguments missing.'))

    page = None

    request.profile = get_profile(request.user)
    limit = request.profile.get_unit_rows()

    units_qs = Unit.objects.get_for_path(pootle_path, request.profile)
    step_queryset = get_step_query(request, units_qs)

    # Maybe we are trying to load directly a specific unit, so we have
    # to calculate its page number
    uid = request.GET.get('uid', None)
    if uid is not None:
        try:
            # XXX: Watch for performance, might want to drop into raw SQL
            # at some stage
            uid_list = list(step_queryset.values_list('id', flat=True))
            preceding = uid_list.index(int(uid))
            page = preceding / limit + 1
        except ValueError:
            pass  # uid wasn't a number or not present in the results

    pager = paginate(request, step_queryset, items=limit, page=page)

    unit_groups = []
    units_by_path = groupby(pager.object_list, lambda x: x.store.pootle_path)
    for pootle_path, units in units_by_path:
        unit_groups.append(_path_units_with_meta(pootle_path, units))

    response = {
        'unit_groups': unit_groups,
    }

    if request.GET.get('pager', False):
        response['pager'] = {
            'count': pager.paginator.count,
            'number': pager.number,
            'num_pages': pager.paginator.num_pages,
            'per_page': pager.paginator.per_page,
        }

    return HttpResponse(jsonify(response), mimetype="application/json")
예제 #9
0
def process_modelformset(request, model_class, queryset, **kwargs):
    """
    With the Django model class 'model_class' and the Django form class
    'form_class', construct a Django formset which can manipulate
    """

    # Create a formset class for the model 'model_class' (i.e. it will contain
    # forms whose contents are based on the fields of 'model_class');
    # parameters for the construction of the forms used in the formset should
    # be in kwargs. In Django 1.0, the interface to modelformset_factory is
    # def modelformset_factory(
    #     model, form=ModelForm, formfield_callback=lambda f: f.formfield(),
    #     formset=BaseModelFormSet,
    #     extra=1, can_delete=False, can_order=False,
    #     max_num=0, fields=None, exclude=None)
    formset_class = modelformset_factory(model_class, **kwargs)

    if queryset is None:
        queryset = model_class.objects.all()


    # If the request is a POST, we want to possibly update our data
    if request.method == 'POST' and request.POST:
        # Create a formset from all the 'model_class' instances whose values
        # will be updated using the contents of request.POST
        objects = paginate(request, queryset)
        formset = formset_class(request.POST, queryset=objects.object_list)
        # Validate all the forms in the formset
        if formset.is_valid():
            # If all is well, Django can save all our data for us
            formset.save()
        else:
            # Otherwise, complain to the user that something went wrong
            return formset, _("There are errors in the form. Please review " \
                              "the problems below."), objects

        # hack to force reevaluation of same query
        queryset = queryset.filter()

    objects = paginate(request, queryset)
    return formset_class(queryset=objects.object_list), None, objects
예제 #10
0
def process_modelformset(request, model_class, queryset, **kwargs):
    """With the Django model class 'model_class' and the Django form class 'form_class',
    construct a Django formset which can manipulate """

    # Create a formset class for the model 'model_class' (i.e. it will contain forms whose
    # contents are based on the fields of 'model_class'); parameters for the construction
    # of the forms used in the formset should be in kwargs. In Django 1.0, the interface
    # to modelformset_factory is
    # def modelformset_factory(model, form=ModelForm, formfield_callback=lambda f: f.formfield(),
    #                          formset=BaseModelFormSet,
    #                          extra=1, can_delete=False, can_order=False,
    #                          max_num=0, fields=None, exclude=None)
    formset_class = modelformset_factory(model_class, **kwargs)

    if queryset is None:
        queryset = model_class.objects.all()

    # If the request is a POST, we want to possibly update our data
    if request.method == 'POST' and request.POST:
        # Create a formset from all the 'model_class' instances whose values will
        # be updated using the contents of request.POST
        objects = paginate(request, queryset)
        formset = formset_class(request.POST, queryset=objects.object_list)
        # Validate all the forms in the formset
        if formset.is_valid():
            # If all is well, Django can save all our data for us
            formset.save()
        else:
            # Otherwise, complain to the user that something went wrong
            return formset, _(
                "There are errors in the form. Please review the problems below."
            ), objects

        # hack to force reevaluation of same query
        queryset = queryset.filter()

    objects = paginate(request, queryset)
    return formset_class(queryset=objects.object_list), None, objects
예제 #11
0
def process_submit(request, pootle_path, uid, type):
    """
    @return: An object in JSON notation that contains the previous
    and last units for the unit next to unit C{uid}.

    This object also contains success status that indicates if the submission
    has been succesfully saved or not.
    """
    json = {}
    if pootle_path[0] != '/':
        pootle_path = '/' + pootle_path

    try:
        unit = Unit.objects.get(id=uid, store__pootle_path=pootle_path)
        directory = unit.store.parent
        profile = get_profile(request.user)
        cantranslate = check_profile_permission(profile, "translate",
                                                directory)
        cansuggest = check_profile_permission(profile, "suggest", directory)
        if type == 'submission' and not cantranslate or \
           type == 'suggestion' and not cansuggest:
            json["success"] = False
            json["msg"] = _(
                "You do not have rights to access translation mode.")
        else:
            translation_project = unit.store.translation_project
            language = translation_project.language
            form_class = unit_form_factory(language, len(unit.source.strings))
            form = form_class(request.POST, instance=unit)
            if form.is_valid():
                if type == 'submission':
                    if form.instance._target_updated or \
                       form.instance._translator_comment_updated or \
                       form.instance._state_updated:
                        form.save()
                        sub = Submission(
                            translation_project=translation_project,
                            submitter=get_profile(request.user))
                        sub.save()
                elif type == 'suggestion':
                    if form.instance._target_updated:
                        #HACKISH: django 1.2 stupidly modifies instance on
                        # model form validation, reload unit from db
                        unit = Unit.objects.get(id=unit.id)
                        sugg = unit.add_suggestion(
                            form.cleaned_data['target_f'],
                            get_profile(request.user))
                        if sugg:
                            SuggestionStat.objects.get_or_create(
                                translation_project=translation_project,
                                suggester=get_profile(request.user),
                                state='pending',
                                unit=unit.id)

                current_page = int(request.POST.get('page', 1))
                all_units = unit.store.units
                units_qs = _filter_queryset(request.POST, all_units)
                unit_rows = profile.get_unit_rows()
                current_unit = unit
                if current_unit is not None:
                    current_index = _get_index_in_qs(units_qs, current_unit)
                    preceding = units_qs[:current_index].count()
                    page = preceding / unit_rows + 1
                    if page != current_page:
                        pager = paginate(request,
                                         units_qs,
                                         items=unit_rows,
                                         page=page)
                        json["pager"] = _build_pager_dict(pager)
                    try:
                        new_index = current_index + 1
                        json["new_uid"] = units_qs[new_index].id
                    except IndexError:
                        # End of set: let's assume the new unit is the last we had
                        new_unit = unit
                        json["new_uid"] = None
                    json["success"] = True
            else:
                # Form failed
                json["success"] = False
                json["msg"] = _("Failed to process submit.")
    except Store.DoesNotExist:
        json["success"] = False
        json["msg"] = _("Store %(path)s does not exist." %
                        {'path': pootle_path})
    except Unit.DoesNotExist:
        json["success"] = False
        json["msg"] = _("Unit %(uid)s does not exist on %(path)s." % {
            'uid': uid,
            'path': pootle_path
        })

    response = simplejson.dumps(json)
    return HttpResponse(response, mimetype="application/json")
예제 #12
0
def translate_page(request, units_queryset, store=None):
    if not check_permission("view", request):
        raise PermissionDenied(_("You do not have rights to access this translation project."))

    cantranslate = check_permission("translate", request)
    cansuggest = check_permission("suggest", request)
    canreview = check_permission("review", request)
    translation_project = request.translation_project
    language = translation_project.language
    # shouldn't we globalize profile context
    profile = get_profile(request.user)

    step_queryset = None

    # Process search first
    search_form = None
    if 'search' in request.GET and 'sfields' in request.GET:
        search_form = SearchForm(request.GET)
        if search_form.is_valid():
            step_queryset = get_search_step_query(request.translation_project, search_form, units_queryset)
    else:
        search_form = SearchForm()

    # which units are we interested in?
    if step_queryset is None:
        step_queryset = get_step_query(request, units_queryset)

    prev_unit, edit_unit, pager = get_current_units(request, step_queryset, units_queryset)

    # time to process POST submission
    form = None
    if prev_unit is not None and ('submit' in request.POST or 'suggest' in request.POST):
        # check permissions
        if 'submit'  in request.POST and not cantranslate or \
           'suggest' in request.POST and not cansuggest:
            raise PermissionDenied

        if prev_unit.hasplural():
            snplurals = len(prev_unit.source.strings)
        else:
            snplurals = None
        form_class = unit_form_factory(language, snplurals)
        form = form_class(request.POST, instance=prev_unit)
        if form.is_valid():
            if cantranslate and 'submit' in request.POST:
                if form.instance._target_updated or form.instance._translator_comment_updated or \
                       form.instance._state_updated:
                    form.save()
                    translation_submitted.send(sender=translation_project,
                                               unit=form.instance, profile=profile)

                    sub = Submission(translation_project=translation_project,
                                     submitter=get_profile(request.user))
                    sub.save()

            elif cansuggest and 'suggest' in request.POST:
                if form.instance._target_updated:
                    #HACKISH: django 1.2 stupidly modifies instance on
                    # model form validation, reload unit from db
                    prev_unit = Unit.objects.get(id=prev_unit.id)
                    sugg = prev_unit.add_suggestion(form.cleaned_data['target_f'], get_profile(request.user))
                    if sugg:
                        SuggestionStat.objects.get_or_create(translation_project=translation_project,
                                                             suggester=get_profile(request.user),
                                                             state='pending', unit=prev_unit.id)
        else:
            # form failed, don't skip to next unit
            edit_unit = prev_unit

    if edit_unit is None:
        # no more units to step through, display end of translation message
        return translate_end(request, translation_project)

    # only create form for edit_unit if prev_unit was processed successfully
    if form is None or form.is_valid():
        if edit_unit.hasplural():
            snplurals = len(edit_unit.source.strings)
        else:
            snplurals = None
        form_class = unit_form_factory(language, snplurals)
        form = form_class(instance=edit_unit)

    if store is None:
        store = edit_unit.store
        pager_query = units_queryset
        preceding = (pager_query.filter(store=store, index__lt=edit_unit.index) | \
                     pager_query.filter(store__pootle_path__lt=store.pootle_path)).count()
        store_preceding = store.units.filter(index__lt=edit_unit.index).count()
    else:
        pager_query = store.units
        preceding = pager_query.filter(index__lt=edit_unit.index).count()
        store_preceding = preceding

    unit_rows = profile.get_unit_rows()

    # regardless of the query used to step through units, we will
    # display units in their original context, and display a pager for
    # the store not for the unit_step query
    if pager is None:
        page = preceding / unit_rows + 1
        pager = paginate(request, pager_query, items=unit_rows, page=page, orphans=0)

    # we always display the active unit in the middle of the page to
    # provide context for translators
    context_rows = (unit_rows - 1) / 2
    if store_preceding > context_rows:
        unit_position = store_preceding % unit_rows
        page_length = pager.end_index() - pager.start_index() + 1
        if page_length < unit_rows:
            if pager.has_other_pages():
                units_query = store.units[page_length:]
            else:
                units_query = store.units
            page = store_preceding / unit_rows
            units = paginate(request, units_query, items=unit_rows, page=page, orphans=0).object_list
        elif unit_position < context_rows:
            # units too close to the top of the batch
            offset = unit_rows - (context_rows - unit_position)
            units_query = store.units[offset:]
            page = store_preceding / unit_rows
            units = paginate(request, units_query, items=unit_rows, page=page, orphans=0).object_list
        elif unit_position >= unit_rows - context_rows:
            # units too close to the bottom of the batch
            offset = context_rows - (unit_rows - unit_position - 1)
            units_query = store.units[offset:]
            page = store_preceding / unit_rows + 1
            units = paginate(request, units_query, items=unit_rows, page=page, orphans=0).object_list
        else:
            units = pager.object_list
    else:
        units = store.units[:unit_rows]

    # caluclate url querystring so state is retained on POST
    # we can't just use request URL cause unit and page GET vars cancel state
    GET_vars = []
    for key, values in request.GET.lists():
        if key not in ('page', 'unit'):
            for value in values:
                GET_vars.append('%s=%s' % (key, value))

    # links for quality check documentation
    checks = []
    for check in request.GET.get('matchnames','').split(','):
        if not check:
            continue
        safe_check = escape(check)
        link = '<a href="http://translate.sourceforge.net/wiki/toolkit/pofilter_tests#%s" target="_blank">%s</a>' % (safe_check, safe_check)
        checks.append(_('checking %s', link))

    # precalculate alternative source languages
    alt_src_langs = get_alt_src_langs(request, profile, translation_project)
    alt_src_codes = alt_src_langs.values_list('code', flat=True)

    context = {
        'unit_rows': unit_rows,
        'alt_src_langs': alt_src_langs,
        'alt_src_codes': alt_src_codes,
        'cantranslate': cantranslate,
        'cansuggest': cansuggest,
        'canreview': canreview,
        'form': form,
        'search_form': search_form,
        'edit_unit': edit_unit,
        'store': store,
        'pager': pager,
        'units': units,
        'language': language,
        'translation_project': translation_project,
        'project': translation_project.project,
        'profile': profile,
        'source_language': translation_project.project.source_language,
        'directory': store.parent,
        'GET_state': '&'.join(GET_vars),
        'checks': checks,
        'MT_BACKENDS': settings.MT_BACKENDS,
        }
    return render_to_response('store/translate.html', context, context_instance=RequestContext(request))
예제 #13
0
def translate_page(request, units_queryset, store=None):
    if not check_permission("view", request):
        raise PermissionDenied(
            _("You do not have rights to access this translation project."))

    cantranslate = check_permission("translate", request)
    cansuggest = check_permission("suggest", request)
    canreview = check_permission("review", request)
    translation_project = request.translation_project
    language = translation_project.language
    # shouldn't we globalize profile context
    profile = get_profile(request.user)

    step_queryset = None

    # Process search first
    search_form = None
    if 'search' in request.GET and 'sfields' in request.GET:
        search_form = SearchForm(request.GET)
        if search_form.is_valid():
            step_queryset = get_search_step_query(request.translation_project,
                                                  search_form, units_queryset)
    else:
        search_form = SearchForm()

    # which units are we interested in?
    if step_queryset is None:
        step_queryset = get_step_query(request, units_queryset)

    prev_unit, edit_unit, pager = get_current_units(request, step_queryset,
                                                    units_queryset)

    # time to process POST submission
    form = None
    if prev_unit is not None and ('submit' in request.POST
                                  or 'suggest' in request.POST):
        # check permissions
        if 'submit'  in request.POST and not cantranslate or \
           'suggest' in request.POST and not cansuggest:
            raise PermissionDenied

        if prev_unit.hasplural():
            snplurals = len(prev_unit.source.strings)
        else:
            snplurals = None
        form_class = unit_form_factory(language, snplurals)
        form = form_class(request.POST, instance=prev_unit)
        if form.is_valid():
            if cantranslate and 'submit' in request.POST:
                if form.instance._target_updated or form.instance._translator_comment_updated or \
                       form.instance._state_updated:
                    form.save()
                    translation_submitted.send(sender=translation_project,
                                               unit=form.instance,
                                               profile=profile)

                    sub = Submission(translation_project=translation_project,
                                     submitter=get_profile(request.user))
                    sub.save()

            elif cansuggest and 'suggest' in request.POST:
                if form.instance._target_updated:
                    #HACKISH: django 1.2 stupidly modifies instance on
                    # model form validation, reload unit from db
                    prev_unit = Unit.objects.get(id=prev_unit.id)
                    sugg = prev_unit.add_suggestion(
                        form.cleaned_data['target_f'],
                        get_profile(request.user))
                    if sugg:
                        SuggestionStat.objects.get_or_create(
                            translation_project=translation_project,
                            suggester=get_profile(request.user),
                            state='pending',
                            unit=prev_unit.id)
        else:
            # form failed, don't skip to next unit
            edit_unit = prev_unit

    if edit_unit is None:
        # no more units to step through, display end of translation message
        return translate_end(request, translation_project)

    # only create form for edit_unit if prev_unit was processed successfully
    if form is None or form.is_valid():
        if edit_unit.hasplural():
            snplurals = len(edit_unit.source.strings)
        else:
            snplurals = None
        form_class = unit_form_factory(language, snplurals)
        form = form_class(instance=edit_unit)

    if store is None:
        store = edit_unit.store
        pager_query = units_queryset
        preceding = (pager_query.filter(store=store, index__lt=edit_unit.index) | \
                     pager_query.filter(store__pootle_path__lt=store.pootle_path)).count()
        store_preceding = store.units.filter(index__lt=edit_unit.index).count()
    else:
        pager_query = store.units
        preceding = pager_query.filter(index__lt=edit_unit.index).count()
        store_preceding = preceding

    unit_rows = profile.get_unit_rows()

    # regardless of the query used to step through units, we will
    # display units in their original context, and display a pager for
    # the store not for the unit_step query
    if pager is None:
        page = preceding / unit_rows + 1
        pager = paginate(request,
                         pager_query,
                         items=unit_rows,
                         page=page,
                         orphans=0)

    # we always display the active unit in the middle of the page to
    # provide context for translators
    context_rows = (unit_rows - 1) / 2
    if store_preceding > context_rows:
        unit_position = store_preceding % unit_rows
        page_length = pager.end_index() - pager.start_index() + 1
        if page_length < unit_rows:
            if pager.has_other_pages():
                units_query = store.units[page_length:]
            else:
                units_query = store.units
            page = store_preceding / unit_rows
            units = paginate(request,
                             units_query,
                             items=unit_rows,
                             page=page,
                             orphans=0).object_list
        elif unit_position < context_rows:
            # units too close to the top of the batch
            offset = unit_rows - (context_rows - unit_position)
            units_query = store.units[offset:]
            page = store_preceding / unit_rows
            units = paginate(request,
                             units_query,
                             items=unit_rows,
                             page=page,
                             orphans=0).object_list
        elif unit_position >= unit_rows - context_rows:
            # units too close to the bottom of the batch
            offset = context_rows - (unit_rows - unit_position - 1)
            units_query = store.units[offset:]
            page = store_preceding / unit_rows + 1
            units = paginate(request,
                             units_query,
                             items=unit_rows,
                             page=page,
                             orphans=0).object_list
        else:
            units = pager.object_list
    else:
        units = store.units[:unit_rows]

    # caluclate url querystring so state is retained on POST
    # we can't just use request URL cause unit and page GET vars cancel state
    GET_vars = []
    for key, values in request.GET.lists():
        if key not in ('page', 'unit'):
            for value in values:
                GET_vars.append('%s=%s' % (key, value))

    # links for quality check documentation
    checks = []
    for check in request.GET.get('matchnames', '').split(','):
        if not check:
            continue
        safe_check = escape(check)
        link = '<a href="http://translate.sourceforge.net/wiki/toolkit/pofilter_tests#%s" target="_blank">%s</a>' % (
            safe_check, safe_check)
        checks.append(_('checking %s', link))

    # precalculate alternative source languages
    alt_src_langs = get_alt_src_langs(request, profile, translation_project)
    alt_src_codes = alt_src_langs.values_list('code', flat=True)

    context = {
        'unit_rows': unit_rows,
        'alt_src_langs': alt_src_langs,
        'alt_src_codes': alt_src_codes,
        'cantranslate': cantranslate,
        'cansuggest': cansuggest,
        'canreview': canreview,
        'form': form,
        'search_form': search_form,
        'edit_unit': edit_unit,
        'store': store,
        'pager': pager,
        'units': units,
        'language': language,
        'translation_project': translation_project,
        'project': translation_project.project,
        'profile': profile,
        'source_language': translation_project.project.source_language,
        'directory': store.parent,
        'GET_state': '&'.join(GET_vars),
        'checks': checks,
        'MT_BACKENDS': settings.MT_BACKENDS,
    }
    return render_to_response('store/translate.html',
                              context,
                              context_instance=RequestContext(request))
예제 #14
0
def get_current_units(request, step_queryset, units_queryset):
    """returns current active unit, and in case of POST previously active unit"""
    edit_unit = None
    prev_unit = None
    pager = None
    # GET gets priority
    if 'unit' in request.GET:
        # load a specific unit in GET
        try:
            edit_id = int(request.GET['unit'])
            edit_unit = step_queryset.get(id=edit_id)
        except (Unit.DoesNotExist, ValueError):
            pass
    elif 'page' in request.GET:
        # load first unit in a specific page
        profile = get_profile(request.user)
        unit_rows = profile.get_unit_rows()
        pager = paginate(request, units_queryset, items=unit_rows, orphans=0)
        edit_unit = pager.object_list[0]

    elif 'id' in request.POST and 'index' in request.POST:
        # GET doesn't specify a unit try POST
        prev_id = int(request.POST['id'])
        prev_index = int(request.POST['index'])
        pootle_path = request.POST['pootle_path']
        back = request.POST.get('back', False)
        if back:
            queryset = (step_queryset.filter(store__pootle_path=pootle_path, index__lte=prev_index) | \
                        step_queryset.filter(store__pootle_path__lt=pootle_path)
                        ).order_by('-store__pootle_path', '-index')
        else:
            queryset = (step_queryset.filter(store__pootle_path=pootle_path, index__gte=prev_index) | \
                        step_queryset.filter(store__pootle_path__gt=pootle_path)
                        ).order_by('store__pootle_path', 'index')

        #FIXME: instead of using an arbitrary limit it would be best to page through mother query
        for unit in queryset[:64].iterator():
            if edit_unit is None and prev_unit is not None:
                edit_unit = unit
                break
            if unit.id == prev_id:
                prev_unit = unit
            elif unit.index > prev_index or back and unit.index < prev_index:
                logging.debug(
                    u"submitting to a unit no longer part of step query, %s:%d",
                    (pootle_path, prev_id))
                # prev_unit no longer part of the query, load it directly
                edit_unit = unit
                prev_unit = Unit.objects.get(store__pootle_path=pootle_path,
                                             id=prev_id)
                break

    if edit_unit is None:
        if prev_unit is not None:
            # probably prev_unit was last unit in chain.
            if back:
                edit_unit = prev_unit
        else:
            # all methods failed, get first unit in queryset
            try:
                edit_unit = step_queryset[0:1][0]
            except IndexError:
                pass

    return prev_unit, edit_unit, pager
예제 #15
0
def process_submit(request, pootle_path, uid, type):
    """
    @return: An object in JSON notation that contains the previous
    and last units for the unit next to unit C{uid}.

    This object also contains success status that indicates if the submission
    has been succesfully saved or not.
    """
    json = {}
    if pootle_path[0] != '/':
        pootle_path = '/' + pootle_path

    try:
        unit = Unit.objects.get(id=uid, store__pootle_path=pootle_path)
        directory = unit.store.parent
        profile = get_profile(request.user)
        cantranslate = check_profile_permission(profile, "translate", directory)
        cansuggest = check_profile_permission(profile, "suggest", directory)
        if type == 'submission' and not cantranslate or \
           type == 'suggestion' and not cansuggest:
            json["success"] = False
            json["msg"] = _("You do not have rights to access translation mode.")
        else:
            translation_project = unit.store.translation_project
            language = translation_project.language
            form_class = unit_form_factory(language, len(unit.source.strings))
            form = form_class(request.POST, instance=unit)
            if form.is_valid():
                if type == 'submission':
                    if form.instance._target_updated or \
                       form.instance._translator_comment_updated or \
                       form.instance._state_updated:
                        form.save()
                        sub = Submission(translation_project=translation_project,
                                         submitter=get_profile(request.user))
                        sub.save()
                elif type == 'suggestion':
                    if form.instance._target_updated:
                        #HACKISH: django 1.2 stupidly modifies instance on
                        # model form validation, reload unit from db
                        unit = Unit.objects.get(id=unit.id)
                        sugg = unit.add_suggestion(form.cleaned_data['target_f'], get_profile(request.user))
                        if sugg:
                            SuggestionStat.objects.get_or_create(translation_project=translation_project,
                                                                 suggester=get_profile(request.user),
                                                                 state='pending', unit=unit.id)

                current_page = int(request.POST.get('page', 1))
                all_units = unit.store.units
                units_qs = _filter_queryset(request.POST, all_units)
                unit_rows = profile.get_unit_rows()
                current_unit = unit
                if current_unit is not None:
                    current_index = _get_index_in_qs(units_qs, current_unit)
                    preceding = units_qs[:current_index].count()
                    page = preceding / unit_rows + 1
                    if page != current_page:
                        pager = paginate(request, units_qs, items=unit_rows, page=page)
                        json["pager"] = _build_pager_dict(pager)
                    try:
                        new_index = current_index + 1
                        json["new_uid"] = units_qs[new_index].id
                    except IndexError:
                        # End of set: let's assume the new unit is the last we had
                        new_unit = unit
                        json["new_uid"] = None
                    json["success"] = True
            else:
                # Form failed
                json["success"] = False
                json["msg"] = _("Failed to process submit.")
    except Store.DoesNotExist:
        json["success"] = False
        json["msg"] = _("Store %(path)s does not exist." %
                        {'path': pootle_path})
    except Unit.DoesNotExist:
        json["success"] = False
        json["msg"] = _("Unit %(uid)s does not exist on %(path)s." %
                        {'uid': uid, 'path': pootle_path})

    response = simplejson.dumps(json)
    return HttpResponse(response, mimetype="application/json")
예제 #16
0
def get_edit_unit(request, pootle_path, uid):
    """
    Given a store path C{pootle_path} and unit id C{uid}, gathers all the
    necessary information to build the editing widget.

    @return: A templatised editing widget is returned within the C{editor}
    variable and paging information is also returned if the page number has
    changed.
    """
    if pootle_path[0] != '/':
        pootle_path = '/' + pootle_path

    unit = get_object_or_404(Unit, id=uid, store__pootle_path=pootle_path)
    translation_project = unit.store.translation_project
    language = translation_project.language
    form_class = unit_form_factory(language, len(unit.source.strings))
    form = form_class(instance=unit)
    store = unit.store
    directory = store.parent
    profile = get_profile(request.user)
    alt_src_langs = get_alt_src_langs(request, profile, translation_project)
    project = translation_project.project
    template_vars = {
        'unit': unit,
        'form': form,
        'store': store,
        'profile': profile,
        'user': request.user,
        'language': language,
        'source_language': translation_project.project.source_language,
        'cantranslate': check_profile_permission(profile, "translate",
                                                 directory),
        'cansuggest': check_profile_permission(profile, "suggest", directory),
        'canreview': check_profile_permission(profile, "review", directory),
        'altsrcs': find_altsrcs(unit,
                                alt_src_langs,
                                store=store,
                                project=project),
        'suggestions': get_sugg_list(unit)
    }

    t = loader.get_template('unit/edit.html')
    c = RequestContext(request, template_vars)
    json = {'success': True, 'editor': t.render(c)}

    current_page = int(request.GET.get('page', 1))
    all_units = unit.store.units
    units_qs = _filter_queryset(request.GET, all_units)
    unit_rows = profile.get_unit_rows()
    current_unit = unit
    if current_unit is not None:
        current_index = _get_index_in_qs(units_qs, current_unit)
        preceding = units_qs[:current_index].count()
        page = preceding / unit_rows + 1
        if page != current_page:
            pager = paginate(request, units_qs, items=unit_rows, page=page)
            json["pager"] = _build_pager_dict(pager)
        # Return context rows if filtering is applied
        if 'filter' in request.GET and request.GET.get('filter',
                                                       'all') != 'all':
            edit_index = _get_index_in_qs(all_units, current_unit)
            json["ctxt"] = _filter_ctxt_units(all_units, edit_index, 2)

    response = simplejson.dumps(json)
    return HttpResponse(response, mimetype="application/json")
예제 #17
0
def get_tp_metadata(request, pootle_path, uid=None):
    """
    @return: An object in JSON notation that contains the metadata information
    about the current translation project: source/target language codes,
    the direction of the text and also a initial pager.

    Success status that indicates if the information has been succesfully
    retrieved or not is returned as well.
    """
    if pootle_path[0] != '/':
        pootle_path = '/' + pootle_path
    profile = get_profile(request.user)
    json = {}

    try:
        store = Store.objects.select_related(
            'translation_project', 'parent').get(pootle_path=pootle_path)
        if not check_profile_permission(profile, 'view', store.parent):
            json["success"] = False
            json["msg"] = _(
                "You do not have rights to access translation mode.")
        else:
            units_qs = _filter_queryset(request.GET, store.units)
            unit_rows = profile.get_unit_rows()

            try:
                if uid is None:
                    try:
                        current_unit = units_qs[0]
                        json["uid"] = units_qs[0].id
                    except IndexError:
                        current_unit = None
                else:
                    current_unit = units_qs.get(id=uid,
                                                store__pootle_path=pootle_path)
                if current_unit is not None:
                    current_index = _get_index_in_qs(units_qs, current_unit)
                    preceding = units_qs[:current_index].count()
                    page = preceding / unit_rows + 1
                    pager = paginate(request,
                                     units_qs,
                                     items=unit_rows,
                                     page=page)
                    json["pager"] = _build_pager_dict(pager)
                tp = store.translation_project
                json["meta"] = {
                    "source_lang": tp.project.source_language.code,
                    "source_dir": tp.project.source_language.get_direction(),
                    "target_lang": tp.language.code,
                    "target_dir": tp.language.get_direction()
                }
                json["success"] = True
            except Unit.DoesNotExist:
                json["success"] = False
                json["msg"] = _("Unit %(uid)s does not exist on %(path)s." % {
                    'uid': uid,
                    'path': pootle_path
                })
    except Store.DoesNotExist:
        json["success"] = False
        json["msg"] = _("Store %(path)s does not exist." %
                        {'path': pootle_path})

    response = simplejson.dumps(json)
    return HttpResponse(response, mimetype="application/json")