Esempio n. 1
0
def test_get_translations(gt_mock, locale_b, resource_a, google_translate_locale):
    entities = [
        EntityFactory(resource=resource_a, string=x, order=i)
        for i, x in enumerate(["abaa", "abac", "aaab", "abab"])
    ]

    entities[1].string_plural = entities[1].string
    entities[3].string_plural = entities[3].string
    entities[1].save()
    entities[3].save()

    google_translate_locale.cldr_plurals = "1, 2"
    google_translate_locale.save()

    for entity in entities[0:2]:
        TranslationMemoryFactory.create(
            entity=entity, source=entity.string, target=entity.string, locale=locale_b,
        )
        TranslationMemoryFactory.create(
            entity=entity,
            source=entity.string,
            target=entity.string,
            locale=google_translate_locale,
        )

    # Mock the return value of get_google_translate_data
    gt_mock.return_value = {
        "status": True,
        "translation": "gt_translation",
    }

    tm_user = User.objects.get(email="*****@*****.**")
    gt_user = User.objects.get(email="*****@*****.**")

    # 100% match exists in translation memory.
    response_a = get_translations(entities[0], locale_b)
    response_b = get_translations(entities[0], google_translate_locale)
    assert response_a == [(entities[0].string, None, tm_user)]
    assert response_b == [(entities[0].string, None, tm_user)]

    # 100% match does not exists and locale.google_translate_code is None.
    response = get_translations(entities[2], locale_b)
    assert response == []

    # 100% match does not exists and locale.google_translate_code is not None.
    response = get_translations(entities[2], google_translate_locale)
    assert response == [("gt_translation", None, gt_user)]

    # Entity.string_plural is not None.
    response_a = get_translations(entities[1], google_translate_locale)
    response_b = get_translations(entities[3], google_translate_locale)
    assert response_a == [
        (entities[1].string, 0, tm_user),
        (entities[1].string, 1, tm_user),
    ]
    assert response_b == [
        ("gt_translation", 0, gt_user),
        ("gt_translation", 1, gt_user),
    ]
Esempio n. 2
0
def pretranslate(self, project_pk, locales=None, entities=None):
    """
    Identifies strings without any translations and any suggestions.
    Engages TheAlgorithm (bug 1552796) to gather pretranslations.
    Stores pretranslations as suggestions (approved=False) to DB.

    :arg project_pk: the pk of the project to be pretranslated
    :arg Queryset locales: the locales for the project to be pretranslated
    :arg Queryset entites: the entities for the project to be pretranslated

    :returns: None
    """
    project = Project.objects.get(pk=project_pk)

    log.info("Fetching pretranslations for project {} started".format(
        project.name))

    if locales:
        locales = project.locales.filter(pk__in=locales)
    else:
        locales = project.locales

    locales = (locales.filter(project_locale__readonly=False).distinct().
               prefetch_project_locale(project))

    if not entities:
        entities = Entity.objects.filter(
            resource__project=project,
            obsolete=False,
        ).prefetch_related("resource")

    # get available TranslatedResource pairs
    tr_pairs = (TranslatedResource.objects.filter(
        resource__project=project,
        locale__in=locales,
    ).annotate(locale_resource=Concat(
        "locale_id", V("-"), "resource_id",
        output_field=CharField())).values_list("locale_resource",
                                               flat=True).distinct())

    # Fetch all distinct locale-entity pairs for which translation exists
    translated_entities = (Translation.objects.filter(
        locale__in=locales,
        entity__in=entities,
    ).annotate(locale_entity=Concat(
        "locale_id", V("-"), "entity_id",
        output_field=CharField())).values_list("locale_entity",
                                               flat=True).distinct())

    translated_entities = list(translated_entities)

    translations = []

    # To keep track of changed TranslatedResources and their latest_translation
    tr_dict = {}

    tr_filter = []
    index = -1

    for locale in locales:
        log.info("Fetching pretranslations for locale {} started".format(
            locale.code))
        for entity in entities:
            locale_entity = "{}-{}".format(locale.id, entity.id)
            locale_resource = "{}-{}".format(locale.id, entity.resource.id)
            if locale_entity in translated_entities or locale_resource not in tr_pairs:
                continue

            strings = get_translations(entity, locale)

            if not strings:
                continue

            for string, plural_form, user in strings:
                t = Translation(
                    entity=entity,
                    locale=locale,
                    string=string,
                    user=user,
                    approved=False,
                    fuzzy=True,
                    active=True,
                    plural_form=plural_form,
                )

                index += 1
                translations.append(t)

                if locale_resource not in tr_dict:
                    tr_dict[locale_resource] = index

                    # Add query for fetching respective TranslatedResource.
                    tr_filter.append(
                        Q(locale__id=locale.id)
                        & Q(resource__id=entity.resource.id))

                # Update the latest translation index
                tr_dict[locale_resource] = index

        log.info("Fetching pretranslations for locale {} done".format(
            locale.code))

    if len(translations) == 0:
        return

    translations = Translation.objects.bulk_create(translations)

    # Run checks on all translations
    translation_pks = {translation.pk for translation in translations}
    bulk_run_checks(
        Translation.objects.for_checks().filter(pk__in=translation_pks))

    # Mark translations as changed
    changed_entities = {}
    existing = ChangedEntityLocale.objects.values_list("entity",
                                                       "locale").distinct()
    for t in translations:
        key = (t.entity.pk, t.locale.pk)
        # Remove duplicate changes to prevent unique constraint violation
        if key not in existing:
            changed_entities[key] = ChangedEntityLocale(entity=t.entity,
                                                        locale=t.locale)
    ChangedEntityLocale.objects.bulk_create(changed_entities.values())

    # Update latest activity and stats for changed instances.
    update_changed_instances(tr_filter, tr_dict, translations)

    log.info("Fetching pretranslations for project {} done".format(
        project.name))
Esempio n. 3
0
def pretranslate(project, locales=None, entities=None):
    """
    Identifies strings without any translations and any suggestions.
    Engages TheAlgorithm (bug 1552796) to gather pretranslations.
    Stores pretranslations as suggestions (approved=False) to DB.

    :arg Project project: the project to be pretranslated
    :arg Queryset locales: the locales for the project to be pretranslated
    :arg Queryset entites: the entities for the project to be pretranslated

    :returns: None
    """

    log.info("Fetching pretranslations for project {} started".format(
        project.name))

    if locales:
        locales = project.locales.filter(pk__in=locales)
    else:
        locales = project.locales

    locales = (locales.filter(project_locale__readonly=False).distinct().
               prefetch_project_locale(project))

    if not entities:
        entities = Entity.objects.filter(
            resource__project=project,
            obsolete=False,
        ).prefetch_related("resource")

    # get available TranslatedResource pairs
    tr_pairs = (TranslatedResource.objects.filter(
        resource__project=project,
        locale__in=locales,
    ).annotate(locale_resource=Concat(
        "locale_id", V("-"), "resource_id",
        output_field=CharField())).values_list("locale_resource",
                                               flat=True).distinct())

    # Fetch all distinct locale-entity pairs for which translation exists
    translated_entities = (Translation.objects.filter(
        locale__in=locales,
        entity__in=entities,
    ).annotate(locale_entity=Concat(
        "locale_id", V("-"), "entity_id",
        output_field=CharField())).values_list("locale_entity",
                                               flat=True).distinct())

    translated_entities = list(translated_entities)

    translations = []

    # To keep track of changed Locales and TranslatedResources
    # Also, their latest_translation and stats count
    locale_dict = {}
    tr_dict = {}

    tr_filter = []
    index = -1

    for locale in locales:
        log.info("Fetching pretranslations for locale {} started".format(
            locale.code))
        for entity in entities:
            locale_entity = "{}-{}".format(locale.id, entity.id)
            locale_resource = "{}-{}".format(locale.id, entity.resource.id)
            if locale_entity in translated_entities or locale_resource not in tr_pairs:
                continue

            strings = get_translations(entity, locale)

            if not strings:
                continue

            for string, plural_form, user in strings:
                t = Translation(
                    entity=entity,
                    locale=locale,
                    string=string,
                    user=user,
                    approved=False,
                    active=True,
                    plural_form=plural_form,
                )

                translations.append(t)

                index += 1

                if locale_resource not in tr_dict:
                    tr_dict[locale_resource] = [index, 0]
                    # Add query for fetching respective TranslatedResource.
                    tr_filter.append(
                        Q(locale__id=locale.id)
                        & Q(resource__id=entity.resource.id))

                if locale.code not in locale_dict:
                    locale_dict[locale.code] = [locale, index, 0]

                # Update the latest translation index
                tr_dict[locale_resource][0] = index
                locale_dict[locale.code][1] = index

                # Increment number of translations (used to adjust stats)
                tr_dict[locale_resource][1] += 1
                locale_dict[locale.code][2] += 1
        log.info("Fetching pretranslations for locale {} done".format(
            locale.code))

    if len(translations) == 0:
        return

    translations = Translation.objects.bulk_create(translations)

    # Update latest activity and unreviewed count for the project.
    project.latest_translation = translations[-1]
    project.unreviewed_strings += len(translations)
    project.save(update_fields=["latest_translation", "unreviewed_strings"])

    # Update latest activity and unreviewed count for changed instances.
    update_changed_instances(tr_filter, tr_dict, locale_dict, translations)

    log.info("Fetching pretranslations for project {} done".format(
        project.name))