def clean(self): project = self.cleaned_data.get("project") language = self.cleaned_data.get("language") if project and language: mapped_code = self.cleaned_data["fs_code"] mapping = project.config.get("pootle.core.lang_mapping", {}) if mapped_code: tps = project.translationproject_set.all() lang_codes = tps.values_list("language__code", flat=True) bad_fs_code = ( (mapped_code in mapping.keys() and not mapping.get(mapped_code) == language.code) or mapped_code in lang_codes) if bad_fs_code: self.errors["fs_code"] = self.error_class( [_("Unable to add mapped code '%(mapped_code)s' for " "language '%(code)s'. Mapped filesystem codes must " "be unique and cannot be in use with an existing " "Translation Project") % dict(mapped_code=mapped_code, code=language.code)]) if language.code in mapping.keys(): self.errors["language"] = self.error_class( [_("Unable to add language '%s'. " "Another language is already mapped to this code") % language.code])
def handle_suggestion_comment(request, suggestion, unit, comment, action): kwargs = { 'comment': comment, 'user': request.user, } comment_form = UnsecuredCommentForm(suggestion, kwargs) if comment_form.is_valid(): comment_form.save() if (action not in ("accepted", "rejected") or not settings.POOTLE_EMAIL_FEEDBACK_ENABLED): return ctx = { 'suggestion_id': suggestion.id, 'unit_url': request.build_absolute_uri(unit.get_translate_url()), 'comment': comment, } if action == "rejected": message = loader.render_to_string( 'editor/email/suggestion_rejected_with_comment.txt', ctx) subject = _(u"Suggestion rejected with comment") else: message = loader.render_to_string( 'editor/email/suggestion_accepted_with_comment.txt', ctx) subject = _(u"Suggestion accepted with comment") send_mail(subject, message, from_email=None, recipient_list=[suggestion.user.email], fail_silently=True)
def render_pager(pager): """Render a pager block with next and previous links""" if not pager.has_other_pages(): return "" result = '<ul class="pager">' if pager.has_previous(): result += '<li><a href="?page=1" class="nth-link">%s</a></li>' % \ _('First') result += ('<li><a href="?page=%d" class="prevnext-link">%s</a>' '</li>' % (pager.previous_page_number(), _('Previous'))) start = max(1, pager.number - 4) end = min(pager.paginator.num_pages, pager.number + 4) if start > 1: result += '<li>...</li>' for i in range(start, end+1): if i == pager.number: result += '<li><span class="current-link">%s</span></li>' % i else: result += ('<li><a href="?page=%d" class="number-link">%d</a>' '</li>' % (i, i)) if end < pager.paginator.num_pages: result += '<li>...</li>' if pager.has_next(): result += ('<li><a href="?page=%d" class="prevnext-link">%s</a>' '</li>' % (pager.next_page_number(), _('Next'))) result += '<li><a href="?page=%d" class="nth-link">%s</a></li>' % \ (pager.paginator.num_pages, _('Last (%d)', pager.paginator.num_pages)) result += '</ul>' return mark_safe(result)
def profile_user(request, profile): context = dict(request=request, profile=profile) context['request_user_is_manager'] = ( request.user.has_manager_permissions()) if profile.user.is_anonymous: context["bio"] = _( "Some translations are provided by anonymous volunteers. " "These are registered under this special meta-account.") elif profile.user.is_system(): context["bio"] = _( "Some translations are imported from external files. " "These are registered under this special meta-account.") else: if request.user == profile.user: context["can_edit_profile"] = True context["should_edit_profile"] = ( not profile.user.has_contact_details or not profile.user.bio) if context["should_edit_profile"]: context["edit_profile_message"] = mark_safe( _("Show others who you are, tell about yourself<br/>" "and make your public profile look gorgeous!")) context["user_title"] = _( "You can set or change your avatar image at www.gravatar.com") if profile.user.bio: context["bio"] = profile.user.bio return context
def get_units(request, **kwargs_): """Gets source and target texts and its metadata. :return: A JSON-encoded string containing the source and target texts grouped by the store they belong to. The optional `count` GET parameter defines the chunk size to consider. The user's preference will be used by default. When the `initial` GET parameter is present, a sorted list of the result set ids will be returned too. """ search_form = UnitSearchForm(request.GET, user=request.user) if not search_form.is_valid(): errors = search_form.errors.as_data() if "path" in errors: for error in errors["path"]: if error.code == "max_length": raise Http400(_('Path too long.')) elif error.code == "required": raise Http400(_('Arguments missing.')) raise Http404(forms.ValidationError(search_form.errors).messages) total, start, end, units_qs = search_backend.get(Unit)( request.user, **search_form.cleaned_data).search() return JsonResponse( {'start': start, 'end': end, 'total': total, 'unitGroups': GroupedResults(units_qs).data})
def check_canonical_url(app_configs=None, **kwargs): from django.conf import settings from django.contrib.sites.models import Site errors = [] no_canonical_error = checks.Critical( _("No canonical URL provided and default site set to example.com."), hint=_( "Set the `POOTLE_CANONICAL_URL` in settings or update the " "default site if you are using django.contrib.sites."), id="pootle.C018") localhost_canonical_warning = checks.Warning( _("Canonical URL is set to http://localhost."), hint=_( "Set the `POOTLE_CANONICAL_URL` to an appropriate value for your " "site or leave it empty if you are using `django.contrib.sites`."), id="pootle.W020") try: contrib_site = Site.objects.get_current() except (ProgrammingError, OperationalError): if "django.contrib.sites" in settings.INSTALLED_APPS: return [] contrib_site = None uses_sites = ( not settings.POOTLE_CANONICAL_URL and contrib_site) if uses_sites: site = Site.objects.get_current() if site.domain == "example.com": errors.append(no_canonical_error) elif not settings.POOTLE_CANONICAL_URL: errors.append(no_canonical_error) elif settings.POOTLE_CANONICAL_URL == "http://localhost": errors.append(localhost_canonical_warning) return errors
def check_pootle_fs_working_dir(app_configs=None, **kwargs): import os from django.conf import settings missing_setting_error = checks.Critical( _("POOTLE_FS_WORKING_PATH setting is not set."), id="pootle.C019", ) missing_directory_error = checks.Critical( _("Path pointed to by POOTLE_FS_WORKING_PATH doesn't exist."), hint=_("Create the directory pointed by `POOTLE_FS_WORKING_PATH` " "setting."), id="pootle.C020", ) not_writable_directory_error = checks.Critical( _("Path pointed to by POOTLE_FS_WORKING_PATH is not writable by " "Pootle."), hint=_("Add the write permission to the `POOTLE_FS_WORKING_PATH` " "directory using 'chmod +w'"), id="pootle.C021", ) errors = [] if not settings.POOTLE_FS_WORKING_PATH: errors.append(missing_setting_error) elif not os.path.exists(settings.POOTLE_FS_WORKING_PATH): errors.append(missing_directory_error) elif not os.access(settings.POOTLE_FS_WORKING_PATH, os.W_OK): errors.append(not_writable_directory_error) return errors
def description(self): params = { 'author': self.user.author_link } sugg_accepted_desc = _(u'Accepted suggestion from %(author)s', params) sugg_rejected_desc = _(u'Rejected suggestion from %(author)s', params) if self.comment: params.update({ 'comment': format_html(u'<span class="comment">{}</span>', self.comment), }) sugg_accepted_desc = _( u'Accepted suggestion from %(author)s ' u'with comment: %(comment)s', params ) sugg_rejected_desc = _( u'Rejected suggestion from %(author)s ' u'with comment: %(comment)s', params ) description_dict = { SubmissionTypes.SUGG_ADD: _(u'Added suggestion'), SubmissionTypes.SUGG_ACCEPT: sugg_accepted_desc, SubmissionTypes.SUGG_REJECT: sugg_rejected_desc, } return description_dict.get(self.submission_type, None)
def update_tables_22000(): text = u""" <p>%s</p> """ % _('Updating existing database tables...') logging.info("Updating existing database tables") from south.db import db # For the sake of South bug 313, we set the default for these fields here: # See http://south.aeracode.org/ticket/313 from pootle_store.models import Suggestion table_name = Suggestion._meta.db_table field = Suggestion._meta.get_field('translator_comment_f') field.default = u'' db.add_column(table_name, field.name, field) from pootle_language.models import Language table_name = Language._meta.db_table field = Language._meta.get_field('description') field.default = u'' db.add_column(table_name, field.name, field) from pootle_translationproject.models import TranslationProject table_name = TranslationProject._meta.db_table field = TranslationProject._meta.get_field('description') field.default = u'' db.add_column(table_name, field.name, field) from pootle_project.models import Project table_name = Project._meta.db_table field = Project._meta.get_field('report_target') field.default = u'' db.add_column(table_name, field.name, field) table_name = QualityCheck._meta.db_table field = QualityCheck._meta.get_field('category') db.add_column(table_name, field.name, field) from pootle_statistics.models import Submission table_name = Submission._meta.db_table for field_name in ('unit', 'field', 'type', 'old_value', 'new_value'): field = Submission._meta.get_field(field_name) db.add_column(table_name, field.name, field) from pootle_store.models import Unit table_name = Unit._meta.db_table for field_name in ('submitted_by', 'submitted_on', 'commented_by', 'commented_on'): field = Unit._meta.get_field(field_name) db.add_column(table_name, field.name, field) text += """ <p>%s</p> """ % _('Removing quality checks, will be recalculated on demand...') logging.info("Fixing quality checks") flush_quality_checks() save_pootle_version(22000) return text
def context(self): if self.submission.new_value: return dict( value=self.submission.new_value, sidetitle=_(u"Comment:"), comment=True) return dict(description=_(u"Removed comment"))
def __init__(self, *args, **kwargs): self.unit = kwargs.pop('unit', None) super(ReportForm, self).__init__(*args, **kwargs) self.fields['body'].label = _(u'Question or comment') body_placeholder = _('Please enter your question or comment') self.fields['body'].widget.attrs['placeholder'] = body_placeholder del self.fields['email_subject']
def clean(self): if any(self.errors): return fs_counter = Counter([v["fs_code"] for v in self.cleaned_data if v]) if set(fs_counter.values()) != set([1]): raise forms.ValidationError(_("Filesystem language codes must be unique")) pootle_counter = Counter([v["pootle_code"] for v in self.cleaned_data if v]) if set(pootle_counter.values()) != set([1]): raise forms.ValidationError(_("Pootle language mappings must be unique"))
def check_db_transaction_hooks(app_configs=None, **kwargs): from django.conf import settings errors = [] if settings.DATABASES['default']['ENGINE'].startswith("transaction_hooks"): errors.append(checks.Critical( _("Database connection uses transaction_hooks."), hint=_("Set the DATABASES['default']['ENGINE'] to use a Django " "backend from django.db.backends."), id="pootle.C006", )) return errors
def get_translation_states(path_obj): states = [] def make_dict(state, title, filter_url=True): filter_name = filter_url and state or None return {"state": state, "title": title, "url": path_obj.get_translate_url(state=filter_name)} states.append(make_dict("total", _("Total"), False)) states.append(make_dict("translated", _("Translated"))) states.append(make_dict("fuzzy", _("Fuzzy"))) states.append(make_dict("untranslated", _("Untranslated"))) return states
def check_db_transaction_on_commit(app_configs=None, **kwargs): from django.db import connection errors = [] try: connection.on_commit except AttributeError: errors.append(checks.Critical( _("Database connection does not implement on_commit."), hint=_("Set the DATABASES['default']['ENGINE'] to use a backend " "from transaction_hooks.backends."), id="pootle.C006", )) return errors
def teams_and_roles(self): teams = {} for team, permissions in self.teams_and_permissions.items(): teams[team] = dict(name=self.site_languages.languages[team]) if "administrate" in permissions: teams[team]["role"] = _("Admin") elif "review" in permissions: teams[team]["role"] = _("Reviewer") elif "translate" in permissions: teams[team]["role"] = _("Translator") else: teams[team]["role"] = "" return teams
def clean(self): """Fail validation if: - URL and body are blank - Current virtual path exists in other page models """ if not self.url and not self.body: # Translators: 'URL' and 'content' refer to form fields. raise ValidationError(_('URL or content must be provided.')) pages = [p.objects.filter(Q(virtual_path=self.virtual_path), ~Q(pk=self.pk),).exists() for p in AbstractPage.__subclasses__()] if True in pages: raise ValidationError(_(u'Virtual path already in use.'))
def profile_score(request, profile): context = dict(profile=profile) top_lang = profile.scores.top_language context["own_profile"] = request.user == profile.user if top_lang and not top_lang[0] == -1 and top_lang[1]: if context["own_profile"]: score_tweet_content = _( "My current score at %(pootle_title)s is %(score)s", dict(pootle_title=settings.POOTLE_TITLE, score=profile.scores.public_score)) context["score_tweet_message"] = _("Tweet this!") context["score_tweet_link"] = ( "https://twitter.com/share?text=%s" % urllib.quote_plus(score_tweet_content.encode("utf8"))) return context
def check_unsupported_python(app_configs=None, **kwargs): errors = [] if sys.version_info >= (3, 0): errors.append(checks.Critical( _("Pootle does not yet support Python 3."), hint=_("Use a Python 2.7 virtualenv."), id="pootle.C023", )) if sys.version_info < (2, 7): errors.append(checks.Critical( _("Pootle no longer supports Python versions older than 2.7"), hint=_("Use a Python 2.7 virtualenv."), id="pootle.C024", )) return errors
def rq_stats(): queue = get_queue() failed_queue = get_failed_queue() try: workers = Worker.all(queue.connection) except ConnectionError: return None num_workers = len(workers) is_running = len(queue.connection.smembers(Worker.redis_workers_keys)) > 0 if is_running: # Translators: this refers to the status of the background job worker status_msg = ungettext('Running (%d worker)', 'Running (%d workers)', num_workers) % num_workers else: # Translators: this refers to the status of the background job worker status_msg = _('Stopped') result = { 'job_count': queue.count, 'failed_job_count': failed_queue.count, 'is_running': is_running, 'status_msg': status_msg, } return result
def update_tables_21000(): text = u""" <p>%s</p> """ % _('Updating existing database tables...') logging.info("Updating existing database tables") from south.db import db #raise ImportError table_name = Store._meta.db_table field = Store._meta.get_field('state') db.add_column(table_name, field.name, field) db.create_index(table_name, (field.name,)) field = Store._meta.get_field('translation_project') field.null = True db.add_column(table_name, field.name, field) db.create_index(table_name, (field.name + '_id',)) table_name = Project._meta.db_table field = Project._meta.get_field('directory') field.null = True db.add_column(table_name, field.name, field) field = Project._meta.get_field('source_language') try: en = Language.objects.get(code='en') except Language.DoesNotExist: # we can't allow translation project detection to kick in yet so let's create en manually en = Language(code='en', fullname='English', nplurals=2, pluralequation="(n != 1)") en.directory = Directory.objects.root.get_or_make_subdir(en.code) en.save_base(raw=True) field.default = en.id db.add_column(table_name, field.name, field) db.create_index(table_name, (field.name + '_id',)) # We shouldn't do save_pootle_version(21000) yet - more to do below return text
def stats_start(): text = u""" <p>%s</p> <ul> """ % _( 'Calculating translation statistics, this will take a few minutes') return text
def stats_language(language): text = u""" <li>%s</li> """ % _('%(language)s is %(percent)d%% complete', {'language': language.localname(), 'percent': language.translated_percentage()}) return text
def syncdb(): text = u""" <p>%s</p> """ % _('Creating missing database tables...') logging.info("Creating missing database tables") call_command('syncdb', interactive=False) return text
def stats_project(project): text = u""" <li>%s</li> """ % _('Project %(project)s is %(percent)d%% complete', {'project': project.fullname, 'percent': project.translated_percentage()}) return text
def save_comment(request, unit): """Stores a new comment for the given ``unit``. :return: If the form validates, the cleaned comment is returned. An error message is returned otherwise. """ # Update current unit instance's attributes unit.commented_by = request.user unit.commented_on = timezone.now().replace(microsecond=0) language = request.translation_project.language form = unit_comment_form_factory(language)(request.POST, instance=unit, request=request) if form.is_valid(): form.save() user = request.user directory = unit.store.parent ctx = { 'unit': unit, 'language': language, 'cantranslate': check_user_permission(user, 'translate', directory), 'cansuggest': check_user_permission(user, 'suggest', directory), } t = loader.get_template('editor/units/xhr_comment.html') return JsonResponse({'comment': t.render(ctx, request)}) return JsonResponseBadRequest({'msg': _("Comment submission failed.")})
def update_qualitychecks_21040(): text = """ <p>%s</p> """ % _('Removing quality checks, will be recalculated on demand...') logging.info("Fixing quality checks") flush_quality_checks() return text
def footer(): text = """ <p>%(endmsg)s</p> <div><script>setTimeout("location.reload()", 10000)</script></div> </body></html> """ % { 'endmsg': _('Initialized database, you will be redirected to the front page in 10 seconds') } return text
def reject_suggestion(request, unit, suggid, **kwargs_): try: suggestion = unit.suggestion_set.get(id=suggid) except ObjectDoesNotExist: raise Http404 # In order to be able to reject a suggestion, users have to either: # 1. Have `review` rights, or # 2. Be the author of the suggestion being rejected has_permission = ( check_permission('review', request) or (not request.user.is_anonymous() and request.user == suggestion.user)) if not has_permission: raise PermissionDenied( _('Insufficient rights to access review mode.')) review.get(Suggestion)( [suggestion], request.user).reject(QueryDict(request.body).get("comment")) json = { 'udbid': unit.id, 'sugid': suggid, 'user_score': request.user.public_score, } return JsonResponse(json)
def dispatch(self, request, *args, **kwargs): if not request.user.is_superuser: msg = _('You do not have rights to administer Pootle.') raise PermissionDenied(msg) return super(SuperuserRequiredMixin, self).dispatch(request, *args, **kwargs)
def profile_social(profile): links = [] if profile.user.website: links.append( dict(url=profile.user.website, icon="icon-user-website", text=_("My Website"))) if profile.user.twitter: links.append( dict(url=profile.user.twitter_url, icon="icon-user-twitter", text="@%s" % profile.user.twitter)) if profile.user.linkedin: links.append( dict(url=profile.user.linkedin, icon="icon-user-linkedin", text=_("My LinkedIn Profile"))) return dict(social_media_links=links)
class LegalPage(AbstractPage): display_name = _('Legal Page') def localized_title(self): return _(self.title) def get_edit_url(self): return reverse('pootle-staticpages-edit', args=['legal', self.pk])
class AbstractFormat(models.Model): class Meta(object): abstract = True name = models.CharField( _('Format name'), max_length=30, unique=True, db_index=True) title = models.CharField( _('Format title'), max_length=255, db_index=True) enabled = models.BooleanField( verbose_name=_('Enabled'), default=True) monolingual = models.BooleanField( verbose_name=_('Monolingual format'), default=False)
def process_formset(self): formset = self.get_formset(self.request.POST) if formset.is_valid(): formset.save() for tp in formset.new_objects: messages.add_message( self.request, messages.INFO, _("Translation project (%s) has been created. We are " "now updating its files from file templates." % tp)) for tp in formset.deleted_objects: messages.add_message( self.request, messages.INFO, _("Translation project (%s) has been deleted" % tp)) else: for form in formset: for error in form.errors.values(): messages.add_message(self.request, messages.ERROR, error)
def clean(self): """Fail validation if: - URL and body are blank - Current virtual path exists in other page models """ if not self.url and not self.body: # Translators: 'URL' and 'content' refer to form fields. raise ValidationError(_('URL or content must be provided.')) pages = [ p.objects.filter( Q(virtual_path=self.virtual_path), ~Q(pk=self.pk), ).exists() for p in AbstractPage.__subclasses__() ] if True in pages: raise ValidationError(_(u'Virtual path already in use.'))
def stats_language(language): text = u""" <li>%s</li> """ % _( '%(language)s is %(percent)d%% complete', { 'language': language.localname(), 'percent': language.translated_percentage() }) return text
def clean_mt_similarity(self): value = self.cleaned_data['mt_similarity'] if 0 <= value <= 1 or value is None: return value raise forms.ValidationError( _('Value of `mt_similarity` should be in in the [0..1] range') )
def get_context_data(self, **kwargs): ctx = super(ContactFormView, self).get_context_data(**kwargs) # Provide the form action URL to use in the template that renders the # contact dialog. ctx.update({ 'contact_form_title': _('Contact Us'), 'contact_form_url': reverse('pootle-contact-xhr'), }) return ctx
def get_context_data(self, **kwargs): ctx = super(ReportFormView, self).get_context_data(**kwargs) # Provide the form action URL to use in the template that renders the # contact dialog. ctx.update({ 'contact_form_title': _('Report problem with string'), 'contact_form_url': reverse('pootle-contact-report-error'), }) return ctx
def _get_suggestion_description(submission): user_url = reverse( 'pootle-user-profile', args=[submission["suggestion__user__username"]]) display_name = ( submission["suggestion__user__full_name"].strip() if submission["suggestion__user__full_name"].strip() else submission["suggestion__user__username"].strip()) params = { 'author': format_html(u'<a href="{}">{}</a>', user_url, display_name) } Comment = get_comment_model() try: comment = Comment.objects.for_model(Suggestion).get( object_pk=submission["suggestion_id"], ) except Comment.DoesNotExist: comment = None else: params.update({ 'comment': format_html(u'<span class="comment">{}</span>', comment.comment), }) if comment: sugg_accepted_desc = _( u'Accepted suggestion from %(author)s with comment: %(comment)s', params ) sugg_rejected_desc = _( u'Rejected suggestion from %(author)s with comment: %(comment)s', params ) else: sugg_accepted_desc = _(u'Accepted suggestion from %(author)s', params) sugg_rejected_desc = _(u'Rejected suggestion from %(author)s', params) return { SubmissionTypes.SUGG_ADD: _(u'Added suggestion'), SubmissionTypes.SUGG_ACCEPT: sugg_accepted_desc, SubmissionTypes.SUGG_REJECT: sugg_rejected_desc, }.get(submission['type'], None)
def import_file(f, user=None): ttk = getclass(f)(f.read()) if not hasattr(ttk, "parseheader"): raise UnsupportedFiletypeError( _( "Unsupported filetype '%s', only PO " "files are supported at this time\n", f.name)) header = ttk.parseheader() pootle_path = header.get("X-Pootle-Path") if not pootle_path: raise MissingPootlePathError( _("File '%s' missing X-Pootle-Path " "header\n", f.name)) rev = header.get("X-Pootle-Revision") if not rev or not rev.isdigit(): raise MissingPootleRevError( _("File '%s' missing or invalid " "X-Pootle-Revision header\n", f.name)) rev = int(rev) try: store = Store.objects.get(pootle_path=pootle_path) except Store.DoesNotExist as e: raise FileImportError( _( "Could not create '%(filename)s'. Missing " "Project/Language? (%(error)s)", dict(filename=f.name, error=e))) tp = store.translation_project allow_add_and_obsolete = ( (tp.project.checkstyle == 'terminology' or tp.is_template_project) and check_user_permission(user, 'administrate', tp.directory)) try: store.update(store=ttk, user=user, submission_type=SubmissionTypes.UPLOAD, store_revision=rev, allow_add_and_obsolete=allow_add_and_obsolete) except Exception as e: # This should not happen! logger.error("Error importing file: %s", str(e)) raise FileImportError(_("There was an error uploading your file"))
def clean_linkedin(self): url = self.cleaned_data['linkedin'] if url != '': parsed = urlparse.urlparse(url) if 'linkedin.com' not in parsed.netloc or parsed.path == '/': raise forms.ValidationError( _('Please enter a valid LinkedIn user profile URL.') ) return url
def update_toolkit_version(): text = """ <p>%s</p> """ % _('Removing quality checks, will be recalculated on demand...') logging.info("New Translate Toolkit version, flushing quality checks") flush_quality_checks() save_toolkit_version() return text
def check_duplicate_emails(app_configs=None, **kwargs): from accounts.utils import get_duplicate_emails errors = [] try: if len(get_duplicate_emails()): errors.append( checks.Warning( _("There are user accounts with duplicate emails. This " "will not be allowed in Pootle 2.8."), hint=_("Try using 'pootle find_duplicate_emails', and " "then update user emails with 'pootle " "update_user_email username email'. You might also " "want to consider using pootle merge_user or " "purge_user commands"), id="pootle.W017")) except (OperationalError, ProgrammingError): # no accounts set up - most likely in a test pass return errors
def preview_content(request): """Returns content rendered based on the configured markup settings.""" if 'text' not in request.POST: return JsonResponseBadRequest({ 'msg': _('Text is missing'), }) return JsonResponse({ 'rendered': apply_markup_filter(request.POST['text']), })
def clean_fs_mapping(self): fs_mapping = self.cleaned_data["fs_mapping"].strip() bad = (not fs_mapping.startswith("/") or not fs_mapping.endswith(".<ext>") or "<language_code>" not in fs_mapping) if bad: raise forms.ValidationError( _('Path mapping must start with "/", end with ".<ext>", and ' 'contain "<language_code>"')) return fs_mapping
def clean(self): if any(self.errors): return no_role = (self.cleaned_data.get("new_member") and not self.cleaned_data.get("role")) if no_role: self.add_error( "role", forms.ValidationError( _("Role is required when adding a new member")))
def get_parent(path_obj): """Retrieves a representation of the parent object. :param path_obj: either a `Directory` or Store` instance. """ parent_dir = path_obj.parent if parent_dir.is_project(): return None if parent_dir.is_language(): label = _('Back to language') else: label = _('Back to parent folder') return { 'title': label, 'href': parent_dir.get_absolute_url() }
def profile_ranking(request, profile): context = dict(request=request, profile=profile) top_lang = profile.scores.top_language context["own_profile"] = request.user == profile.user if top_lang and not top_lang[0] == -1 and top_lang[1]: context["ranking_text"] = _( "#%s contributor in %s in the last 30 days" % (top_lang[0], top_lang[1].name)) if context["own_profile"]: ranking_tweet_content = _( "I am #%s contributor in %s in the last 30 days at %s!" % (top_lang[0], top_lang[1].name, settings.POOTLE_TITLE)) context["ranking_tweet_link"] = ( "https://twitter.com/share?text=%s" % urllib.quote_plus(ranking_tweet_content.encode("utf8"))) context["ranking_tweet_link_text"] = _("Tweet this!") else: context["no_ranking_text"] = _("No contributions in the last 30 days") return context
def get_form(self, *args, **kwargs): form = super(UserSettingsView, self).get_form(*args, **kwargs) form.fields['alt_src_langs'].help_text = None form.fields['alt_src_langs'].widget.attrs['class'] = \ 'js-select2 select2-multiple' form.fields['alt_src_langs'].widget.attrs['data-placeholder'] = \ _('Select one or more languages') return form
def pluralize_sugg(sugg): unit = sugg.unit if not unit.hasplural(): return [(0, sugg.target, None)] forms = [] for i, target in enumerate(sugg.target.strings): forms.append((i, target, _('Plural Form %d', i))) return forms
class LanguageSuggestionAdminView(PootleLanguageAdminFormView): template_name = 'languages/admin/language_team_suggestions.html' form_class = LanguageSuggestionAdminForm success_url_pattern = "pootle-language-admin-suggestions" formtable_columns = (_("Unit"), _("State"), _("Source"), _("Suggestion"), _("Suggested by"), _("Suggested at"), _("Project")) @property def default_form_kwargs(self): return dict(page_no=1, results_per_page=10) def add_success_message(self, form): count = (form.fields["suggestions"].queryset.count() if form.cleaned_data["select_all"] else len( form.cleaned_data["suggestions"])) reject_and_notify = (form.cleaned_data["actions"] == "reject" and form.cleaned_data["comment"]) accept_and_notify = (form.cleaned_data["actions"] == "accept" and form.cleaned_data["comment"]) if reject_and_notify: message = _( "Rejected %s suggestions with comment. Users will be notified", count) elif accept_and_notify: message = _( "Accepted %s suggestions with comment. Users will be notified", count) elif form.cleaned_data["actions"] == "reject": message = _("Rejected %s suggestions", count) else: message = _("Accepted %s suggestions", count) messages.success(self.request, message) def get_context_data(self, **kwargs): context = super(LanguageSuggestionAdminView, self).get_context_data(**kwargs) context["page"] = "admin-suggestions" context["language"] = self.language form = context["form"] form.is_valid() batch = form.batch() form.fields["suggestions"].choices = [ (item.id, SuggestionDisplay(item)) for item in batch.object_list ] context["formtable"] = SuggestionFormtable( form, columns=self.formtable_columns, page=batch, messages=messages.get_messages(self.request)) return context def get_form_kwargs(self): kwargs = super(LanguageSuggestionAdminView, self).get_form_kwargs() if not self.request.POST: kwargs["data"] = self.default_form_kwargs kwargs["user"] = self.request.user return kwargs
def get_uids(request): """Gets all uids based on search criteria :return: A JSON-encoded string containing the sorted list of unit IDs (uids) """ search_form = UnitSearchForm(request.GET, user=request.user) if not search_form.is_valid(): errors = search_form.errors.as_data() if "path" in errors: for error in errors["path"]: if error.code == "max_length": raise Http400(_('Path too long.')) elif error.code == "required": raise Http400(_('Arguments missing.')) raise Http404(forms.ValidationError(search_form.errors).messages) begin, end, total, uids = search_backend.get(Unit)( request.user, **search_form.cleaned_data ).get_uids() last_store_id = None uid_groups = [] group = [] for uid, store_id in uids: if not store_id == last_store_id: if len(group) > 0: uid_groups.append(group) group = [] last_store_id = store_id group.append(uid) if len(group) > 0: uid_groups.append(group) return JsonResponse({ 'begin': begin, 'end': end, 'total': total, 'uids': uid_groups, })
def dispatch(self, *args, **kwargs): user = self.request.user url_field_value = kwargs[self.test_user_field] field_value = getattr(user, self.test_user_field, '') can_access = user.is_superuser or \ unicode(field_value) == url_field_value if not can_access: raise PermissionDenied(_('You cannot access this page.')) return super(TestUserFieldMixin, self).dispatch(*args, **kwargs)
def check_revision(app_configs=None, **kwargs): from pootle.core.models import Revision from pootle_store.models import Unit errors = [] revision = Revision.get() try: max_revision = Unit.max_revision() except (OperationalError, ProgrammingError): return errors if revision is None or revision < max_revision: errors.append( checks.Critical( _("Revision is missing or has an incorrect value."), hint=_( "Run `revision --restore` to reset the revision counter."), id="pootle.C016", )) return errors
def footer(): text = """ <p>%(endmsg)s</p> <div><script>setTimeout("location.reload()", 10000)</script></div> </body></html> """ % { 'endmsg': _('Pootle initialized the database. You will be redirected to the front page in 10 seconds.' ) } return text
def check_email_server_is_alive(app_configs=None, **kwargs): from django.conf import settings errors = [] if settings.ZING_SIGNUP_ENABLED or settings.ZING_CONTACT_EMAIL.strip(): from django.core.mail import get_connection connection = get_connection() try: connection.open() except Exception: errors.append(checks.Warning( _("Email server is not available."), hint=_("Review your email settings and make sure your email " "server is working."), id="pootle.W004", )) else: connection.close() return errors
def check_users(app_configs=None, **kwargs): from django.contrib.auth import get_user_model errors = [] User = get_user_model() try: admin_user = User.objects.get(username='******') except (User.DoesNotExist, OperationalError, ProgrammingError): pass else: if admin_user.check_password('admin'): errors.append(checks.Warning( _("The default 'admin' user still has a password set to " "'admin'."), hint=_("Remove the 'admin' user or change its password."), id="pootle.W016", )) return errors
def send_confirmation_mail(self, *args, **kwargs): try: super(PootleAccountAdapter, self).send_confirmation_mail(*args, **kwargs) except Exception: logger.exception("ERROR: Sign up failed. Couldn't sent " "confirmation email.") raise RuntimeError( _('Some problem happened when tried to send ' 'the confirmation email. Please try again ' 'later.'))
def clean(self): self_review = (self.request_user == self.target_object.user and self.cleaned_data.get("action") == "reject") permission = ("view" if self_review else "review") has_permission = check_user_permission( self.request_user, permission, self.target_object.unit.store.parent) if not has_permission: raise forms.ValidationError( _("Insufficient rights to access this page.")) if not self.errors: super(SuggestionReviewForm, self).clean()