def do_upload(self, request, translation_project, directory): if self.form.is_valid() and 'file' in request.FILES: django_file = self.form.cleaned_data['file'] overwrite = self.form.cleaned_data['overwrite'] scan_translation_project_files(translation_project) oldstats = translation_project.getquickstats() # The URL relative to the URL of the translation project. Thus, if # directory.pootle_path == /af/pootle/foo/bar, then # relative_root_dir == foo/bar. if django_file.name.endswith('.zip'): archive = True upload_archive(request, directory, django_file, overwrite) else: archive = False upload_file(request, directory, django_file, overwrite) scan_translation_project_files(translation_project) newstats = translation_project.getquickstats() # create a submission, doesn't fix stats but at least # shows up in last activity column s = Submission(creation_time=datetime.datetime.utcnow(), translation_project=translation_project, submitter=get_profile(request.user)) s.save() post_file_upload.send(sender=translation_project, user=request.user, oldstats=oldstats, newstats=newstats, archive=archive) return {'upload': self}
def toggle_qualitycheck(self, check_id, false_positive, user): check = self.qualitycheck_set.get(id=check_id) if check.false_positive == false_positive: return check.false_positive = false_positive check.save() self._log_user = user if false_positive: self._save_action = MUTE_QUALITYCHECK else: self._save_action = UNMUTE_QUALITYCHECK # create submission if false_positive: sub_type = SubmissionTypes.MUTE_CHECK else: sub_type = SubmissionTypes.UNMUTE_CHECK sub = Submission(creation_time=make_aware(timezone.now()), translation_project=self.store.translation_project, submitter=user, field=SubmissionFields.NONE, unit=self, store=self.store, type=sub_type, quality_check=check) sub.save() # update timestamp # log user action self.save()
def submit(request, unit): """Processes translation submissions and stores them in the database. :return: An object in JSON notation that contains the previous and last units for the unit next to unit ``uid``. """ json = {} translation_project = request.translation_project language = translation_project.language if unit.hasplural(): snplurals = len(unit.source.strings) else: snplurals = None # Store current time so that it is the same for all submissions current_time = timezone.now() form_class = unit_form_factory(language, snplurals, request) form = form_class(request.POST, instance=unit, request=request) if form.is_valid(): if form.updated_fields: for field, old_value, new_value in form.updated_fields: sub = Submission( creation_time=current_time, translation_project=translation_project, submitter=request.profile, unit=unit, store=unit.store, field=field, type=SubmissionTypes.NORMAL, old_value=old_value, new_value=new_value, similarity=form.cleaned_data["similarity"], mt_similarity=form.cleaned_data["mt_similarity"], ) sub.save() # Update current unit instance's attributes # important to set these attributes after saving Submission # because we need to access the unit's state before it was saved if SubmissionFields.TARGET in (f[0] for f in form.updated_fields): form.instance.submitted_by = request.profile form.instance.submitted_on = current_time form.instance.reviewed_by = None form.instance.reviewed_on = None form.instance._log_user = request.profile form.save() json["checks"] = _get_critical_checks_snippet(request, unit) json["user_score"] = request.profile.public_score return JsonResponse(json) return JsonResponseBadRequest({"msg": _("Failed to process submission.")})
def toggle_qualitycheck(self, check_id, false_positive, user): check = self.qualitycheck_set.get(id=check_id) if check.false_positive == false_positive: return self.revision = Revision.incr() self.save( reviewed_by=user) check.false_positive = false_positive check.save() # create submission old_value = MUTED new_value = UNMUTED if false_positive: old_value = UNMUTED new_value = MUTED update_time = make_aware(timezone.now()) sub = Submission( creation_time=update_time, translation_project=self.store.translation_project, submitter=user, field=SubmissionFields.NONE, unit=self, type=SubmissionTypes.WEB, old_value=old_value, new_value=new_value, quality_check=check) sub.save()
def save(self, *args, **kwargs): changed_with = kwargs.pop("changed_with", None) kwargs["commit"] = False unit = super(UnitForm, self).save(*args, **kwargs) with update_data_after(unit.store): current_time = timezone.now() if SubmissionFields.TARGET in (f[0] for f in self.updated_fields): unit.submitted_by = self.user unit.submitted_on = current_time unit.reviewed_by = None unit.reviewed_on = None suggestion = self.cleaned_data["suggestion"] user = ( suggestion.user if suggestion else self.user) unit.save( submitted_on=current_time, submitted_by=user, changed_with=changed_with) translation_project = unit.store.translation_project for field, old_value, new_value in self.updated_fields: if field == SubmissionFields.TARGET and suggestion: old_value = str(suggestion.target_f) sub = Submission( creation_time=current_time, translation_project=translation_project, submitter=self.user, unit=unit, field=field, type=SubmissionTypes.WEB, old_value=old_value, new_value=new_value) sub.save() return unit
def submit(request, unit): """Processes translation submissions and stores them in the database. :return: An object in JSON notation that contains the previous and last units for the unit next to unit ``uid``. """ json = {} cantranslate = check_permission("translate", request) if not cantranslate: raise PermissionDenied(_("You do not have rights to access " "translation mode.")) translation_project = request.translation_project language = translation_project.language if unit.hasplural(): snplurals = len(unit.source.strings) else: snplurals = None # Update current unit instance's attributes unit.submitted_by = request.profile unit.submitted_on = datetime.utcnow() form_class = unit_form_factory(language, snplurals, request) form = form_class(request.POST, instance=unit) if form.is_valid(): if form.updated_fields: # Store creation time so that it is the same for all submissions creation_time=datetime.utcnow() for field, old_value, new_value in form.updated_fields: sub = Submission( creation_time=creation_time, translation_project=translation_project, submitter=request.profile, unit=unit, field=field, type=SubmissionTypes.NORMAL, old_value=old_value, new_value=new_value, ) sub.save() form.save() translation_submitted.send( sender=translation_project, unit=form.instance, profile=request.profile, ) rcode = 200 else: # Form failed #FIXME: we should display validation errors here rcode = 400 json["msg"] = _("Failed to process submission.") response = jsonify(json) return HttpResponse(response, status=rcode, mimetype="application/json")
def accept_suggestion(request, unit, suggid): json = { 'udbid': unit.id, 'sugid': suggid, } translation_project = request.translation_project if request.POST.get('accept'): try: suggestion = unit.suggestion_set.get(id=suggid) except ObjectDoesNotExist: raise Http404 old_target = unit.target success = unit.accept_suggestion(suggid) json['newtargets'] = [highlight_whitespace(target) for target in unit.target.strings] json['newdiffs'] = {} for sugg in unit.get_suggestions(): json['newdiffs'][sugg.id] = \ [highlight_diffs(unit.target.strings[i], target) for i, target in enumerate(sugg.target.strings)] if suggestion is not None and success: if suggestion.user: translation_submitted.send(sender=translation_project, unit=unit, profile=suggestion.user) # FIXME: we need a totally different model for tracking stats, this # is just lame suggstat, created = SuggestionStat.objects.get_or_create( translation_project=translation_project, suggester=suggestion.user, state='pending', unit=unit.id, ) suggstat.reviewer = request.profile suggstat.state = 'accepted' suggstat.save() # For now assume the target changed # TODO: check all fields for changes creation_time = timezone.now() sub = Submission( creation_time=creation_time, translation_project=translation_project, submitter=suggestion.user, from_suggestion=suggstat, unit=unit, field=SubmissionFields.TARGET, type=SubmissionTypes.SUGG_ACCEPT, old_value=old_target, new_value=unit.target, ) sub.save() response = jsonify(json) return HttpResponse(response, mimetype="application/json")
def process_submit(request, unit, type): """ Processes submissions and suggestions and stores them in the database. @return: An object in JSON notation that contains the previous and last units for the unit next to unit C{uid}. """ json = {} cantranslate = check_permission("translate", request) cansuggest = check_permission("suggest", request) if type == "submission" and not cantranslate or type == "suggestion" and not cansuggest: raise PermissionDenied(_("You do not have rights to access translation mode.")) translation_project = request.translation_project language = translation_project.language if unit.hasplural(): snplurals = len(unit.source.strings) else: snplurals = None form_class = unit_form_factory(language, snplurals, request) 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() translation_submitted.send(sender=translation_project, unit=form.instance, profile=request.profile) sub = Submission(translation_project=translation_project, submitter=request.profile) 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"], request.profile) if sugg: SuggestionStat.objects.get_or_create( translation_project=translation_project, suggester=request.profile, state="pending", unit=unit.id, ) rcode = 200 else: # Form failed # FIXME: we should display validation errors here rcode = 400 json["msg"] = _("Failed to process submit.") response = jsonify(json) return HttpResponse(response, status=rcode, mimetype="application/json")
def _handle_upload_form(request, translation_project): """Process the upload form in TP overview.""" from pootle_app.signals import post_file_upload upload_form_class = upload_form_factory(request) if request.method == 'POST' and 'file' in request.FILES: upload_form = upload_form_class(request.POST, request.FILES) if not upload_form.is_valid(): return upload_form else: django_file = upload_form.cleaned_data['file'] overwrite = upload_form.cleaned_data['overwrite'] upload_to = upload_form.cleaned_data['upload_to'] upload_to_dir = upload_form.cleaned_data['upload_to_dir'] # XXX Why do we scan here? translation_project.scan_files(vcs_sync=False) oldstats = translation_project.get_stats() # The URL relative to the URL of the translation project. Thus, if # directory.pootle_path == /af/pootle/foo/bar, then # relative_root_dir == foo/bar. if django_file.name.endswith('.zip'): archive = True target_directory = upload_to_dir or request.directory upload_archive(request, target_directory, django_file, overwrite) else: archive = False upload_file(request, request.directory, django_file, overwrite, store=upload_to) translation_project.scan_files(vcs_sync=False) newstats = translation_project.get_stats() # Create a submission. Doesn't fix stats but at least shows up in # last activity column. from django.utils import timezone s = Submission( creation_time=timezone.now(), translation_project=translation_project, submitter=request.user, type=SubmissionTypes.UPLOAD, # The other fields are only relevant to unit-based changes. ) s.save() post_file_upload.send(sender=translation_project, user=request.user, oldstats=oldstats, newstats=newstats, archive=archive) # Always return a blank upload form unless the upload form is not valid. return upload_form_class()
def _create_comment_submission(unit, user, creation_time, comment): sub = Submission( creation_time=creation_time, translation_project=unit.store.translation_project, submitter=user, unit=unit, field=SubmissionFields.COMMENT, type=SubmissionTypes.WEB, new_value=comment, ) sub.save() return sub
def accept_suggestion(request, uid, suggid): unit = get_object_or_404(Unit, id=uid) directory = unit.store.parent translation_project = unit.store.translation_project if not check_profile_permission( get_profile(request.user), 'review', directory): raise PermissionDenied response = { 'udbid': unit.id, 'sugid': suggid, } if request.POST.get('accept'): try: suggestion = unit.suggestion_set.get(id=suggid) except ObjectDoesNotExist: suggestion = None response['success'] = unit.accept_suggestion(suggid) response['newtargets'] = [ highlight_whitespace(target) for target in unit.target.strings] response['newdiffs'] = {} for sugg in unit.get_suggestions(): response['newdiffs'][sugg.id] = [ highlight_diffs(unit.target.strings[i], target) \ for i, target in enumerate(sugg.target.strings)] if suggestion is not None and response['success']: if suggestion.user: translation_submitted.send( sender=translation_project, unit=unit, profile=suggestion.user) # FIXME: we need a totally different model for tracking # stats, this is just lame suggstat, created = SuggestionStat.objects.get_or_create( translation_project=translation_project, suggester=suggestion.user, state='pending', unit=unit.id) suggstat.reviewer = get_profile(request.user) suggstat.state = 'accepted' suggstat.save() sub = Submission(translation_project=translation_project, submitter=get_profile(request.user), from_suggestion=suggstat) sub.save() response = simplejson.dumps(response) return HttpResponse(response, mimetype="application/json")
def accept_suggestion(request, uid, suggid): json = {} try: unit = Unit.objects.get(id=uid) directory = unit.store.parent translation_project = unit.store.translation_project profile = get_profile(request.user) if not check_profile_permission(profile, 'review', directory): json["success"] = False json["msg"] = _("You do not have rights to access review mode.") else: json["udbid"] = unit.id json["sugid"] = suggid if request.POST.get('accept'): try: sugg = unit.suggestion_set.get(id=suggid) except ObjectDoesNotExist: sugg = None json['success'] = unit.accept_suggestion(suggid) json['newtargets'] = [highlight_whitespace(target) for target in unit.target.strings] json['newdiffs'] = {} for sugg in unit.get_suggestions(): json['newdiffs'][sugg.id] = [highlight_diffs(unit.target.strings[i], target) \ for i, target in enumerate(sugg.target.strings)] if sugg is not None and json['success']: #FIXME: we need a totally different model for tracking stats, this is just lame suggstat, created = SuggestionStat.objects.get_or_create(translation_project=translation_project, suggester=sugg.user, state='pending', unit=unit.id) suggstat.reviewer = profile suggstat.state = 'accepted' suggstat.save() sub = Submission(translation_project=translation_project, submitter=profile, from_suggestion=suggstat) sub.save() except Unit.DoesNotExist: json["success"] = False json["msg"] = _("Unit %(uid)s does not exist." % {'uid': uid}) response = simplejson.dumps(json) return HttpResponse(response, mimetype="application/json")
def _create_comment_on_unit(unit, user, comment): from pootle_statistics.models import (Submission, SubmissionFields, SubmissionTypes) unit.translator_comment = comment unit.save(user=user) sub = Submission( creation_time=unit.change.commented_on, translation_project=unit.store.translation_project, submitter=user, unit=unit, field=SubmissionFields.COMMENT, type=SubmissionTypes.WEB, new_value=comment, ) sub.save()
def _mark_unit_fuzzy(unit, user): from pootle_store.constants import FUZZY from pootle_statistics.models import (Submission, SubmissionFields, SubmissionTypes) unit.markfuzzy() unit.save() sub = Submission( creation_time=unit.mtime, translation_project=unit.store.translation_project, submitter=user, unit=unit, field=SubmissionFields.STATE, type=SubmissionTypes.WEB, old_value=unit.state, new_value=FUZZY, ) sub.save()
def GET(self, template_vars, request, translation_project, directory, store=None): can_edit = check_permission('administrate', request) project = translation_project.project language = translation_project.language path_obj = store or directory path_stats = get_raw_stats(path_obj, include_suggestions=True) path_summary = get_path_summary(path_obj, path_stats) actions = action_groups(request, path_obj, path_stats=path_stats) template_vars.update({ 'translation_project': translation_project, 'project': project, 'language': language, 'directory': directory, 'path_summary': path_summary, 'stats': path_stats, 'topstats': gentopstats_translation_project(translation_project), 'feed_path': directory.pootle_path[1:], 'action_groups': actions, 'can_edit': can_edit, }) if store is not None: template_vars.update({ 'store': store }) else: table_fields = ['name', 'progress', 'total', 'need-translation', 'suggestions'] template_vars.update({ 'table': { 'id': 'tp', 'proportional': True, 'fields': table_fields, 'headings': get_table_headings(table_fields), 'items': get_children(translation_project, directory), } }) # If current directory is the TP root directory. if not directory.path: template_vars.update({ 'latest_action': translation_project.get_latest_submission() }) else: template_vars.update({ 'latest_action': Submission.get_latest_for_dir(path_obj) }) if can_edit: from pootle_translationproject.forms import DescriptionForm template_vars['form'] = DescriptionForm(instance=translation_project) return template_vars
def save(self, **kwargs): """Register the submission and save the comment.""" if self.has_changed(): creation_time = timezone.now() translation_project = self.request.translation_project sub = Submission( creation_time=creation_time, translation_project=translation_project, submitter=self.request.user, unit=self.instance, field=SubmissionFields.COMMENT, type=SubmissionTypes.WEB, old_value=self.previous_value, new_value=self.cleaned_data['translator_comment'] ) sub.save() super(UnitCommentForm, self).save(**kwargs)
def do_upload(self, request, translation_project, directory, store): if self.form.is_valid() and 'file' in request.FILES: django_file = self.form.cleaned_data['file'] overwrite = self.form.cleaned_data['overwrite'] upload_to = self.form.cleaned_data['upload_to'] upload_to_dir = self.form.cleaned_data['upload_to_dir'] # XXX Why do we scan here? translation_project.scan_files(vcs_sync=False) oldstats = translation_project.getquickstats() # The URL relative to the URL of the translation project. Thus, if # directory.pootle_path == /af/pootle/foo/bar, then # relative_root_dir == foo/bar. if django_file.name.endswith('.zip'): archive = True target_directory = upload_to_dir or directory upload_archive(request, target_directory, django_file, overwrite) else: archive = False upload_file(request, directory, django_file, overwrite, store=upload_to) translation_project.scan_files(vcs_sync=False) newstats = translation_project.getquickstats() # create a submission, doesn't fix stats but at least # shows up in last activity column from django.utils import timezone s = Submission( creation_time=timezone.now(), translation_project=translation_project, submitter=get_profile(request.user), type=SubmissionTypes.UPLOAD, # the other fields are only relevant to unit-based changes ) s.save() post_file_upload.send( sender=translation_project, user=request.user, oldstats=oldstats, newstats=newstats, archive=archive) return {'upload': self}
def save_unit(self): user = self.request_user current_time = make_aware(timezone.now()) updated = [] target = multistring(self.cleaned_data["target_f"] or [u'']) if target != self.unit.target: self.unit.submitted_by = user self.unit.submitted_on = current_time self.unit.reviewed_by = None self.unit.reviewed_on = None updated.append( (SubmissionFields.TARGET, self.unit.target_f, self.cleaned_data["target_f"])) self.unit.target = self.cleaned_data["target_f"] if self.unit.target: if self.cleaned_data["is_fuzzy"]: self.unit.state = FUZZY else: self.unit.state = TRANSLATED else: self.unit.state = UNTRANSLATED self.unit.save( submitted_on=current_time, submitted_by=user, changed_with=SubmissionTypes.WEB) if self.unit.state_updated: updated.append( (SubmissionFields.STATE, self.unit._frozen.state, self.unit.state)) translation_project = self.unit.store.translation_project for field, old_value, new_value in updated: sub = Submission( creation_time=current_time, translation_project=translation_project, submitter=user, unit=self.unit, field=field, type=SubmissionTypes.WEB, old_value=old_value, new_value=new_value) sub.save()
def _mark_unit_fuzzy(unit, user): from pootle_store.util import FUZZY from pootle_statistics.models import (Submission, SubmissionFields, SubmissionTypes) sub = Submission( creation_time=unit.commented_on, translation_project=unit.store.translation_project, submitter=user, unit=unit, store=unit.store, field=SubmissionFields.STATE, type=SubmissionTypes.NORMAL, old_value=unit.state, new_value=FUZZY, ) sub.save() unit.markfuzzy() unit._state_updated = True unit.save()
def save(self): """Registers the submission and saves the comment.""" if self.has_changed(): creation_time = timezone.now() translation_project = self.request.translation_project sub = Submission( creation_time=creation_time, translation_project=translation_project, submitter=self.request.profile, unit=self.instance, field=SubmissionFields.COMMENT, type=SubmissionTypes.NORMAL, old_value=u"", new_value=self.cleaned_data['translator_comment'] ) sub.save() super(UnitCommentForm, self).save()
def _create_comment_on_unit(unit, user, comment): from pootle_statistics.models import Submission, SubmissionFields, SubmissionTypes unit.translator_comment = comment unit.commented_on = timezone.now() unit.commented_by = user sub = Submission( creation_time=unit.commented_on, translation_project=unit.store.translation_project, submitter=user, unit=unit, store=unit.store, field=SubmissionFields.COMMENT, type=SubmissionTypes.NORMAL, new_value=comment, ) sub.save() unit._comment_updated = True unit.save()
def create_submission(self, suggestion, suggestion_type, user, **kwargs): return Submission( creation_time=kwargs.get("creation_time", suggestion.creation_time), translation_project=suggestion.unit.store.translation_project, submitter=user, unit=suggestion.unit, store=suggestion.unit.store, type=suggestion_type, suggestion=suggestion)
def accept_suggestion(request, unit, suggid): json = {} translation_project = request.translation_project json["udbid"] = unit.id json["sugid"] = suggid if request.POST.get('accept'): try: suggestion = unit.suggestion_set.get(id=suggid) except ObjectDoesNotExist: raise Http404 success = unit.accept_suggestion(suggid) json['newtargets'] = [ highlight_whitespace(target) for target in unit.target.strings ] json['newdiffs'] = {} for sugg in unit.get_suggestions(): json['newdiffs'][sugg.id] = [highlight_diffs(unit.target.strings[i], target) \ for i, target in enumerate(sugg.target.strings)] if suggestion is not None and success: if suggestion.user: translation_submitted.send(sender=translation_project, unit=unit, profile=suggestion.user) #FIXME: we need a totally different model for tracking stats, this is just lame if suggestion.user != request.profile: suggstat, created = SuggestionStat.objects.get_or_create( translation_project=translation_project, suggester=suggestion.user, state='pending', unit=unit.id) suggstat.reviewer = request.profile suggstat.state = 'accepted' suggstat.save() else: suggstat = None sub = Submission(translation_project=translation_project, submitter=suggestion.user, from_suggestion=suggstat) sub.save() response = jsonify(json) return HttpResponse(response, mimetype="application/json")
def accept_suggestion(self, suggestion): unit = suggestion.unit translation_project = unit.store.translation_project # Save for later old_state = unit.state old_target = unit.target # Update some basic attributes so we can create submissions. Note # these do not conflict with `ScoreLog`'s interests, so it's safe unit.target = suggestion.target if unit.state == FUZZY: unit.state = TRANSLATED current_time = timezone.now() suggestion.state = SuggestionStates.ACCEPTED suggestion.reviewer = self.reviewer suggestion.review_time = current_time suggestion.save() create_subs = OrderedDict() if old_state != unit.state: create_subs[SubmissionFields.STATE] = [old_state, unit.state] create_subs[SubmissionFields.TARGET] = [old_target, unit.target] subs_created = [] for field in create_subs: kwargs = { 'creation_time': current_time, 'translation_project': translation_project, 'submitter': self.reviewer, 'unit': unit, 'store': unit.store, 'field': field, 'type': SubmissionTypes.SUGG_ACCEPT, 'old_value': create_subs[field][0], 'new_value': create_subs[field][1], } if field == SubmissionFields.TARGET: kwargs['suggestion'] = suggestion subs_created.append(Submission(**kwargs)) if subs_created: unit.submission_set.add(*subs_created, bulk=False) # FIXME: remove such a dependency on `ScoreLog` # Update current unit instance's attributes # important to set these attributes after saving Submission # because in the `ScoreLog` we need to access the unit's certain # attributes before it was saved # THIS NEEDS TO GO ^^ unit.submitted_by = suggestion.user unit.submitted_on = current_time unit.reviewed_by = self.reviewer unit.reviewed_on = unit.submitted_on unit._log_user = self.reviewer unit.save()
def save(self, **kwargs): """Register the submission and save the comment.""" if self.has_changed(): self.instance._comment_updated = True creation_time = timezone.now() translation_project = self.request.translation_project sub = Submission( creation_time=creation_time, translation_project=translation_project, submitter=self.request.user, unit=self.instance, store=self.instance.store, field=SubmissionFields.COMMENT, type=SubmissionTypes.NORMAL, old_value=self.previous_value, new_value=self.cleaned_data['translator_comment']) sub.save() super(UnitCommentForm, self).save(**kwargs)
def _create_comment_on_unit(unit, user, comment): from pootle_statistics.models import (Submission, SubmissionFields, SubmissionTypes) unit.translator_comment = comment unit.commented_on = timezone.now() unit.commented_by = user sub = Submission( creation_time=unit.commented_on, translation_project=unit.store.translation_project, submitter=user, unit=unit, store=unit.store, field=SubmissionFields.COMMENT, type=SubmissionTypes.NORMAL, new_value=comment, ) sub.save() unit._comment_updated = True unit.save()
def save(self, **kwargs): """Register the submission and save the comment.""" if self.has_changed(): self.instance._comment_updated = True creation_time = timezone.now() translation_project = self.request.translation_project sub = Submission( creation_time=creation_time, translation_project=translation_project, submitter=self.request.profile, unit=self.instance, store=self.instance.store, field=SubmissionFields.COMMENT, type=SubmissionTypes.NORMAL, old_value=self.previous_value, new_value=self.cleaned_data["translator_comment"], ) sub.save() super(UnitCommentForm, self).save(**kwargs)
def do_upload(self, request, translation_project, directory): if self.form.is_valid() and 'file' in request.FILES: django_file = self.form.cleaned_data['file'] overwrite = self.form.cleaned_data['overwrite'] upload_to = self.form.cleaned_data['upload_to'] upload_to_dir = self.form.cleaned_data['upload_to_dir'] translation_project.scan_files() oldstats = translation_project.getquickstats() # The URL relative to the URL of the translation project. Thus, if # directory.pootle_path == /af/pootle/foo/bar, then # relative_root_dir == foo/bar. if django_file.name.endswith('.zip'): archive = True target_directory = upload_to_dir or directory upload_archive(request, target_directory, django_file, overwrite) else: archive = False upload_file(request, directory, django_file, overwrite, store=upload_to) translation_project.scan_files() newstats = translation_project.getquickstats() # create a submission, doesn't fix stats but at least # shows up in last activity column s = Submission(creation_time=datetime.datetime.utcnow(), translation_project=translation_project, submitter=get_profile(request.user)) s.save() post_file_upload.send(sender=translation_project, user=request.user, oldstats=oldstats, newstats=newstats, archive=archive) return {'upload': self}
def save_unit(self): current_time = make_aware(timezone.now()) updated = [] if self.cleaned_data["target_f"]: self.unit.target = self.cleaned_data["target_f"] self.unit.save( submitted_on=current_time, submitted_by=self.target_object.user, reviewed_on=current_time, reviewed_by=self.request_user, changed_with=SubmissionTypes.WEB) updated.append( (SubmissionFields.TARGET, self.unit._frozen.target, self.unit.target)) if self.unit.state_updated: updated.append( (SubmissionFields.STATE, self.unit._frozen.state, self.unit.state)) translation_project = self.unit.store.translation_project for field, old_value, new_value in updated: sub = Submission( creation_time=current_time, translation_project=translation_project, suggestion=self.target_object, submitter=self.target_object.user, unit=self.unit, field=field, type=SubmissionTypes.WEB, old_value=old_value, new_value=new_value) sub.save() self.suggestion_review.accept( update_unit=( False if self.cleaned_data["target_f"] else True))
def accept_suggestion(request, unit, suggid): json = {} translation_project = request.translation_project json["udbid"] = unit.id json["sugid"] = suggid if request.POST.get('accept'): try: suggestion = unit.suggestion_set.get(id=suggid) except ObjectDoesNotExist: raise Http404 success = unit.accept_suggestion(suggid) json['newtargets'] = [highlight_whitespace(target) for target in unit.target.strings] json['newdiffs'] = {} for sugg in unit.get_suggestions(): json['newdiffs'][sugg.id] = [highlight_diffs(unit.target.strings[i], target) \ for i, target in enumerate(sugg.target.strings)] if suggestion is not None and success: if suggestion.user: translation_submitted.send(sender=translation_project, unit=unit, profile=suggestion.user) #FIXME: we need a totally different model for tracking stats, this is just lame if suggestion.user != request.profile: suggstat, created = SuggestionStat.objects.get_or_create(translation_project=translation_project, suggester=suggestion.user, state='pending', unit=unit.id) suggstat.reviewer = request.profile suggstat.state = 'accepted' suggstat.save() else: suggstat = None sub = Submission(translation_project=translation_project, submitter=suggestion.user, from_suggestion=suggstat) sub.save() response = jsonify(json) return HttpResponse(response, mimetype="application/json")
def record_submissions(self, unit, old_target, old_state, current_time, user, submission_type=None, **kwargs): """Records all applicable submissions for `unit`. EXTREME HAZARD: this relies on implicit `._<field>_updated` members being available in `unit`. Let's look into replacing such members with something saner (#3895). """ state_updated = kwargs.get("state_updated") or unit._state_updated target_updated = kwargs.get("target_updated") or unit._target_updated comment_updated = kwargs.get( "comment_updated") or unit._comment_updated create_subs = OrderedDict() if state_updated: create_subs[SubmissionFields.STATE] = [old_state, unit.state] if target_updated: create_subs[SubmissionFields.TARGET] = [old_target, unit.target_f] if comment_updated: create_subs[SubmissionFields.COMMENT] = [ '', unit.translator_comment or '' ] if submission_type is None: submission_type = SubmissionTypes.SYSTEM subs_created = [] for field in create_subs: subs_created.append( Submission(creation_time=current_time, translation_project_id=self.translation_project_id, submitter=user, unit=unit, store_id=self.id, field=field, type=submission_type, old_value=create_subs[field][0], new_value=create_subs[field][1])) if subs_created: unit.submission_set.add(*subs_created, bulk=False)
def record_submissions(self, unit, old_target, old_state, current_time, user, submission_type=None, **kwargs): """Records all applicable submissions for `unit`. """ state_updated = kwargs.get("state_updated") target_updated = kwargs.get("target_updated") comment_updated = kwargs.get("comment_updated") create_subs = OrderedDict() if state_updated: create_subs[SubmissionFields.STATE] = [old_state, unit.state] if target_updated: create_subs[SubmissionFields.TARGET] = [old_target, unit.target_f] if comment_updated: create_subs[SubmissionFields.COMMENT] = [ '', unit.translator_comment or '' ] if submission_type is None: submission_type = SubmissionTypes.SYSTEM subs_created = [] for field in create_subs: subs_created.append( Submission(creation_time=current_time, translation_project_id=self.translation_project_id, submitter=user, unit=unit, revision=unit.revision, store_id=self.id, field=field, type=submission_type, old_value=create_subs[field][0], new_value=create_subs[field][1])) if subs_created: unit.submission_set.add(*subs_created, bulk=False)
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))
def submit(request, unit): """Processes translation submissions and stores them in the database. :return: An object in JSON notation that contains the previous and last units for the unit next to unit ``uid``. """ json = {} translation_project = request.translation_project language = translation_project.language if unit.hasplural(): snplurals = len(unit.source.strings) else: snplurals = None # Store current time so that it is the same for all submissions current_time = timezone.now() form_class = unit_form_factory(language, snplurals, request) form = form_class(request.POST, instance=unit, request=request) if form.is_valid(): if form.updated_fields: for field, old_value, new_value in form.updated_fields: sub = Submission( creation_time=current_time, translation_project=translation_project, submitter=request.profile, unit=unit, store=unit.store, field=field, type=SubmissionTypes.NORMAL, old_value=old_value, new_value=new_value, similarity=form.cleaned_data['similarity'], mt_similarity=form.cleaned_data['mt_similarity'], ) sub.save() # Update current unit instance's attributes # important to set these attributes after saving Submission # because we need to access the unit's state before it was saved if SubmissionFields.TARGET in \ map(lambda x: x[0], form.updated_fields): form.instance.submitted_by = request.profile form.instance.submitted_on = current_time form.instance.reviewed_by = None form.instance.reviewed_on = None form.instance._log_user = request.profile form.save() translation_submitted.send( sender=translation_project, unit=form.instance, profile=request.profile, ) has_critical_checks = unit.qualitycheck_set.filter( category=Category.CRITICAL).exists() if has_critical_checks: can_review = check_user_permission(request.profile, 'review', unit.store.parent) ctx = {'canreview': can_review, 'unit': unit} template = loader.get_template('editor/units/xhr_checks.html') context = RequestContext(request, ctx) json['checks'] = template.render(context) rcode = 200 json['user_score'] = request.profile.public_score else: # Form failed #FIXME: we should display validation errors here rcode = 400 json["msg"] = _("Failed to process submission.") response = jsonify(json) return HttpResponse(response, status=rcode, content_type="application/json")
def process_submit(request, unit, type): """Processes submissions and suggestions and stores them in the database. :return: An object in JSON notation that contains the previous and last units for the unit next to unit ``uid``. """ json = {} cantranslate = check_permission("translate", request) cansuggest = check_permission("suggest", request) if type == 'submission' and not cantranslate or type == 'suggestion' and not cansuggest: raise PermissionDenied(_("You do not have rights to access translation mode.")) translation_project = request.translation_project language = translation_project.language if unit.hasplural(): snplurals = len(unit.source.strings) else: snplurals = None import copy old_unit = copy.copy(unit) form_class = unit_form_factory(language, snplurals, request) form = form_class(request.POST, instance=unit) if form.is_valid(): if type == 'submission' and form.updated_fields: # Store creation time so that it is the same for all submissions: creation_time=datetime.utcnow() for field, old_value, new_value in form.updated_fields: sub = Submission( creation_time=creation_time, translation_project=translation_project, submitter=request.profile, unit=unit, field=field, type=NORMAL, old_value=old_value, new_value=new_value, ) sub.save() form.save() translation_submitted.send( sender=translation_project, unit=form.instance, profile=request.profile, ) 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'], request.profile) if sugg: SuggestionStat.objects.get_or_create(translation_project=translation_project, suggester=request.profile, state='pending', unit=unit.id) rcode = 200 else: # Form failed #FIXME: we should display validation errors here rcode = 400 json["msg"] = _("Failed to process submit.") response = jsonify(json) return HttpResponse(response, status=rcode, mimetype="application/json")
def overview(request, translation_project, dir_path, filename=None): current_path = translation_project.directory.pootle_path + dir_path if filename: current_path = current_path + filename store = get_object_or_404(Store, pootle_path=current_path) directory = store.parent template_vars = { 'store_tags': store.tags.all().order_by('name'), } template = "translation_project/store_overview.html" else: store = None directory = get_object_or_404(Directory, pootle_path=current_path) template_vars = { 'tp_tags': translation_project.tags.all().order_by('name'), } template = "translation_project/overview.html" if (check_permission('translate', request) or check_permission('suggest', request) or check_permission('overwrite', request)): template_vars.update({ 'upload_form': _handle_upload_form(request, current_path, translation_project, directory), }) can_edit = check_permission('administrate', request) project = translation_project.project language = translation_project.language path_obj = store or directory latest_action = '' # If current directory is the TP root directory. if not directory.path: latest_action = translation_project.get_latest_submission() elif store is None: # If this is not a file. latest_action = Submission.get_latest_for_dir(path_obj) path_stats = get_raw_stats(path_obj, include_suggestions=True) path_summary = get_path_summary(path_obj, path_stats, latest_action) actions = action_groups(request, path_obj, path_stats=path_stats) action_output = '' running = request.GET.get(EXTDIR, '') if running: if store: act = StoreAction else: act = TranslationProjectAction try: action = act.lookup(running) except KeyError: messages.error(request, _("Unable to find %s %s") % (act, running)) else: if not getattr(action, 'nosync', False): (store or translation_project).sync() if action.is_active(request): vcs_dir = settings.VCS_DIRECTORY po_dir = settings.PODIRECTORY tp_dir = directory.get_real_path() store_fn = '*' if store: tp_dir_slash = add_trailing_slash(tp_dir) if store.file.name.startswith(tp_dir_slash): # Note: store_f used below in reverse() call. store_f = store.file.name[len(tp_dir_slash):] store_fn = store_f.replace('/', os.sep) # Clear possibly stale output/error (even from other path_obj). action.set_output('') action.set_error('') try: action.run(path=path_obj, root=po_dir, tpdir=tp_dir, project=project.code, language=language.code, store=store_fn, style=translation_project.file_style, vc_root=vcs_dir) except StandardError: err = (_("Exception while running '%s' extension action") % action.title) logging.exception(err) if (action.error): messages.error(request, action.error) else: messages.error(request, err) else: if (action.error): messages.warning(request, action.error) action_output = action.output if getattr(action, 'get_download', None): export_path = action.get_download(path_obj) if export_path: response = HttpResponse('/export/' + export_path) response['Content-Disposition'] = ( 'attachment; filename="%s"' % os.path.basename(export_path)) return response if not action_output: if not store: rev_args = [language.code, project.code, ''] overview_url = reverse('tp.overview', args=rev_args) else: slash = store_f.rfind('/') store_d = '' if slash > 0: store_d = store_f[:slash] store_f = store_f[slash + 1:] elif slash == 0: store_f = store_f[1:] rev_args = [ language.code, project.code, store_d, store_f ] overview_url = reverse('tp.overview', args=rev_args) return HttpResponseRedirect(overview_url) template_vars.update({ 'translation_project': translation_project, 'project': project, 'language': language, 'path_obj': path_obj, 'resource_path': request.resource_path, 'path_summary': path_summary, 'stats': path_stats, 'topstats': gentopstats_translation_project(translation_project), 'feed_path': directory.pootle_path[1:], 'action_groups': actions, 'action_output': action_output, 'can_edit': can_edit, }) if store is None: table_fields = [ 'name', 'progress', 'total', 'need-translation', 'suggestions' ] template_vars.update({ 'table': { 'id': 'tp', 'proportional': True, 'fields': table_fields, 'headings': get_table_headings(table_fields), 'items': get_children(translation_project, directory), } }) if can_edit: if store is None: url_kwargs = { 'language_code': language.code, 'project_code': project.code, } add_tag_action_url = reverse('tp.ajax_add_tag', kwargs=url_kwargs) else: add_tag_action_url = reverse('pootle-store-ajax-add-tag', args=[path_obj.pk]) template_vars.update({ 'form': DescriptionForm(instance=translation_project), 'add_tag_form': TagForm(), 'add_tag_action_url': add_tag_action_url, }) return render_to_response(template, template_vars, context_instance=RequestContext(request))
def overview(request, translation_project, dir_path, filename=None): current_path = translation_project.directory.pootle_path + dir_path if filename: current_path = current_path + filename store = get_object_or_404(Store, pootle_path=current_path) directory = store.parent template_vars = { 'store_tags': store.tags.all().order_by('name'), } template = "translation_project/store_overview.html" else: store = None directory = get_object_or_404(Directory, pootle_path=current_path) template_vars = { 'tp_tags': translation_project.tags.all().order_by('name'), } template = "translation_project/overview.html" if (check_permission('translate', request) or check_permission('suggest', request) or check_permission('overwrite', request)): template_vars.update({ 'upload_form': _handle_upload_form(request, current_path, translation_project, directory), }) can_edit = check_permission('administrate', request) project = translation_project.project language = translation_project.language path_obj = store or directory latest_action = '' # If current directory is the TP root directory. if not directory.path: latest_action = translation_project.get_latest_submission() elif store is None: # If this is not a file. latest_action = Submission.get_latest_for_dir(path_obj) path_stats = get_raw_stats(path_obj, include_suggestions=True) path_summary = get_path_summary(path_obj, path_stats, latest_action) actions = action_groups(request, path_obj, path_stats=path_stats) action_output = '' running = request.GET.get(EXTDIR, '') if running: if store: act = StoreAction else: act = TranslationProjectAction try: action = act.lookup(running) except KeyError: messages.error(request, _("Unable to find %s %s") % (act, running)) else: if not getattr(action, 'nosync', False): (store or translation_project).sync() if action.is_active(request): vcs_dir = settings.VCS_DIRECTORY po_dir = settings.PODIRECTORY tp_dir = directory.get_real_path() store_fn = '*' if store: tp_dir_slash = add_trailing_slash(tp_dir) if store.file.name.startswith(tp_dir_slash): # Note: store_f used below in reverse() call. store_f = store.file.name[len(tp_dir_slash):] store_fn = store_f.replace('/', os.sep) # Clear possibly stale output/error (even from other path_obj). action.set_output('') action.set_error('') try: action.run(path=path_obj, root=po_dir, tpdir=tp_dir, project=project.code, language=language.code, store=store_fn, style=translation_project.file_style, vc_root=vcs_dir) except StandardError: err = (_("Exception while running '%s' extension action") % action.title) logging.exception(err) if (action.error): messages.error(request, action.error) else: messages.error(request, err) else: if (action.error): messages.warning(request, action.error) action_output = action.output if getattr(action, 'get_download', None): export_path = action.get_download(path_obj) if export_path: response = HttpResponse('/export/' + export_path) response['Content-Disposition'] = ( 'attachment; filename="%s"' % os.path.basename(export_path)) return response if not action_output: if not store: rev_args = [language.code, project.code, ''] overview_url = reverse('tp.overview', args=rev_args) else: slash = store_f.rfind('/') store_d = '' if slash > 0: store_d = store_f[:slash] store_f = store_f[slash + 1:] elif slash == 0: store_f = store_f[1:] rev_args = [language.code, project.code, store_d, store_f] overview_url = reverse('tp.overview', args=rev_args) return HttpResponseRedirect(overview_url) template_vars.update({ 'translation_project': translation_project, 'project': project, 'language': language, 'path_obj': path_obj, 'resource_path': request.resource_path, 'path_summary': path_summary, 'stats': path_stats, 'topstats': gentopstats_translation_project(translation_project), 'feed_path': directory.pootle_path[1:], 'action_groups': actions, 'action_output': action_output, 'can_edit': can_edit, }) if store is None: table_fields = ['name', 'progress', 'total', 'need-translation', 'suggestions'] template_vars.update({ 'table': { 'id': 'tp', 'proportional': True, 'fields': table_fields, 'headings': get_table_headings(table_fields), 'items': get_children(translation_project, directory), } }) if can_edit: if store is None: url_kwargs = { 'language_code': language.code, 'project_code': project.code, } add_tag_action_url = reverse('tp.ajax_add_tag', kwargs=url_kwargs) else: add_tag_action_url = reverse('pootle-store-ajax-add-tag', args=[path_obj.pk]) template_vars.update({ 'form': DescriptionForm(instance=translation_project), 'add_tag_form': TagForm(), 'add_tag_action_url': add_tag_action_url, }) return render_to_response(template, template_vars, context_instance=RequestContext(request))
def accept_suggestion(request, unit, suggid): json = { 'udbid': unit.id, 'sugid': suggid, } translation_project = request.translation_project if request.POST.get('accept'): try: suggestion = unit.suggestion_set.get(id=suggid) except ObjectDoesNotExist: raise Http404 old_target = unit.target success = unit.accept_suggestion(suggid) json['newtargets'] = [ highlight_whitespace(target) for target in unit.target.strings ] json['newdiffs'] = {} for sugg in unit.get_suggestions(): json['newdiffs'][sugg.id] = \ [highlight_diffs(unit.target.strings[i], target) for i, target in enumerate(sugg.target.strings)] if suggestion is not None and success: if suggestion.user: translation_submitted.send(sender=translation_project, unit=unit, profile=suggestion.user) # FIXME: we need a totally different model for tracking stats, this # is just lame suggstat, created = SuggestionStat.objects.get_or_create( translation_project=translation_project, suggester=suggestion.user, state='pending', unit=unit.id, ) suggstat.reviewer = request.profile suggstat.state = 'accepted' suggstat.save() # For now assume the target changed # TODO: check all fields for changes creation_time = timezone.now() sub = Submission( creation_time=creation_time, translation_project=translation_project, submitter=suggestion.user, from_suggestion=suggstat, unit=unit, field=SubmissionFields.TARGET, type=SubmissionTypes.SUGG_ACCEPT, old_value=old_target, new_value=unit.target, ) sub.save() response = jsonify(json) return HttpResponse(response, mimetype="application/json")
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")
def submit(request, unit): """Processes translation submissions and stores them in the database. :return: An object in JSON notation that contains the previous and last units for the unit next to unit ``uid``. """ json = {} cantranslate = check_permission("translate", request) if not cantranslate: raise PermissionDenied(_("You do not have rights to access " "translation mode.")) translation_project = request.translation_project language = translation_project.language if unit.hasplural(): snplurals = len(unit.source.strings) else: snplurals = None # Store current time so that it is the same for all submissions current_time = timezone.now() # Update current unit instance's attributes unit.submitted_by = request.profile unit.submitted_on = current_time form_class = unit_form_factory(language, snplurals, request) form = form_class(request.POST, instance=unit) if form.is_valid(): if form.updated_fields: for field, old_value, new_value in form.updated_fields: sub = Submission( creation_time=current_time, translation_project=translation_project, submitter=request.profile, unit=unit, field=field, type=SubmissionTypes.NORMAL, old_value=old_value, new_value=new_value, ) sub.save() form.save() translation_submitted.send( sender=translation_project, unit=form.instance, profile=request.profile, ) rcode = 200 else: # Form failed #FIXME: we should display validation errors here rcode = 400 json["msg"] = _("Failed to process submission.") response = jsonify(json) return HttpResponse(response, status=rcode, mimetype="application/json")
def submit(request, unit): """Processes translation submissions and stores them in the database. :return: An object in JSON notation that contains the previous and last units for the unit next to unit ``uid``. """ json = {} translation_project = request.translation_project language = translation_project.language user = request.user if unit.hasplural(): snplurals = len(unit.source.strings) else: snplurals = None # Store current time so that it is the same for all submissions current_time = timezone.now() # Update current unit instance's attributes unit.submitted_by = request.user unit.submitted_on = current_time form_class = unit_form_factory(language, snplurals, request) form = form_class(request.POST, instance=unit, request=request) if form.is_valid(): if form.updated_fields: for field, old_value, new_value in form.updated_fields: sub = Submission( creation_time=current_time, translation_project=translation_project, submitter=request.user, unit=unit, field=field, type=SubmissionTypes.NORMAL, old_value=old_value, new_value=new_value, ) sub.save() form.instance._log_user = request.user form.save() translation_submitted.send( sender=translation_project, unit=form.instance, user=request.user, ) has_critical_checks = unit.qualitycheck_set.filter( category=Category.CRITICAL ).exists() if has_critical_checks: can_review = check_user_permission(user, "review", unit.store.parent) ctx = { 'canreview': can_review, 'unit': unit } template = loader.get_template('editor/units/xhr_checks.html') context = RequestContext(request, ctx) json['checks'] = template.render(context) rcode = 200 else: # Form failed #FIXME: we should display validation errors here rcode = 400 json["msg"] = _("Failed to process submission.") response = jsonify(json) return HttpResponse(response, status=rcode, mimetype="application/json")
def submit(request, unit): """Processes translation submissions and stores them in the database. :return: An object in JSON notation that contains the previous and last units for the unit next to unit ``uid``. """ json = {} translation_project = request.translation_project language = translation_project.language old_unit = copy.copy(unit) if unit.hasplural(): snplurals = len(unit.source.strings) else: snplurals = None # Store current time so that it is the same for all submissions current_time = timezone.now() form_class = unit_form_factory(language, snplurals, request) form = form_class(request.POST, instance=unit, request=request) if form.is_valid(): suggestion = form.cleaned_data['suggestion'] if suggestion: old_unit.accept_suggestion(suggestion, request.translation_project, request.user) if form.cleaned_data['comment']: kwargs = dict( comment=form.cleaned_data['comment'], user=request.user, ) comment_form = UnsecuredCommentForm(suggestion, kwargs) if comment_form.is_valid(): comment_form.save() if form.updated_fields: for field, old_value, new_value in form.updated_fields: if field == SubmissionFields.TARGET and suggestion: old_value = str(suggestion.target_f) sub = Submission( creation_time=current_time, translation_project=translation_project, submitter=request.user, unit=unit, store=unit.store, field=field, type=SubmissionTypes.NORMAL, old_value=old_value, new_value=new_value, similarity=form.cleaned_data['similarity'], mt_similarity=form.cleaned_data['mt_similarity'], ) sub.save() # Update current unit instance's attributes # important to set these attributes after saving Submission # because we need to access the unit's state before it was saved if SubmissionFields.TARGET in (f[0] for f in form.updated_fields): form.instance.submitted_by = request.user form.instance.submitted_on = current_time form.instance.reviewed_by = None form.instance.reviewed_on = None form.instance._log_user = request.user form.save() json['checks'] = _get_critical_checks_snippet(request, unit) json['user_score'] = request.user.public_score return JsonResponse(json) return JsonResponseBadRequest({'msg': _("Failed to process submission.")})
def submit(request, unit): """Processes translation submissions and stores them in the database. :return: An object in JSON notation that contains the previous and last units for the unit next to unit ``uid``. """ json = {} cantranslate = check_permission("translate", request) if not cantranslate: raise PermissionDenied(_("You do not have rights to access " "translation mode.")) translation_project = request.translation_project language = translation_project.language if unit.hasplural(): snplurals = len(unit.source.strings) else: snplurals = None # Store current time so that it is the same for all submissions current_time = timezone.now() # Update current unit instance's attributes unit.submitted_by = request.profile unit.submitted_on = current_time form_class = unit_form_factory(language, snplurals, request) form = form_class(request.POST, instance=unit) if form.is_valid(): if form.updated_fields: for field, old_value, new_value in form.updated_fields: # (jgonzale|2014-09-05|INTL-591): log unsolicited modification to the source field if field == SubmissionFields.SOURCE: logging.warning( u'Corrupted submission for (unit_id, {0}) - ' \ u'(submitter, {1}) ' \ u'(source_old_value, {2}) ' \ u'(request info - {3})'.format(unit.id, request.profile, old_value, repr(request)) ) sub = Submission( creation_time=current_time, translation_project=translation_project, submitter=request.profile, unit=unit, field=field, type=SubmissionTypes.NORMAL, old_value=old_value, new_value=new_value, ) sub.save() form.save() translation_submitted.send( sender=translation_project, unit=form.instance, profile=request.profile, ) rcode = 200 else: # Form failed #FIXME: we should display validation errors here rcode = 400 json["msg"] = _("Failed to process submission.") response = jsonify(json) return HttpResponse(response, status=rcode, mimetype="application/json")
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))