Example #1
0
    def test_not_counting_outdated(self):
        """Out-of-date translations shouldn't count as "done".

        "Out-of-date" can mean either moderately or majorly out of date. The
        only thing we don't care about is typo-level outdatedness.

        """
        t = TranslatedRevisionFactory(document__locale="de", is_approved=True)
        overview = l10n_overview_rows("de")
        eq_(1, overview["top-20"]["numerator"])
        eq_(1, overview["top-50"]["numerator"])
        eq_(1, overview["top-100"]["numerator"])
        eq_(1, overview["all"]["numerator"])

        # Update the parent with a typo-level revision:
        ApprovedRevisionFactory(
            document=t.document.parent, significance=TYPO_SIGNIFICANCE, is_ready_for_localization=True
        )
        # Assert it still shows up in the numerators:
        overview = l10n_overview_rows("de")
        eq_(1, overview["top-20"]["numerator"])
        eq_(1, overview["top-50"]["numerator"])
        eq_(1, overview["top-100"]["numerator"])
        eq_(1, overview["all"]["numerator"])

        # Update the parent with a medium-level revision:
        ApprovedRevisionFactory(
            document=t.document.parent, significance=MEDIUM_SIGNIFICANCE, is_ready_for_localization=True
        )
        # Assert it no longer shows up in the numerators:
        overview = l10n_overview_rows("de")
        eq_(0, overview["all"]["numerator"])
        eq_(0, overview["top-20"]["numerator"])
        eq_(0, overview["top-50"]["numerator"])
        eq_(0, overview["top-100"]["numerator"])
Example #2
0
    def test_by_product(self):
        """Test the product filtering of the overview."""
        p = ProductFactory(title='Firefox', slug='firefox')
        t = TranslatedRevisionFactory(is_approved=True, document__locale='de')

        eq_(0, l10n_overview_rows('de', product=p)['all']['numerator'])
        eq_(0, l10n_overview_rows('de', product=p)['all']['denominator'])

        t.document.parent.products.add(p)

        eq_(1, l10n_overview_rows('de', product=p)['all']['numerator'])
        eq_(1, l10n_overview_rows('de', product=p)['all']['denominator'])
Example #3
0
    def test_counting_unready_templates(self):
        """Templates without a ready-for-l10n rev don't count"""
        # Make a template with an approved but not-ready-for-l10n rev:
        d = TemplateDocumentFactory(is_localizable=True)
        r = ApprovedRevisionFactory(document=d, is_ready_for_localization=False)

        # It shouldn't show up in the total:
        eq_(0, l10n_overview_rows("de")["templates"]["denominator"])

        r.is_ready_for_localization = True
        r.save()
        eq_(1, l10n_overview_rows("de")["templates"]["denominator"])
Example #4
0
    def test_by_product(self):
        """Test the product filtering of the overview."""
        p = product(title="Firefox", slug="firefox", save=True)
        t = translated_revision(is_approved=True, save=True)

        eq_(0, l10n_overview_rows("de", product=p)["all"]["numerator"])
        eq_(0, l10n_overview_rows("de", product=p)["all"]["denominator"])

        t.document.parent.products.add(p)

        eq_(1, l10n_overview_rows("de", product=p)["all"]["numerator"])
        eq_(1, l10n_overview_rows("de", product=p)["all"]["denominator"])
    def test_by_product(self):
        """Test the product filtering of the overview."""
        p = product(title='Firefox', slug='firefox', save=True)
        t = translated_revision(is_approved=True, save=True)

        eq_(0, l10n_overview_rows('de', product=p)['all']['numerator'])
        eq_(0, l10n_overview_rows('de', product=p)['all']['denominator'])

        t.document.parent.products.add(p)

        eq_(1, l10n_overview_rows('de', product=p)['all']['numerator'])
        eq_(1, l10n_overview_rows('de', product=p)['all']['denominator'])
Example #6
0
    def test_counting_unready_docs(self):
        """Docs without a ready-for-l10n rev shouldn't count in total."""
        # Make a doc with an approved but not-ready-for-l10n rev:
        d = DocumentFactory(is_localizable=True)
        r = ApprovedRevisionFactory(document=d, is_ready_for_localization=False)

        # It shouldn't show up in the total:
        eq_(0, l10n_overview_rows('de')['all']['denominator'])

        r.is_ready_for_localization = True
        r.save()
        eq_(1, l10n_overview_rows('de')['all']['denominator'])
Example #7
0
    def test_by_product(self):
        """Test the product filtering of the overview."""
        p = ProductFactory(title="Firefox", slug="firefox")
        t = TranslatedRevisionFactory(is_approved=True, document__locale="de")

        eq_(0, l10n_overview_rows("de", product=p)["all"]["numerator"])
        eq_(0, l10n_overview_rows("de", product=p)["all"]["denominator"])

        t.document.parent.products.add(p)

        eq_(1, l10n_overview_rows("de", product=p)["all"]["numerator"])
        eq_(1, l10n_overview_rows("de", product=p)["all"]["denominator"])
Example #8
0
    def test_templates_and_docs_disjunct(self):
        """Make sure templates aren't included in the All Articles count."""
        t = translated_revision(is_approved=True, save=True)
        # It shows up in All when it's a normal doc:
        eq_(1, l10n_overview_rows("de")["all"]["numerator"])
        eq_(1, l10n_overview_rows("de")["all"]["denominator"])

        t.document.parent.title = t.document.title = "Template:thing"
        t.document.parent.is_template = t.document.is_template = True
        t.document.parent.save()
        t.document.save()
        # ...but not when it's a template:
        eq_(0, l10n_overview_rows("de")["all"]["numerator"])
        eq_(0, l10n_overview_rows("de")["all"]["denominator"])
Example #9
0
    def test_templates_and_docs_disjunct(self):
        """Make sure templates aren't included in the All Articles count."""
        t = TranslatedRevisionFactory(document__locale="de", is_approved=True)
        # It shows up in All when it's a normal doc:
        eq_(1, l10n_overview_rows("de")["all"]["numerator"])
        eq_(1, l10n_overview_rows("de")["all"]["denominator"])

        t.document.parent.title = t.document.title = "Template:thing"
        t.document.parent.category = TEMPLATES_CATEGORY
        # is_template will be automatically set for both templates, and so will
        # the child document's category.
        t.document.parent.save()
        t.document.save()
        # ...but not when it's a template:
        eq_(0, l10n_overview_rows("de")["all"]["numerator"])
        eq_(0, l10n_overview_rows("de")["all"]["denominator"])
Example #10
0
    def test_miscounting_archived(self):
        """
        Verify that the l10n overview readout treats archived docs consistently.

        Bug 1012384
        """
        locale = 'nl'
        parent1 = DocumentFactory(category=CANNED_RESPONSES_CATEGORY, is_archived=False)
        translation1 = DocumentFactory(parent=parent1, locale=locale)
        parent2 = DocumentFactory(category=CANNED_RESPONSES_CATEGORY, is_archived=True)
        translation2 = DocumentFactory(parent=parent2, locale=locale)

        trans_rev1 = ApprovedRevisionFactory(document=parent1, is_ready_for_localization=True)
        ApprovedRevisionFactory(document=translation1, based_on=trans_rev1)
        trans_rev2 = ApprovedRevisionFactory(document=parent2, is_ready_for_localization=True)
        ApprovedRevisionFactory(document=translation2, based_on=trans_rev2)

        # Document.save() will enforce that parents and translations share is_archived.
        # The point of this is to test what happens when that isn't true though,
        # so bypass Document.save().
        translation2.is_archived = False
        ModelBase.save(translation2)
        eq_(translation2.is_archived, False)

        overview = l10n_overview_rows(locale)
        eq_(1, overview['all']['denominator'])
        eq_(1, overview['all']['numerator'])
Example #11
0
    def test_templates_and_docs_disjunct(self):
        """Make sure templates aren't included in the All Articles count."""
        t = translated_revision(is_approved=True, save=True)
        # It shows up in All when it's a normal doc:
        eq_(1, l10n_overview_rows('de')['all']['numerator'])
        eq_(1, l10n_overview_rows('de')['all']['denominator'])

        t.document.parent.title = t.document.title = 'Template:thing'
        t.document.parent.category = TEMPLATES_CATEGORY
        # is_template will be automatically set for both templates, and so will
        # the child document's category.
        t.document.parent.save()
        t.document.save()
        # ...but not when it's a template:
        eq_(0, l10n_overview_rows('de')['all']['numerator'])
        eq_(0, l10n_overview_rows('de')['all']['denominator'])
Example #12
0
    def test_counting_unready_docs(self):
        """Docs without a ready-for-l10n rev shouldn't count in total."""
        # Make a doc with an approved but not-ready-for-l10n rev:
        r = revision(
            document=document(title="smoo", is_localizable=True, save=True),
            is_ready_for_localization=False,
            is_approved=True,
            save=True,
        )

        # It shouldn't show up in the total:
        eq_(0, l10n_overview_rows("de")["all"]["denominator"])

        r.is_ready_for_localization = True
        r.save()
        eq_(1, l10n_overview_rows("de")["all"]["denominator"])
Example #13
0
    def test_redirects_are_ignored(self):
        """Verify that redirects aren't counted in the overview."""
        TranslatedRevisionFactory(document__locale="de", is_approved=True)

        eq_(1, l10n_overview_rows("de")["all"]["numerator"])

        # A redirect shouldn't affect any of the tests.
        RedirectRevisionFactory(
            document__is_localizable=True, document__is_template=True, is_ready_for_localization=True
        )

        overview = l10n_overview_rows("de")
        eq_(1, overview["all"]["numerator"])
        eq_(1, overview["top-20"]["numerator"])
        eq_(1, overview["top-50"]["numerator"])
        eq_(1, overview["top-100"]["numerator"])
Example #14
0
    def test_counting_unready_templates(self):
        """Templates without a ready-for-l10n rev don't count"""
        # Make a template with an approved but not-ready-for-l10n rev:
        r = revision(document=document(title='Template:smoo',
                                       is_localizable=True,
                                       is_template=True,
                                       save=True),
                     is_ready_for_localization=False,
                     is_approved=True,
                     save=True)

        # It shouldn't show up in the total:
        eq_(0, l10n_overview_rows('de')['templates']['denominator'])

        r.is_ready_for_localization = True
        r.save()
        eq_(1, l10n_overview_rows('de')['templates']['denominator'])
Example #15
0
 def test_not_counting_untranslated(self):
     """Translations with no approved revisions shouldn't count as done.
     """
     translated_revision(is_approved=False, save=True)
     overview = l10n_overview_rows('de')
     eq_(0, overview['top-20']['numerator'])
     eq_(0, overview['top-50']['numerator'])
     eq_(0, overview['top-100']['numerator'])
     eq_(0, overview['all']['numerator'])
Example #16
0
 def test_not_counting_untranslated(self):
     """Translations with no approved revisions shouldn't count as done.
     """
     TranslatedRevisionFactory(document__locale='de', is_approved=False)
     overview = l10n_overview_rows('de')
     eq_(0, overview['top-20']['numerator'])
     eq_(0, overview['top-50']['numerator'])
     eq_(0, overview['top-100']['numerator'])
     eq_(0, overview['all']['numerator'])
Example #17
0
 def test_not_counting_untranslated(self):
     """Translations with no approved revisions shouldn't count as done.
     """
     translated_revision(is_approved=False, save=True)
     overview = l10n_overview_rows("de")
     eq_(0, overview["top-20"]["numerator"])
     eq_(0, overview["top-50"]["numerator"])
     eq_(0, overview["top-100"]["numerator"])
     eq_(0, overview["all"]["numerator"])
Example #18
0
 def test_not_counting_untranslated(self):
     """Translations with no approved revisions shouldn't count as done.
     """
     TranslatedRevisionFactory(document__locale="de", is_approved=False)
     overview = l10n_overview_rows("de")
     eq_(0, overview["top-20"]["numerator"])
     eq_(0, overview["top-50"]["numerator"])
     eq_(0, overview["top-100"]["numerator"])
     eq_(0, overview["all"]["numerator"])
Example #19
0
    def test_redirects_are_ignored(self):
        """Verify that redirects aren't counted in the overview."""
        translated_revision(is_approved=True, save=True)

        eq_(1, l10n_overview_rows("de")["all"]["numerator"])

        # A redirect shouldn't affect any of the tests.
        revision(
            document=document(title="A redirect", is_localizable=True, is_template=True, save=True),
            is_ready_for_localization=True,
            is_approved=True,
            content="REDIRECT [[An article]]",
            save=True,
        )

        overview = l10n_overview_rows("de")
        eq_(1, overview["all"]["numerator"])
        eq_(1, overview["top-20"]["numerator"])
        eq_(1, overview["top-50"]["numerator"])
        eq_(1, overview["top-100"]["numerator"])
Example #20
0
    def test_not_counting_how_to_contribute(self):
        """Articles with the How to contribute category should not be counted.
        """
        t = translated_revision(is_approved=True, save=True)
        overview = l10n_overview_rows('de')
        eq_(1, overview['all']['numerator'])
        eq_(1, overview['top-20']['numerator'])
        eq_(1, overview['top-50']['numerator'])
        eq_(1, overview['top-100']['numerator'])

        # Update the parent with the How To Contribute category
        d = t.document.parent
        d.category = HOW_TO_CONTRIBUTE_CATEGORY
        d.save()

        overview = l10n_overview_rows('de')
        eq_(0, overview['all']['numerator'])
        eq_(0, overview['top-20']['numerator'])
        eq_(0, overview['top-50']['numerator'])
        eq_(0, overview['top-100']['numerator'])
Example #21
0
    def test_counting_unready_parents(self):
        """Translations with no ready revs don't count in numerator

        By dint of factoring, this also tests that templates whose
        parents....

        """
        parent_rev = RevisionFactory(document__is_localizable=True, is_approved=True, is_ready_for_localization=False)
        translation = DocumentFactory(parent=parent_rev.document, locale="de", is_localizable=False)
        RevisionFactory(document=translation, is_approved=True, based_on=parent_rev)
        eq_(0, l10n_overview_rows("de")["all"]["numerator"])
Example #22
0
    def test_not_counting_how_to_contribute(self):
        """Articles with the How to contribute category should not be counted.
        """
        t = TranslatedRevisionFactory(document__locale="de", is_approved=True)
        overview = l10n_overview_rows("de")
        eq_(1, overview["all"]["numerator"])
        eq_(1, overview["top-20"]["numerator"])
        eq_(1, overview["top-50"]["numerator"])
        eq_(1, overview["top-100"]["numerator"])

        # Update the parent with the How To Contribute category
        d = t.document.parent
        d.category = HOW_TO_CONTRIBUTE_CATEGORY
        d.save()

        overview = l10n_overview_rows("de")
        eq_(0, overview["all"]["numerator"])
        eq_(0, overview["top-20"]["numerator"])
        eq_(0, overview["top-50"]["numerator"])
        eq_(0, overview["top-100"]["numerator"])
Example #23
0
    def test_redirects_are_ignored(self):
        """Verify that redirects aren't counted in the overview."""
        translated_revision(is_approved=True, save=True)

        eq_(1, l10n_overview_rows('de')['all']['numerator'])

        # A redirect shouldn't affect any of the tests.
        revision(document=document(title='A redirect',
                                   is_localizable=True,
                                   is_template=True,
                                   save=True),
                 is_ready_for_localization=True,
                 is_approved=True,
                 content='REDIRECT [[An article]]',
                 save=True)

        overview = l10n_overview_rows('de')
        eq_(1, overview['all']['numerator'])
        eq_(1, overview['top-20']['numerator'])
        eq_(1, overview['top-50']['numerator'])
        eq_(1, overview['top-100']['numerator'])
Example #24
0
    def test_not_counting_templates(self):
        """Articles in the Templates category should not be counted.
        """
        t = translated_revision(is_approved=True, save=True)
        overview = l10n_overview_rows("de")
        eq_(1, overview["all"]["numerator"])
        eq_(1, overview["top-20"]["numerator"])
        eq_(1, overview["top-50"]["numerator"])
        eq_(1, overview["top-100"]["numerator"])

        # Update the parent and translation to be a template
        d = t.document.parent
        d.title = "Template:Lorem Ipsum Dolor"
        d.save()
        t.document.title = "Template:Lorem Ipsum Dolor"
        t.document.save()

        overview = l10n_overview_rows("de")
        eq_(0, overview["all"]["numerator"])
        eq_(0, overview["top-20"]["numerator"])
        eq_(0, overview["top-50"]["numerator"])
        eq_(0, overview["top-100"]["numerator"])
Example #25
0
    def test_not_counting_templates(self):
        """Articles in the Templates category should not be counted.
        """
        t = translated_revision(is_approved=True, save=True)
        overview = l10n_overview_rows('de')
        eq_(1, overview['all']['numerator'])
        eq_(1, overview['top-20']['numerator'])
        eq_(1, overview['top-50']['numerator'])
        eq_(1, overview['top-100']['numerator'])

        # Update the parent and translation to be a template
        d = t.document.parent
        d.title = 'Template:Lorem Ipsum Dolor'
        d.save()
        t.document.title = 'Template:Lorem Ipsum Dolor'
        t.document.save()

        overview = l10n_overview_rows('de')
        eq_(0, overview['all']['numerator'])
        eq_(0, overview['top-20']['numerator'])
        eq_(0, overview['top-50']['numerator'])
        eq_(0, overview['top-100']['numerator'])
Example #26
0
def update_l10n_coverage_metrics():
    """Calculate and store the l10n metrics for each locale/product.

    The metrics are:
    * Percent localized of top 20 articles
    * Percent localized of all articles
    """
    today = date.today()

    # Loop through all locales.
    for locale in settings.SUMO_LANGUAGES:

        # Skip en-US, it is always 100% localized.
        if locale == settings.WIKI_DEFAULT_LANGUAGE:
            continue

        # Loop through all enabled products, including None (really All).
        for product in [None] + list(Product.objects.filter(visible=True)):

            # (Ab)use the l10n_overview_rows helper from the readouts.
            rows = l10n_overview_rows(locale=locale, product=product)

            # % of top 20 articles
            top20 = rows['top-20']

            try:
                percent = 100.0 * float(top20['numerator']) / top20['denominator']
            except ZeroDivisionError:
                percent = 0.0

            WikiMetric.objects.create(
                code=L10N_TOP20_CODE,
                locale=locale,
                product=product,
                date=today,
                value=percent)

            # % of all articles
            all_ = rows['all']
            try:
                percent = 100 * float(all_['numerator']) / all_['denominator']
            except ZeroDivisionError:
                percent = 0.0

            WikiMetric.objects.create(
                code=L10N_ALL_CODE,
                locale=locale,
                product=product,
                date=today,
                value=percent)
Example #27
0
def localization(request):
    """Render aggregate data about articles in a non-default locale."""
    if request.LANGUAGE_CODE == settings.WIKI_DEFAULT_LANGUAGE:
        return HttpResponseRedirect(reverse('dashboards.contributors'))
    locales = Locale.objects.filter(locale=request.LANGUAGE_CODE)
    if locales:
        permission = user_can_announce(request.user, locales[0])
    else:
        permission = False

    product = _get_product(request)

    data = {
        'overview_rows': l10n_overview_rows(
            request.LANGUAGE_CODE, product=product),
        'user_can_announce': permission,
    }
    return render_readouts(request, L10N_READOUTS, 'localization.html',
                           extra_data=data, product=product)
Example #28
0
    def test_counting_unready_parents(self):
        """Translations with no ready revs don't count in numerator

        By dint of factoring, this also tests that templates whose
        parents....

        """
        parent_rev = revision(document=document(is_localizable=True,
                                                save=True),
                              is_approved=True,
                              is_ready_for_localization=False,
                              save=True)
        translation = document(parent=parent_rev.document,
                               locale='de',
                               is_localizable=False,
                               save=True)
        revision(document=translation,
                 is_approved=True,
                 based_on=parent_rev,
                 save=True)
        eq_(0, l10n_overview_rows('de')['all']['numerator'])
Example #29
0
    def test_counting_unready_parents(self):
        """Translations with no ready revs don't count in numerator

        By dint of factoring, this also tests that templates whose
        parents....

        """
        parent_rev = revision(document=document(is_localizable=True,
                                                save=True),
                              is_approved=True,
                              is_ready_for_localization=False,
                              save=True)
        translation = document(parent=parent_rev.document,
                               locale='de',
                               is_localizable=False,
                               save=True)
        revision(document=translation,
                 is_approved=True,
                 based_on=parent_rev,
                 save=True)
        eq_(0, l10n_overview_rows('de')['all']['numerator'])
Example #30
0
def localization(request):
    """Render aggregate data about articles in a non-default locale."""
    if request.LANGUAGE_CODE == settings.WIKI_DEFAULT_LANGUAGE:
        return HttpResponseRedirect(reverse('dashboards.contributors'))
    locales = Locale.objects.filter(locale=request.LANGUAGE_CODE)
    if locales:
        permission = user_can_announce(request.user, locales[0])
    else:
        permission = False

    product = _get_product(request)

    data = {
        'overview_rows': l10n_overview_rows(request.LANGUAGE_CODE,
                                            product=product),
        'user_can_announce': permission,
    }
    return render_readouts(request,
                           L10N_READOUTS,
                           'localization.html',
                           extra_data=data,
                           product=product)
    def handle(self, **options):
        """
        The metrics are:
        * Percent localized of top 20 articles
        * Percent localized of all articles
        """
        today = date.today()

        # Loop through all locales.
        for locale in settings.SUMO_LANGUAGES:

            # Skip en-US, it is always 100% localized.
            if locale == settings.WIKI_DEFAULT_LANGUAGE:
                continue

            # Loop through all enabled products, including None (really All).
            for product in [None] + list(Product.objects.filter(visible=True)):

                # (Ab)use the l10n_overview_rows helper from the readouts.
                rows = l10n_overview_rows(locale=locale, product=product)

                # % of top 20 articles
                top20 = rows['top-20']

                try:
                    percent = 100.0 * float(top20['numerator']) / top20['denominator']
                except ZeroDivisionError:
                    percent = 0.0

                WikiMetric.objects.create(
                    code=L10N_TOP20_CODE,
                    locale=locale,
                    product=product,
                    date=today,
                    value=percent)

                # % of top 100 articles
                top100 = rows['top-100']

                try:
                    percent = 100.0 * float(top100['numerator']) / top100['denominator']
                except ZeroDivisionError:
                    percent = 0.0

                WikiMetric.objects.create(
                    code=L10N_TOP100_CODE,
                    locale=locale,
                    product=product,
                    date=today,
                    value=percent)

                # % of all articles
                all_ = rows['all']
                try:
                    percent = 100 * float(all_['numerator']) / all_['denominator']
                except ZeroDivisionError:
                    percent = 0.0

                WikiMetric.objects.create(
                    code=L10N_ALL_CODE,
                    locale=locale,
                    product=product,
                    date=today,
                    value=percent)