Beispiel #1
0
 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])
Beispiel #2
0
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)
Beispiel #3
0
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)
Beispiel #4
0
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
Beispiel #5
0
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})
Beispiel #6
0
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
Beispiel #7
0
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
Beispiel #8
0
    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)
Beispiel #9
0
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
Beispiel #10
0
    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"))
Beispiel #11
0
    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']
Beispiel #12
0
 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"))
Beispiel #13
0
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
Beispiel #14
0
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
Beispiel #15
0
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
Beispiel #16
0
 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
Beispiel #17
0
    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.'))
Beispiel #18
0
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
Beispiel #19
0
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
Beispiel #20
0
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
Beispiel #21
0
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
Beispiel #22
0
def stats_start():
    text = u"""
    <p>%s</p>
    <ul>
    """ % _(
    'Calculating translation statistics, this will take a few minutes')
    return text
Beispiel #23
0
def stats_language(language):
    text = u"""
    <li>%s</li>
    """ % _('%(language)s is %(percent)d%% complete',
    {'language': language.localname(),
    'percent': language.translated_percentage()})
    return text
Beispiel #24
0
def syncdb():
    text = u"""
    <p>%s</p>
    """ % _('Creating missing database tables...')
    logging.info("Creating missing database tables")
    call_command('syncdb', interactive=False)
    return text
Beispiel #25
0
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
Beispiel #26
0
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.")})
Beispiel #27
0
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
Beispiel #29
0
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)
Beispiel #30
0
    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)
Beispiel #31
0
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)
Beispiel #32
0
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])
Beispiel #33
0
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)
Beispiel #34
0
    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)
Beispiel #35
0
    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
Beispiel #37
0
        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')
            )
Beispiel #38
0
 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
Beispiel #39
0
 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
Beispiel #40
0
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)
Beispiel #41
0
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"))
Beispiel #42
0
    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
Beispiel #43
0
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
Beispiel #44
0
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
Beispiel #45
0
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']),
    })
Beispiel #46
0
 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
Beispiel #47
0
 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")))
Beispiel #48
0
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()
    }
Beispiel #49
0
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
Beispiel #50
0
    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
Beispiel #51
0
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
Beispiel #52
0
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
Beispiel #53
0
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,
    })
Beispiel #54
0
    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)
Beispiel #55
0
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
Beispiel #56
0
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
Beispiel #57
0
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
Beispiel #58
0
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
Beispiel #59
0
 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.'))
Beispiel #60
0
 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()