def handle_translate(request, translation, this_unit_url, next_unit_url): """Save translation or suggestion to database and backend.""" # Antispam protection antispam = AntispamForm(request.POST) if not antispam.is_valid(): # Silently redirect to next entry return HttpResponseRedirect(next_unit_url) form = TranslationForm( request.user, translation, None, request.POST ) if not form.is_valid(): show_form_errors(request, form) return None unit = form.cleaned_data['unit'] go_next = True if 'suggest' in request.POST: go_next = perform_suggestion(unit, form, request) elif not request.user.has_perm('unit.edit', unit): messages.error( request, _('Insufficient privileges for saving translations.') ) else: go_next = perform_translation(unit, form, request) # Redirect to next entry if go_next: return HttpResponseRedirect(next_unit_url) return HttpResponseRedirect(this_unit_url)
def search(translation, request): """Perform search or returns cached search results.""" # Possible new search form = SearchForm(request.GET) # Process form form_valid = form.is_valid() if not form_valid: show_form_errors(request, form) search_result = { 'form': form, 'offset': form.cleaned_data.get('offset', 1), 'checksum': form.cleaned_data.get('checksum'), } search_url = form.urlencode() session_key = 'search_{0}_{1}'.format(translation.pk, search_url) if (session_key in request.session and 'offset' in request.GET and 'items' in request.session[session_key]): search_result.update(request.session[session_key]) return search_result allunits = translation.unit_set.search( form.cleaned_data, translation=translation, ) search_query = form.get_search_query() if form_valid else '' name = form.get_name() if form_valid else '' # Grab unit IDs unit_ids = list(allunits.values_list('id', flat=True)) # Check empty search results if not unit_ids: messages.warning(request, _('No string matched your search!')) return redirect(translation) # Remove old search results cleanup_session(request.session) store_result = { 'query': search_query, 'url': search_url, 'items': form.items(), 'key': session_key, 'name': force_text(name), 'ids': unit_ids, 'ttl': int(time.time()) + 86400, } request.session[session_key] = store_result search_result.update(store_result) return search_result
def remove_translation(request, project, component, lang): obj = get_translation(request, project, component, lang) if not request.user.has_perm('translation.delete', obj): raise PermissionDenied() form = DeleteForm(obj, request.POST) if not form.is_valid(): show_form_errors(request, form) return redirect_param(obj, '#delete') obj.remove(request.user) messages.success(request, _('Translation has been removed.')) return redirect(obj.component)
def whiteboard_project(request, project): obj = get_project(request, project) if not request.user.has_perm('project.edit', obj): raise PermissionDenied() form = WhiteboardForm(request.POST) if not form.is_valid(): show_form_errors(request, form) return redirect_param(obj, '#whiteboard') WhiteboardMessage.objects.create( project=obj, **form.cleaned_data ) return redirect(obj)
def perform_rename(form_cls, request, obj, perm, **kwargs): if not request.user.has_perm(perm, obj): raise PermissionDenied() form = form_cls(request, request.POST, instance=obj) if not form.is_valid(): show_form_errors(request, form) return redirect_param(obj, '#delete') form.save() Change.objects.create( user=request.user, author=request.user, **kwargs ) return redirect(obj)
def state_change(request, project, component=None, lang=None): obj, unit_set, context = parse_url(request, project, component, lang) if not request.user.has_perm('translation.auto', obj): raise PermissionDenied() form = MassStateForm(request.user, obj, request.POST) if not form.is_valid(): messages.error(request, _('Failed to process form!')) show_form_errors(request, form) return redirect(obj) matching = unit_set.filter_type( form.cleaned_data['type'], context['project'], context['translation'].language if 'translation' in context else None, ).exclude( state=STATE_EMPTY ) updated = 0 with transaction.atomic(): for unit in matching.select_for_update(): if not request.user.has_perm('unit.edit', unit): continue unit.translate( request, unit.target, int(form.cleaned_data['state']), change_action=Change.ACTION_MASS_STATE, ) updated += 1 import_message( request, updated, _('Mass state change completed, no strings were updated.'), ungettext( 'Mass state change completed, %d string was updated.', 'Mass state change completed, %d strings were updated.', updated ) ) return redirect(obj)
def save_zen(request, project, component, lang): """Save handler for zen mode.""" def render_mesage(message): return render_to_string( 'message.html', {'tags': message.tags, 'message': message.message} ) translation = get_translation(request, project, component, lang) form = TranslationForm( request.user, translation, None, request.POST ) translationsum = '' if not form.is_valid(): show_form_errors(request, form) elif not request.user.has_perm('unit.edit', form.cleaned_data['unit']): messages.error( request, _('Insufficient privileges for saving translations.') ) else: unit = form.cleaned_data['unit'] perform_translation(unit, form, request) translationsum = hash_to_checksum(unit.get_target_hash()) response = { 'messages': '', 'state': 'success', 'translationsum': translationsum, } storage = get_messages(request) if storage: response['messages'] = '\n'.join([render_mesage(m) for m in storage]) tags = {m.tags for m in storage} if 'error' in tags: response['state'] = 'danger' elif 'warning' in tags: response['state'] = 'warning' elif 'info' in tags: response['state'] = 'info' return JsonResponse(data=response)
def download_translation(request, project, component, lang): obj = get_translation(request, project, component, lang) kwargs = {} if 'format' in request.GET or 'type' in request.GET: form = DownloadForm(request.GET) if not form.is_valid(): show_form_errors(request, form) return redirect(obj) kwargs['units'] = obj.unit_set.search( form.cleaned_data, translation=obj, ) kwargs['fmt'] = form.cleaned_data['format'] return download_translation_file(obj, **kwargs)
def whiteboard_translation(request, project, component, lang): obj = get_translation(request, project, component, lang) if not request.user.has_perm('component.edit', obj): raise PermissionDenied() form = WhiteboardForm(request.POST) if not form.is_valid(): show_form_errors(request, form) return redirect_param(obj, '#whiteboard') WhiteboardMessage.objects.create( project=obj.component.project, component=obj.component, language=obj.language, **form.cleaned_data ) return redirect(obj)
def auto_translation(request, project, component, lang): translation = get_translation(request, project, component, lang) project = translation.component.project if not request.user.has_perm('translation.auto', project): raise PermissionDenied() autoform = AutoForm(request.user, translation, request.POST) if translation.component.locked or not autoform.is_valid(): messages.error(request, _('Failed to process form!')) show_form_errors(request, autoform) return redirect(translation) auto = AutoTranslate( request.user, translation, autoform.cleaned_data['type'], request=request ) if autoform.cleaned_data['auto_source'] == 'mt': auto.process_mt( autoform.cleaned_data['engines'], autoform.cleaned_data['threshold'], ) else: auto.process_others( autoform.cleaned_data['component'], ) import_message( request, auto.updated, _('Automatic translation completed, no strings were updated.'), ungettext( 'Automatic translation completed, %d string was updated.', 'Automatic translation completed, %d strings were updated.', auto.updated ) ) return redirect(translation)
def remove_project(request, project): obj = get_project(request, project) if not request.user.has_perm('project.edit', obj): raise PermissionDenied() form = DeleteForm(obj, request.POST) if not form.is_valid(): show_form_errors(request, form) return redirect_param(obj, '#delete') project_removal.delay(obj.pk) messages.success(request, _('Project was scheduled for removal.')) Change.objects.create( action=Change.ACTION_REMOVE_PROJECT, target=obj.slug, user=request.user, author=request.user ) return redirect('home')
def remove_component(request, project, component): obj = get_component(request, project, component) if not request.user.has_perm('component.edit', obj): raise PermissionDenied() form = DeleteForm(obj, request.POST) if not form.is_valid(): show_form_errors(request, form) return redirect_param(obj, '#delete') obj.delete() messages.success(request, _('Translation component has been removed.')) Change.objects.create( project=obj.project, action=Change.ACTION_REMOVE_COMPONENT, target=obj.slug, user=request.user, author=request.user ) return redirect(obj.project)
def new_unit(request, project, component, lang): translation = get_translation(request, project, component, lang) if not request.user.has_perm('unit.add', translation): raise PermissionDenied() form = NewUnitForm(request.user, request.POST) if not form.is_valid(): show_form_errors(request, form) else: key = form.cleaned_data['key'] value = form.cleaned_data['value'][0] if translation.unit_set.filter(context=key).exists(): messages.error( request, _('Translation with this key seem to already exist!') ) else: translation.new_unit(request, key, value) messages.success( request, _('New string has been added.') ) return redirect(translation)
def get_credits(request, project=None, component=None): """View for credits""" if project is None: obj = None kwargs = {'translation__pk__gt': 0} elif component is None: obj = get_project(request, project) kwargs = {'translation__component__project': obj} else: obj = get_component(request, project, component) kwargs = {'translation__component': obj} form = ReportsForm(request.POST) if not form.is_valid(): show_form_errors(request, form) return redirect_param(obj or 'home', '#reports') data = generate_credits( None if request.user.has_perm('reports.view', obj) else request.user, form.cleaned_data['start_date'], form.cleaned_data['end_date'], **kwargs) if form.cleaned_data['style'] == 'json': return JsonResponse(data=data, safe=False) if form.cleaned_data['style'] == 'html': start = '<table>' row_start = '<tr>' language_format = '<th>{0}</th>' translator_start = '<td><ul>' translator_format = '<li><a href="mailto:{0}">{1}</a></li>' translator_end = '</ul></td>' row_end = '</tr>' mime = 'text/html' end = '</table>' else: start = '' row_start = '' language_format = '* {0}\n' translator_start = '' translator_format = ' * {1} <{0}>' translator_end = '' row_end = '' mime = 'text/plain' end = '' result = [] result.append(start) for language in data: name, translators = language.popitem() result.append(row_start) result.append(language_format.format(name)) result.append(translator_start + '\n'.join( translator_format.format(*t) for t in translators) + translator_end) result.append(row_end) result.append(end) return HttpResponse('\n'.join(result), content_type='{0}; charset=utf-8'.format(mime))
def get_credits(request, project, component): """View for credits""" obj = get_component(request, project, component) if not request.user.has_perm('reports.view', obj): raise PermissionDenied() form = ReportsForm(request.POST) if not form.is_valid(): show_form_errors(request, form) return redirect_param(obj, '#reports') data = generate_credits( obj, form.cleaned_data['start_date'], form.cleaned_data['end_date'], ) if form.cleaned_data['style'] == 'json': return JsonResponse(data=data, safe=False) if form.cleaned_data['style'] == 'html': start = '<table>' row_start = '<tr>' language_format = '<th>{0}</th>' translator_start = '<td><ul>' translator_format = '<li><a href="mailto:{0}">{1}</a></li>' translator_end = '</ul></td>' row_end = '</tr>' mime = 'text/html' end = '</table>' else: start = '' row_start = '' language_format = '* {0}\n' translator_start = '' translator_format = ' * {1} <{0}>' translator_end = '' row_end = '' mime = 'text/plain' end = '' result = [] result.append(start) for language in data: name, translators = language.popitem() result.append(row_start) result.append(language_format.format(name)) result.append( ''.join(( translator_start, '\n'.join( [translator_format.format(*t) for t in translators] ), translator_end, )) ) result.append(row_end) result.append(end) return HttpResponse( '\n'.join(result), content_type='{0}; charset=utf-8'.format(mime), )
def search(request, project=None, component=None, lang=None): """Perform site-wide search on units.""" is_ratelimited = not check_rate_limit('search', request) search_form = SiteSearchForm(request.GET) context = { 'search_form': search_form, } search_kwargs = {} if component: obj = get_component(request, project, component) context['component'] = obj context['project'] = obj.project context['back_url'] = obj.get_absolute_url() search_kwargs = {'component': obj} elif project: obj = get_project(request, project) context['project'] = obj context['back_url'] = obj.get_absolute_url() search_kwargs = {'project': obj} else: obj = None context['back_url'] = None if lang: s_language = get_object_or_404(Language, code=lang) context['language'] = s_language search_kwargs = {'language': s_language} if obj: if component: context['back_url'] = obj.translation_set.get( language=s_language).get_absolute_url() else: context['back_url'] = reverse('project-language', kwargs={ 'project': project, 'lang': lang, }) else: context['back_url'] = s_language.get_absolute_url() if not is_ratelimited and request.GET and search_form.is_valid(): # Filter results by ACL if component: units = Unit.objects.filter(translation__component=obj) elif project: units = Unit.objects.filter(translation__component__project=obj) else: allowed_projects = request.user.allowed_projects units = Unit.objects.filter( translation__component__project__in=allowed_projects) units = units.search(search_form.cleaned_data, **search_kwargs) if lang: units = units.filter(translation__language=context['language']) units = get_paginator(request, units) context['show_results'] = True context['page_obj'] = units context['title'] = _('Search for %s') % (search_form.cleaned_data['q']) context['query_string'] = search_form.urlencode() context['search_query'] = search_form.cleaned_data['q'] elif is_ratelimited: messages.error(request, _('Too many search queries, please try again later.')) elif request.GET: messages.error(request, _('Invalid search query!')) show_form_errors(request, search_form) return render(request, 'search.html', context)
def search(request, project=None, component=None, lang=None): """Perform site-wide search on units.""" is_ratelimited = not check_rate_limit('search', request) search_form = SiteSearchForm(request.GET) context = { 'search_form': search_form, } search_kwargs = {} if component: obj = get_component(request, project, component) context['component'] = obj context['project'] = obj.project context['back_url'] = obj.get_absolute_url() search_kwargs = {'component': obj} elif project: obj = get_project(request, project) context['project'] = obj context['back_url'] = obj.get_absolute_url() search_kwargs = {'project': obj} else: obj = None context['back_url'] = None if lang: s_language = get_object_or_404(Language, code=lang) context['language'] = s_language search_kwargs = {'language': s_language} if obj: if component: context['back_url'] = obj.translation_set.get( language=s_language ).get_absolute_url() else: context['back_url'] = reverse( 'project-language', kwargs={ 'project': project, 'lang': lang, } ) else: context['back_url'] = s_language.get_absolute_url() if not is_ratelimited and request.GET and search_form.is_valid(): # Filter results by ACL if component: units = Unit.objects.filter(translation__component=obj) elif project: units = Unit.objects.filter(translation__component__project=obj) else: allowed_projects = request.user.allowed_projects units = Unit.objects.filter( translation__component__project__in=allowed_projects ) units = units.search( search_form.cleaned_data, **search_kwargs ) if lang: units = units.filter( translation__language=context['language'] ) units = get_paginator(request, units) context['show_results'] = True context['page_obj'] = units context['title'] = _('Search for %s') % ( search_form.cleaned_data['q'] ) context['query_string'] = search_form.urlencode() context['search_query'] = search_form.cleaned_data['q'] elif is_ratelimited: messages.error( request, _('Too many search queries, please try again later.') ) elif request.GET: messages.error(request, _('Invalid search query!')) show_form_errors(request, search_form) return render( request, 'search.html', context )
def search_replace(request, project, component=None, lang=None): obj, unit_set, context = parse_url(request, project, component, lang) form = ReplaceForm(request.POST) if not form.is_valid(): messages.error(request, _('Failed to process form!')) show_form_errors(request, form) return redirect(obj) search_text = form.cleaned_data['search'] replacement = form.cleaned_data['replacement'] matching = unit_set.filter(target__contains=search_text) updated = 0 if matching.exists(): confirm = ReplaceConfirmForm(matching, request.POST) limited = False if matching.count() > 300: matching = matching.order_by('id')[:250] limited = True if not confirm.is_valid(): for unit in matching: unit.replacement = unit.target.replace( search_text, replacement ) context.update({ 'matching': matching, 'search_query': search_text, 'replacement': replacement, 'form': form, 'limited': limited, 'confirm': ReplaceConfirmForm(matching), }) return render( request, 'replace.html', context ) matching = confirm.cleaned_data['units'] with transaction.atomic(): for unit in matching.select_for_update(): if not request.user.has_perm('unit.edit', unit): continue unit.translate( request, unit.target.replace(search_text, replacement), unit.state, change_action=Change.ACTION_REPLACE ) updated += 1 import_message( request, updated, _('Search and replace completed, no strings were updated.'), ungettext( 'Search and replace completed, %d string was updated.', 'Search and replace completed, %d strings were updated.', updated ) ) return redirect(obj)
def upload_translation(request, project, component, lang): """Handling of translation uploads.""" obj = get_translation(request, project, component, lang) if not request.user.has_perm("upload.perform", obj): raise PermissionDenied() # Check method and lock if obj.component.locked: messages.error(request, _("Access denied.")) return redirect(obj) # Get correct form handler based on permissions form = get_upload_form(request.user, obj, request.POST, request.FILES) # Check form validity if not form.is_valid(): messages.error(request, _("Please fix errors in the form.")) show_form_errors(request, form) return redirect(obj) # Create author name author_name = None author_email = None if request.user.has_perm("upload.authorship", obj): author_name = form.cleaned_data["author_name"] author_email = form.cleaned_data["author_email"] # Check for overwriting conflicts = "" if request.user.has_perm("upload.overwrite", obj): conflicts = form.cleaned_data["conflicts"] # Do actual import try: not_found, skipped, accepted, total = obj.handle_upload( request, request.FILES["file"], conflicts, author_name, author_email, method=form.cleaned_data["method"], fuzzy=form.cleaned_data["fuzzy"], ) if total == 0: message = _("No strings were imported from the uploaded file.") else: message = ngettext( "Processed {0} string from the uploaded files " "(skipped: {1}, not found: {2}, updated: {3}).", "Processed {0} strings from the uploaded files " "(skipped: {1}, not found: {2}, updated: {3}).", total, ).format(total, skipped, not_found, accepted) if accepted == 0: messages.warning(request, message) else: messages.success(request, message) except PluralFormsMismatch: messages.error( request, _("Plural forms in the uploaded file do not match current translation." ), ) except Exception as error: messages.error( request, _("File upload has failed: %s") % str(error).replace(obj.component.full_path, ""), ) report_error(cause="Upload error") return redirect(obj)
def search(request, project=None, component=None, lang=None): """Perform site-wide search on units.""" is_ratelimited = not check_rate_limit("search", request) search_form = SearchForm(request.user, request.GET) sort = get_sort_name(request) context = {"search_form": search_form} if component: obj = get_component(request, project, component) context["component"] = obj context["project"] = obj.project context["back_url"] = obj.get_absolute_url() elif project: obj = get_project(request, project) context["project"] = obj context["back_url"] = obj.get_absolute_url() else: obj = None context["back_url"] = None if lang: s_language = get_object_or_404(Language, code=lang) context["language"] = s_language if obj: if component: context["back_url"] = obj.translation_set.get( language=s_language ).get_absolute_url() else: context["back_url"] = reverse( "project-language", kwargs={"project": project, "lang": lang} ) else: context["back_url"] = s_language.get_absolute_url() if not is_ratelimited and request.GET and search_form.is_valid(): # This is ugly way to hide query builder when showing results search_form = SearchForm(request.user, request.GET, show_builder=False) search_form.is_valid() # Filter results by ACL if component: units = Unit.objects.filter(translation__component=obj) elif project: units = Unit.objects.filter(translation__component__project=obj) else: units = Unit.objects.filter_access(request.user) units = units.search(search_form.cleaned_data.get("q", "")).distinct() if lang: units = units.filter(translation__language=context["language"]) units = get_paginator(request, units.order_by_request(search_form.cleaned_data)) # Rebuild context from scratch here to get new form context = { "search_form": search_form, "show_results": True, "page_obj": units, "title": _("Search for %s") % (search_form.cleaned_data["q"]), "query_string": search_form.urlencode(), "search_query": search_form.cleaned_data["q"], "search_items": search_form.items(), "filter_name": search_form.get_name(), "sort_name": sort["name"], "sort_query": sort["query"], } elif is_ratelimited: messages.error(request, _("Too many search queries, please try again later.")) elif request.GET: messages.error(request, _("Invalid search query!")) show_form_errors(request, search_form) return render(request, "search.html", context)
def search(base, unit_set, request): """Perform search or returns cached search results.""" # Possible new search form = PositionSearchForm(user=request.user, data=request.GET, show_builder=False) # Process form form_valid = form.is_valid() if form_valid: cleaned_data = form.cleaned_data search_url = form.urlencode() search_query = form.get_search_query() name = form.get_name() search_items = form.items() else: cleaned_data = {} show_form_errors(request, form) search_url = "" search_query = "" name = "" search_items = () search_result = { "form": form, "offset": cleaned_data.get("offset", 1), } session_key = f"search_{base.cache_key}_{search_url}" if (session_key in request.session and "offset" in request.GET and "items" in request.session[session_key]): search_result.update(request.session[session_key]) return search_result allunits = unit_set.search(cleaned_data.get("q", "")).distinct() # Grab unit IDs unit_ids = list( allunits.order_by_request(cleaned_data).values_list("id", flat=True)) # Check empty search results if not unit_ids: messages.warning(request, _("No string matched your search!")) return redirect(base) # Remove old search results cleanup_session(request.session) store_result = { "query": search_query, "url": search_url, "items": search_items, "key": session_key, "name": force_str(name), "ids": unit_ids, "ttl": int(time.time()) + 86400, } request.session[session_key] = store_result search_result.update(store_result) return search_result
def upload_translation(request, project, component, lang): """Handling of translation uploads.""" obj = get_translation(request, project, component, lang) if not request.user.has_perm('upload.perform', obj): raise PermissionDenied() # Check method and lock if obj.component.locked: messages.error(request, _('Access denied.')) return redirect(obj) # Get correct form handler based on permissions form = get_upload_form(request.user, obj, request.POST, request.FILES) # Check form validity if not form.is_valid(): messages.error(request, _('Please fix errors in the form.')) show_form_errors(request, form) return redirect(obj) # Create author name author_name = None author_email = None if request.user.has_perm('upload.authorship', obj): author_name = form.cleaned_data['author_name'] author_email = form.cleaned_data['author_email'] # Check for overwriting overwrite = False if request.user.has_perm('upload.overwrite', obj): overwrite = form.cleaned_data['upload_overwrite'] # Do actual import try: not_found, skipped, accepted, total = obj.merge_upload( request, request.FILES['file'], overwrite, author_name, author_email, method=form.cleaned_data['method'], fuzzy=form.cleaned_data['fuzzy'], ) if total == 0: message = _('No strings were imported from the uploaded file.') else: message = ungettext( 'Processed {0} string from the uploaded files ' '(skipped: {1}, not found: {2}, updated: {3}).', 'Processed {0} strings from the uploaded files ' '(skipped: {1}, not found: {2}, updated: {3}).', total).format(total, skipped, not_found, accepted) if accepted == 0: messages.warning(request, message) else: messages.success(request, message) except Exception as error: messages.error(request, _('File content merge failed: %s') % force_text(error)) report_error(error, request, prefix='Failed to merge content') return redirect(obj)
def get_credits(request, project, component): """View for credits""" obj = get_component(request, project, component) if not request.user.has_perm('reports.view', obj): raise PermissionDenied() form = ReportsForm(request.POST) if not form.is_valid(): show_form_errors(request, form) return redirect_param(obj, '#reports') data = generate_credits( obj, form.cleaned_data['start_date'], form.cleaned_data['end_date'], ) if form.cleaned_data['style'] == 'json': return JsonResponse(data=data, safe=False) if form.cleaned_data['style'] == 'html': start = '<table>' row_start = '<tr>' language_format = '<th>{0}</th>' translator_start = '<td><ul>' translator_format = '<li><a href="mailto:{0}">{1}</a></li>' translator_end = '</ul></td>' row_end = '</tr>' mime = 'text/html' end = '</table>' else: start = '' row_start = '' language_format = '* {0}\n' translator_start = '' translator_format = ' * {1} <{0}>' translator_end = '' row_end = '' mime = 'text/plain' end = '' result = [] result.append(start) for language in data: name, translators = language.popitem() result.append(row_start) result.append(language_format.format(name)) result.append(''.join(( translator_start, '\n'.join([translator_format.format(*t) for t in translators]), translator_end, ))) result.append(row_end) result.append(end) return HttpResponse( '\n'.join(result), content_type='{0}; charset=utf-8'.format(mime), )
def form_invalid(self, form): show_form_errors(self.request, form) return super().form_invalid(form)
def get_counts(request, project=None, component=None): """View for work counts.""" if project is None: obj = None kwargs = {} elif component is None: obj = get_project(request, project) kwargs = {"project": obj} else: obj = get_component(request, project, component) kwargs = {"component": obj} form = ReportsForm(request.POST) if not form.is_valid(): show_form_errors(request, form) return redirect_param(obj or "home", "#reports") data = generate_counts( None if request.user.has_perm("reports.view", obj) else request.user, form.cleaned_data["start_date"], form.cleaned_data["end_date"], **kwargs) if form.cleaned_data["style"] == "json": return JsonResponse(data=data, safe=False) headers = ( "Name", "Email", "Count total", "Edits total", "Source words total", "Source chars total", "Target words total", "Target chars total", "Count new", "Edits new", "Source words new", "Source chars new", "Target words new", "Target chars new", "Count approved", "Edits approved", "Source words approved", "Source chars approved", "Target words approved", "Target chars approved", "Count edited", "Edits edited", "Source words edited", "Source chars edited", "Target words edited", "Target chars edited", ) if form.cleaned_data["style"] == "html": start = HTML_HEADING.format("".join("<th>{0}</th>".format(h) for h in headers)) row_start = "<tr>" cell_name = cell_count = "<td>{0}</td>\n" row_end = "</tr>" mime = "text/html" end = "</table>" else: start = "{0}\n{1} {2}\n{0}".format( RST_HEADING, " ".join("{0:40}".format(h) for h in headers[:2]), " ".join("{0:24}".format(h) for h in headers[2:]), ) row_start = "" cell_name = "{0:40} " cell_count = "{0:24} " row_end = "" mime = "text/plain" end = RST_HEADING result = [] result.append(start) for item in data: if row_start: result.append(row_start) result.append("".join(( cell_name.format(item["name"] or "Anonymous"), cell_name.format(item["email"] or ""), cell_count.format(item["count"]), cell_count.format(item["edits"]), cell_count.format(item["words"]), cell_count.format(item["chars"]), cell_count.format(item["t_words"]), cell_count.format(item["t_chars"]), cell_count.format(item["count_new"]), cell_count.format(item["edits_new"]), cell_count.format(item["words_new"]), cell_count.format(item["chars_new"]), cell_count.format(item["t_words_new"]), cell_count.format(item["t_chars_new"]), cell_count.format(item["count_approve"]), cell_count.format(item["edits_approve"]), cell_count.format(item["words_approve"]), cell_count.format(item["chars_approve"]), cell_count.format(item["t_words_approve"]), cell_count.format(item["t_chars_approve"]), cell_count.format(item["count_edit"]), cell_count.format(item["edits_edit"]), cell_count.format(item["words_edit"]), cell_count.format(item["chars_edit"]), cell_count.format(item["t_words_edit"]), cell_count.format(item["t_chars_edit"]), ))) if row_end: result.append(row_end) result.append(end) return HttpResponse("\n".join(result), content_type="{0}; charset=utf-8".format(mime))
def get_counts(request, project, component): """View for work counts""" obj = get_component(request, project, component) if not request.user.has_perm('reports.view', obj): raise PermissionDenied() form = ReportsForm(request.POST) if not form.is_valid(): show_form_errors(request, form) return redirect_param(obj, '#reports') data = generate_counts( obj, form.cleaned_data['start_date'], form.cleaned_data['end_date'], ) if form.cleaned_data['style'] == 'json': return JsonResponse(data=data, safe=False) headers = ( 'Name', 'Email', 'Count total', 'Source words total', 'Source chars total', 'Target words total', 'Target chars total', 'Count new', 'Source words new', 'Source chars new', 'Target words new', 'Target chars new', 'Count approved', 'Source words approved', 'Source chars approved', 'Target words approved', 'Target chars approved', 'Count edited', 'Source words edited', 'Source chars edited', 'Target words edited', 'Target chars edited', ) if form.cleaned_data['style'] == 'html': start = HTML_HEADING.format( ''.join(['<th>{0}</th>'.format(h) for h in headers]) ) row_start = '<tr>' cell_name = cell_count = '<td>{0}</td>\n' row_end = '</tr>' mime = 'text/html' end = '</table>' else: start = '{0}\n{1} {2}\n{0}'.format( RST_HEADING, ' '.join(['{0:40}'.format(h) for h in headers[:2]]), ' '.join(['{0:24}'.format(h) for h in headers[2:]]), ) row_start = '' cell_name = '{0:40} ' cell_count = '{0:24} ' row_end = '' mime = 'text/plain' end = RST_HEADING result = [] result.append(start) for item in data: if row_start: result.append(row_start) result.append( ''.join(( cell_name.format(item['name']), cell_name.format(item['email']), cell_count.format(item['count']), cell_count.format(item['words']), cell_count.format(item['chars']), cell_count.format(item['t_words']), cell_count.format(item['t_chars']), cell_count.format(item['count_new']), cell_count.format(item['words_new']), cell_count.format(item['chars_new']), cell_count.format(item['t_words_new']), cell_count.format(item['t_chars_new']), cell_count.format(item['count_approve']), cell_count.format(item['words_approve']), cell_count.format(item['chars_approve']), cell_count.format(item['t_words_approve']), cell_count.format(item['t_chars_approve']), cell_count.format(item['count_edit']), cell_count.format(item['words_edit']), cell_count.format(item['chars_edit']), cell_count.format(item['t_words_edit']), cell_count.format(item['t_chars_edit']), )) ) if row_end: result.append(row_end) result.append(end) return HttpResponse( '\n'.join(result), content_type='{0}; charset=utf-8'.format(mime), )
def upload_translation(request, project, component, lang): """Handling of translation uploads.""" obj = get_translation(request, project, component, lang) if not request.user.has_perm('upload.perform', obj): raise PermissionDenied() # Check method and lock if obj.component.locked: messages.error(request, _('Access denied.')) return redirect(obj) # Get correct form handler based on permissions form = get_upload_form( request.user, obj, request.POST, request.FILES ) # Check form validity if not form.is_valid(): messages.error(request, _('Please fix errors in the form.')) show_form_errors(request, form) return redirect(obj) # Create author name author = None if (request.user.has_perm('upload.authorship', obj) and form.cleaned_data['author_name'] != '' and form.cleaned_data['author_email'] != ''): author = '{0} <{1}>'.format( form.cleaned_data['author_name'], form.cleaned_data['author_email'] ) # Check for overwriting overwrite = False if request.user.has_perm('upload.overwrite', obj): overwrite = form.cleaned_data['upload_overwrite'] # Do actual import try: not_found, skipped, accepted, total = obj.merge_upload( request, request.FILES['file'], overwrite, author, method=form.cleaned_data['method'], fuzzy=form.cleaned_data['fuzzy'], ) if total == 0: message = _('No strings were imported from the uploaded file.') else: message = ungettext( 'Processed {0} string from the uploaded files ' '(skipped: {1}, not found: {2}, updated: {3}).', 'Processed {0} strings from the uploaded files ' '(skipped: {1}, not found: {2}, updated: {3}).', total ).format(total, skipped, not_found, accepted) if accepted == 0: messages.warning(request, message) else: messages.success(request, message) except Exception as error: messages.error( request, _('File content merge failed: %s') % force_text(error) ) report_error(error, request) return redirect(obj)
def get_counts(request, project, component): """View for work counts""" obj = get_component(request, project, component) if not request.user.has_perm('reports.view', obj): raise PermissionDenied() form = ReportsForm(request.POST) if not form.is_valid(): show_form_errors(request, form) return redirect_param(obj, '#reports') data = generate_counts( obj, form.cleaned_data['start_date'], form.cleaned_data['end_date'], ) if form.cleaned_data['style'] == 'json': return JsonResponse(data=data, safe=False) headers = ( 'Name', 'Email', 'Count total', 'Source words total', 'Source chars total', 'Target words total', 'Target chars total', 'Count new', 'Source words new', 'Source chars new', 'Target words new', 'Target chars new', 'Count approved', 'Source words approved', 'Source chars approved', 'Target words approved', 'Target chars approved', 'Count edited', 'Source words edited', 'Source chars edited', 'Target words edited', 'Target chars edited', ) if form.cleaned_data['style'] == 'html': start = HTML_HEADING.format(''.join( ['<th>{0}</th>'.format(h) for h in headers])) row_start = '<tr>' cell_name = cell_count = '<td>{0}</td>\n' row_end = '</tr>' mime = 'text/html' end = '</table>' else: start = '{0}\n{1} {2}\n{0}'.format( RST_HEADING, ' '.join(['{0:40}'.format(h) for h in headers[:2]]), ' '.join(['{0:24}'.format(h) for h in headers[2:]]), ) row_start = '' cell_name = '{0:40} ' cell_count = '{0:24} ' row_end = '' mime = 'text/plain' end = RST_HEADING result = [] result.append(start) for item in data: if row_start: result.append(row_start) result.append(''.join(( cell_name.format(item['name']), cell_name.format(item['email']), cell_count.format(item['count']), cell_count.format(item['words']), cell_count.format(item['chars']), cell_count.format(item['t_words']), cell_count.format(item['t_chars']), cell_count.format(item['count_new']), cell_count.format(item['words_new']), cell_count.format(item['chars_new']), cell_count.format(item['t_words_new']), cell_count.format(item['t_chars_new']), cell_count.format(item['count_approve']), cell_count.format(item['words_approve']), cell_count.format(item['chars_approve']), cell_count.format(item['t_words_approve']), cell_count.format(item['t_chars_approve']), cell_count.format(item['count_edit']), cell_count.format(item['words_edit']), cell_count.format(item['chars_edit']), cell_count.format(item['t_words_edit']), cell_count.format(item['t_chars_edit']), ))) if row_end: result.append(row_end) result.append(end) return HttpResponse( '\n'.join(result), content_type='{0}; charset=utf-8'.format(mime), )
def search_replace(request, project, component=None, lang=None): obj, unit_set, context = parse_url(request, project, component, lang) form = ReplaceForm(request.POST) if not form.is_valid(): messages.error(request, _("Failed to process form!")) show_form_errors(request, form) return redirect(obj) search_text = form.cleaned_data["search"] replacement = form.cleaned_data["replacement"] matching = unit_set.filter(target__contains=search_text) updated = 0 if matching.exists(): confirm = ReplaceConfirmForm(matching, request.POST) limited = False if matching.count() > 300: matching = matching.order_by("id")[:250] limited = True if not confirm.is_valid(): for unit in matching: unit.replacement = unit.target.replace(search_text, replacement) context.update( { "matching": matching, "search_query": search_text, "replacement": replacement, "form": form, "limited": limited, "confirm": ReplaceConfirmForm(matching), } ) return render(request, "replace.html", context) matching = confirm.cleaned_data["units"] with transaction.atomic(): for unit in matching.select_for_update(): if not request.user.has_perm("unit.edit", unit): continue unit.translate( request.user, unit.target.replace(search_text, replacement), unit.state, change_action=Change.ACTION_REPLACE, ) updated += 1 import_message( request, updated, _("Search and replace completed, no strings were updated."), ngettext( "Search and replace completed, %d string was updated.", "Search and replace completed, %d strings were updated.", updated, ), ) return redirect(obj)
def get_credits(request, project=None, component=None): """View for credits.""" if project is None: obj = None kwargs = {"translation__pk__gt": 0} elif component is None: obj = get_project(request, project) kwargs = {"translation__component__project": obj} else: obj = get_component(request, project, component) kwargs = {"translation__component": obj} form = ReportsForm(request.POST) if not form.is_valid(): show_form_errors(request, form) return redirect_param(obj or "home", "#reports") data = generate_credits( None if request.user.has_perm("reports.view", obj) else request.user, form.cleaned_data["start_date"], form.cleaned_data["end_date"], **kwargs) if form.cleaned_data["style"] == "json": return JsonResponse(data=data, safe=False) if form.cleaned_data["style"] == "html": start = "<table>" row_start = "<tr>" language_format = "<th>{0}</th>" translator_start = "<td><ul>" translator_format = '<li><a href="mailto:{0}">{1}</a> ({2})</li>' translator_end = "</ul></td>" row_end = "</tr>" mime = "text/html" end = "</table>" else: start = "" row_start = "" language_format = "* {0}\n" translator_start = "" translator_format = " * {1} <{0}> ({2})" translator_end = "" row_end = "" mime = "text/plain" end = "" result = [] result.append(start) for language in data: name, translators = language.popitem() result.append(row_start) result.append(language_format.format(name)) result.append(translator_start + "\n".join( translator_format.format(*t) for t in translators) + translator_end) result.append(row_end) result.append(end) return HttpResponse("\n".join(result), content_type="{0}; charset=utf-8".format(mime))
def search(request, project=None, component=None, lang=None): """Perform site-wide search on units.""" is_ratelimited = not check_rate_limit("search", request) search_form = SearchForm(request.user, request.GET) context = {"search_form": search_form} if component: obj = get_component(request, project, component) context["component"] = obj context["project"] = obj.project context["back_url"] = obj.get_absolute_url() elif project: obj = get_project(request, project) context["project"] = obj context["back_url"] = obj.get_absolute_url() else: obj = None context["back_url"] = None if lang: s_language = get_object_or_404(Language, code=lang) context["language"] = s_language if obj: if component: context["back_url"] = obj.translation_set.get( language=s_language).get_absolute_url() else: context["back_url"] = reverse("project-language", kwargs={ "project": project, "lang": lang }) else: context["back_url"] = s_language.get_absolute_url() if not is_ratelimited and request.GET and search_form.is_valid(): # Filter results by ACL if component: units = Unit.objects.filter(translation__component=obj) elif project: units = Unit.objects.filter(translation__component__project=obj) else: units = Unit.objects.filter( translation__component__project_id__in=request.user. allowed_project_ids) units = units.search(search_form.cleaned_data.get("q", "")).distinct() if lang: units = units.filter(translation__language=context["language"]) units = get_paginator(request, units.order()) context["show_results"] = True context["page_obj"] = units context["title"] = _("Search for %s") % (search_form.cleaned_data["q"]) context["query_string"] = search_form.urlencode() context["search_query"] = search_form.cleaned_data["q"] elif is_ratelimited: messages.error(request, _("Too many search queries, please try again later.")) elif request.GET: messages.error(request, _("Invalid search query!")) show_form_errors(request, search_form) return render(request, "search.html", context)