prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  Don't submit pretranslated strings with warnings or errors
  If possible, it would be great to have 2 different behaviors:
  * Strings with warning should be suggested, instead of submitted, because they might be OK (i.e. the warning could be ignored), or at least it might be still useful to post-edit them instead of starting from scratch.
  * String with errors shouldn't be even suggested.
  
  If not possible, I guess storing them both as suggestions would work, since the localizer wouldn't be able to confirm a string with errors (but it will be confusing).
  
  The important piece is not storing them in VCS, because it will create a chain of errors, especially in parts that we don't control (the final product).
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `pontoon/pretranslation/tasks.py`
  Content:
  ```
  1 import logging
  2 
  3 from django.db.models import Q, CharField, Value as V
  4 from django.db.models.functions import Concat
  5 from django.conf import settings
  6 from pontoon.base.models import (
  7     Project,
  8     Entity,
  9     TranslatedResource,
  10     Translation,
  11 )
  12 from pontoon.actionlog.models import ActionLog
  13 from pontoon.pretranslation.pretranslate import (
  14     get_pretranslations,
  15     update_changed_instances,
  16 )
  17 from pontoon.base.tasks import PontoonTask
  18 from pontoon.sync.core import serial_task
  19 from pontoon.checks.utils import bulk_run_checks
  20 
  21 
  22 log = logging.getLogger(__name__)
  23 
  24 
  25 @serial_task(settings.SYNC_TASK_TIMEOUT, base=PontoonTask, lock_key="project={0}")
  26 def pretranslate(self, project_pk, locales=None, entities=None):
  27     """
  28     Identifies strings without any translations and any suggestions.
  29     Engages TheAlgorithm (bug 1552796) to gather pretranslations.
  30     Stores pretranslations as suggestions (approved=False) to DB.
  31 
  32     :arg project_pk: the pk of the project to be pretranslated
  33     :arg Queryset locales: the locales for the project to be pretranslated
  34     :arg Queryset entites: the entities for the project to be pretranslated
  35 
  36     :returns: None
  37     """
  38     project = Project.objects.get(pk=project_pk)
  39 
  40     if not project.pretranslation_enabled:
  41         log.info(f"Pretranslation not enabled for project {project.name}")
  42         return
  43 
  44     if locales:
  45         locales = project.locales.filter(pk__in=locales)
  46     else:
  47         locales = project.locales
  48 
  49     locales = locales.filter(
  50         project_locale__project=project,
  51         project_locale__pretranslation_enabled=True,
  52         project_locale__readonly=False,
  53     )
  54 
  55     if not locales:
  56         log.info(
  57             f"Pretranslation not enabled for any locale within project {project.name}"
  58         )
  59         return
  60 
  61     log.info(f"Fetching pretranslations for project {project.name} started")
  62 
  63     if not entities:
  64         entities = Entity.objects.filter(
  65             resource__project=project,
  66             obsolete=False,
  67         )
  68 
  69     entities = entities.prefetch_related("resource")
  70 
  71     # get available TranslatedResource pairs
  72     tr_pairs = (
  73         TranslatedResource.objects.filter(
  74             resource__project=project,
  75             locale__in=locales,
  76         )
  77         .annotate(
  78             locale_resource=Concat(
  79                 "locale_id", V("-"), "resource_id", output_field=CharField()
  80             )
  81         )
  82         .values_list("locale_resource", flat=True)
  83         .distinct()
  84     )
  85 
  86     # Fetch all distinct locale-entity pairs for which translation exists
  87     translated_entities = (
  88         Translation.objects.filter(
  89             locale__in=locales,
  90             entity__in=entities,
  91         )
  92         .annotate(
  93             locale_entity=Concat(
  94                 "locale_id", V("-"), "entity_id", output_field=CharField()
  95             )
  96         )
  97         .values_list("locale_entity", flat=True)
  98         .distinct()
  99     )
  100 
  101     translated_entities = list(translated_entities)
  102 
  103     translations = []
  104 
  105     # To keep track of changed TranslatedResources and their latest_translation
  106     tr_dict = {}
  107 
  108     tr_filter = []
  109     index = -1
  110 
  111     for locale in locales:
  112         log.info(f"Fetching pretranslations for locale {locale.code} started")
  113         for entity in entities:
  114             locale_entity = f"{locale.id}-{entity.id}"
  115             locale_resource = f"{locale.id}-{entity.resource.id}"
  116             if locale_entity in translated_entities or locale_resource not in tr_pairs:
  117                 continue
  118 
  119             pretranslations = get_pretranslations(entity, locale)
  120 
  121             if not pretranslations:
  122                 continue
  123 
  124             for string, plural_form, user in pretranslations:
  125                 t = Translation(
  126                     entity=entity,
  127                     locale=locale,
  128                     string=string,
  129                     user=user,
  130                     approved=False,
  131                     pretranslated=True,
  132                     active=True,
  133                     plural_form=plural_form,
  134                 )
  135 
  136                 index += 1
  137                 translations.append(t)
  138 
  139                 if locale_resource not in tr_dict:
  140                     tr_dict[locale_resource] = index
  141 
  142                     # Add query for fetching respective TranslatedResource.
  143                     tr_filter.append(
  144                         Q(locale__id=locale.id) & Q(resource__id=entity.resource.id)
  145                     )
  146 
  147                 # Update the latest translation index
  148                 tr_dict[locale_resource] = index
  149 
  150         log.info(f"Fetching pretranslations for locale {locale.code} done")
  151 
  152     if len(translations) == 0:
  153         return
  154 
  155     translations = Translation.objects.bulk_create(translations)
  156 
  157     # Log creating actions
  158     actions_to_log = [
  159         ActionLog(
  160             action_type=ActionLog.ActionType.TRANSLATION_CREATED,
  161             performed_by=t.user,
  162             translation=t,
  163         )
  164         for t in translations
  165     ]
  166 
  167     ActionLog.objects.bulk_create(actions_to_log)
  168 
  169     # Run checks on all translations
  170     translation_pks = {translation.pk for translation in translations}
  171     bulk_run_checks(Translation.objects.for_checks().filter(pk__in=translation_pks))
  172 
  173     # Mark translations as changed
  174     changed_translations = Translation.objects.filter(pk__in=translation_pks)
  175     changed_translations.bulk_mark_changed()
  176 
  177     # Update latest activity and stats for changed instances.
  178     update_changed_instances(tr_filter, tr_dict, translations)
  179 
  180     log.info(f"Fetching pretranslations for project {project.name} done")
  181
  ```
  --- END FILES ---
  
  Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.
  
  Here is an example:
  
  ```diff
  diff --git a/examples/server_async.py b/examples/server_async.py
  --- a/examples/server_async.py
  +++ b/examples/server_async.py
  @@ -313,4 +313,4 @@
   
   
   if __name__ == "__main__":
  -    asyncio.run(run_async_server("."), debug=True)
  +    asyncio.run(run_async_server(), debug=True)
  diff --git a/examples/server_sync.py b/examples/server_sync.py
  --- a/examples/server_sync.py
  +++ b/examples/server_sync.py
  @@ -313,5 +313,5 @@
   
   
   if __name__ == "__main__":
  -    server = run_sync_server(".")
  +    server = run_sync_server()
       server.shutdown()
  
  ```
  
golden_diff: diff --git a/pontoon/pretranslation/tasks.py b/pontoon/pretranslation/tasks.py
  --- a/pontoon/pretranslation/tasks.py
  +++ b/pontoon/pretranslation/tasks.py
  @@ -171,7 +171,12 @@
       bulk_run_checks(Translation.objects.for_checks().filter(pk__in=translation_pks))
   
       # Mark translations as changed
  -    changed_translations = Translation.objects.filter(pk__in=translation_pks)
  +    changed_translations = Translation.objects.filter(
  +        pk__in=translation_pks,
  +        # Do not sync translations with errors and warnings
  +        errors__isnull=True,
  +        warnings__isnull=True,
  +    )
       changed_translations.bulk_mark_changed()
   
       # Update latest activity and stats for changed instances.
  
verification_info: {"golden_diff": "diff --git a/pontoon/pretranslation/tasks.py b/pontoon/pretranslation/tasks.py\n--- a/pontoon/pretranslation/tasks.py\n+++ b/pontoon/pretranslation/tasks.py\n@@ -171,7 +171,12 @@\n     bulk_run_checks(Translation.objects.for_checks().filter(pk__in=translation_pks))\n \n     # Mark translations as changed\n-    changed_translations = Translation.objects.filter(pk__in=translation_pks)\n+    changed_translations = Translation.objects.filter(\n+        pk__in=translation_pks,\n+        # Do not sync translations with errors and warnings\n+        errors__isnull=True,\n+        warnings__isnull=True,\n+    )\n     changed_translations.bulk_mark_changed()\n \n     # Update latest activity and stats for changed instances.\n", "issue": "Don't submit pretranslated strings with warnings or errors\nIf possible, it would be great to have 2 different behaviors:\r\n* Strings with warning should be suggested, instead of submitted, because they might be OK (i.e. the warning could be ignored), or at least it might be still useful to post-edit them instead of starting from scratch.\r\n* String with errors shouldn't be even suggested.\r\n\r\nIf not possible, I guess storing them both as suggestions would work, since the localizer wouldn't be able to confirm a string with errors (but it will be confusing).\r\n\r\nThe important piece is not storing them in VCS, because it will create a chain of errors, especially in parts that we don't control (the final product).\n", "before_files": [{"content": "import logging\n\nfrom django.db.models import Q, CharField, Value as V\nfrom django.db.models.functions import Concat\nfrom django.conf import settings\nfrom pontoon.base.models import (\n    Project,\n    Entity,\n    TranslatedResource,\n    Translation,\n)\nfrom pontoon.actionlog.models import ActionLog\nfrom pontoon.pretranslation.pretranslate import (\n    get_pretranslations,\n    update_changed_instances,\n)\nfrom pontoon.base.tasks import PontoonTask\nfrom pontoon.sync.core import serial_task\nfrom pontoon.checks.utils import bulk_run_checks\n\n\nlog = logging.getLogger(__name__)\n\n\n@serial_task(settings.SYNC_TASK_TIMEOUT, base=PontoonTask, lock_key=\"project={0}\")\ndef pretranslate(self, project_pk, locales=None, entities=None):\n    \"\"\"\n    Identifies strings without any translations and any suggestions.\n    Engages TheAlgorithm (bug 1552796) to gather pretranslations.\n    Stores pretranslations as suggestions (approved=False) to DB.\n\n    :arg project_pk: the pk of the project to be pretranslated\n    :arg Queryset locales: the locales for the project to be pretranslated\n    :arg Queryset entites: the entities for the project to be pretranslated\n\n    :returns: None\n    \"\"\"\n    project = Project.objects.get(pk=project_pk)\n\n    if not project.pretranslation_enabled:\n        log.info(f\"Pretranslation not enabled for project {project.name}\")\n        return\n\n    if locales:\n        locales = project.locales.filter(pk__in=locales)\n    else:\n        locales = project.locales\n\n    locales = locales.filter(\n        project_locale__project=project,\n        project_locale__pretranslation_enabled=True,\n        project_locale__readonly=False,\n    )\n\n    if not locales:\n        log.info(\n            f\"Pretranslation not enabled for any locale within project {project.name}\"\n        )\n        return\n\n    log.info(f\"Fetching pretranslations for project {project.name} started\")\n\n    if not entities:\n        entities = Entity.objects.filter(\n            resource__project=project,\n            obsolete=False,\n        )\n\n    entities = entities.prefetch_related(\"resource\")\n\n    # get available TranslatedResource pairs\n    tr_pairs = (\n        TranslatedResource.objects.filter(\n            resource__project=project,\n            locale__in=locales,\n        )\n        .annotate(\n            locale_resource=Concat(\n                \"locale_id\", V(\"-\"), \"resource_id\", output_field=CharField()\n            )\n        )\n        .values_list(\"locale_resource\", flat=True)\n        .distinct()\n    )\n\n    # Fetch all distinct locale-entity pairs for which translation exists\n    translated_entities = (\n        Translation.objects.filter(\n            locale__in=locales,\n            entity__in=entities,\n        )\n        .annotate(\n            locale_entity=Concat(\n                \"locale_id\", V(\"-\"), \"entity_id\", output_field=CharField()\n            )\n        )\n        .values_list(\"locale_entity\", flat=True)\n        .distinct()\n    )\n\n    translated_entities = list(translated_entities)\n\n    translations = []\n\n    # To keep track of changed TranslatedResources and their latest_translation\n    tr_dict = {}\n\n    tr_filter = []\n    index = -1\n\n    for locale in locales:\n        log.info(f\"Fetching pretranslations for locale {locale.code} started\")\n        for entity in entities:\n            locale_entity = f\"{locale.id}-{entity.id}\"\n            locale_resource = f\"{locale.id}-{entity.resource.id}\"\n            if locale_entity in translated_entities or locale_resource not in tr_pairs:\n                continue\n\n            pretranslations = get_pretranslations(entity, locale)\n\n            if not pretranslations:\n                continue\n\n            for string, plural_form, user in pretranslations:\n                t = Translation(\n                    entity=entity,\n                    locale=locale,\n                    string=string,\n                    user=user,\n                    approved=False,\n                    pretranslated=True,\n                    active=True,\n                    plural_form=plural_form,\n                )\n\n                index += 1\n                translations.append(t)\n\n                if locale_resource not in tr_dict:\n                    tr_dict[locale_resource] = index\n\n                    # Add query for fetching respective TranslatedResource.\n                    tr_filter.append(\n                        Q(locale__id=locale.id) & Q(resource__id=entity.resource.id)\n                    )\n\n                # Update the latest translation index\n                tr_dict[locale_resource] = index\n\n        log.info(f\"Fetching pretranslations for locale {locale.code} done\")\n\n    if len(translations) == 0:\n        return\n\n    translations = Translation.objects.bulk_create(translations)\n\n    # Log creating actions\n    actions_to_log = [\n        ActionLog(\n            action_type=ActionLog.ActionType.TRANSLATION_CREATED,\n            performed_by=t.user,\n            translation=t,\n        )\n        for t in translations\n    ]\n\n    ActionLog.objects.bulk_create(actions_to_log)\n\n    # Run checks on all translations\n    translation_pks = {translation.pk for translation in translations}\n    bulk_run_checks(Translation.objects.for_checks().filter(pk__in=translation_pks))\n\n    # Mark translations as changed\n    changed_translations = Translation.objects.filter(pk__in=translation_pks)\n    changed_translations.bulk_mark_changed()\n\n    # Update latest activity and stats for changed instances.\n    update_changed_instances(tr_filter, tr_dict, translations)\n\n    log.info(f\"Fetching pretranslations for project {project.name} done\")\n", "path": "pontoon/pretranslation/tasks.py"}], "after_files": [{"content": "import logging\n\nfrom django.db.models import Q, CharField, Value as V\nfrom django.db.models.functions import Concat\nfrom django.conf import settings\nfrom pontoon.base.models import (\n    Project,\n    Entity,\n    TranslatedResource,\n    Translation,\n)\nfrom pontoon.actionlog.models import ActionLog\nfrom pontoon.pretranslation.pretranslate import (\n    get_pretranslations,\n    update_changed_instances,\n)\nfrom pontoon.base.tasks import PontoonTask\nfrom pontoon.sync.core import serial_task\nfrom pontoon.checks.utils import bulk_run_checks\n\n\nlog = logging.getLogger(__name__)\n\n\n@serial_task(settings.SYNC_TASK_TIMEOUT, base=PontoonTask, lock_key=\"project={0}\")\ndef pretranslate(self, project_pk, locales=None, entities=None):\n    \"\"\"\n    Identifies strings without any translations and any suggestions.\n    Engages TheAlgorithm (bug 1552796) to gather pretranslations.\n    Stores pretranslations as suggestions (approved=False) to DB.\n\n    :arg project_pk: the pk of the project to be pretranslated\n    :arg Queryset locales: the locales for the project to be pretranslated\n    :arg Queryset entites: the entities for the project to be pretranslated\n\n    :returns: None\n    \"\"\"\n    project = Project.objects.get(pk=project_pk)\n\n    if not project.pretranslation_enabled:\n        log.info(f\"Pretranslation not enabled for project {project.name}\")\n        return\n\n    if locales:\n        locales = project.locales.filter(pk__in=locales)\n    else:\n        locales = project.locales\n\n    locales = locales.filter(\n        project_locale__project=project,\n        project_locale__pretranslation_enabled=True,\n        project_locale__readonly=False,\n    )\n\n    if not locales:\n        log.info(\n            f\"Pretranslation not enabled for any locale within project {project.name}\"\n        )\n        return\n\n    log.info(f\"Fetching pretranslations for project {project.name} started\")\n\n    if not entities:\n        entities = Entity.objects.filter(\n            resource__project=project,\n            obsolete=False,\n        )\n\n    entities = entities.prefetch_related(\"resource\")\n\n    # get available TranslatedResource pairs\n    tr_pairs = (\n        TranslatedResource.objects.filter(\n            resource__project=project,\n            locale__in=locales,\n        )\n        .annotate(\n            locale_resource=Concat(\n                \"locale_id\", V(\"-\"), \"resource_id\", output_field=CharField()\n            )\n        )\n        .values_list(\"locale_resource\", flat=True)\n        .distinct()\n    )\n\n    # Fetch all distinct locale-entity pairs for which translation exists\n    translated_entities = (\n        Translation.objects.filter(\n            locale__in=locales,\n            entity__in=entities,\n        )\n        .annotate(\n            locale_entity=Concat(\n                \"locale_id\", V(\"-\"), \"entity_id\", output_field=CharField()\n            )\n        )\n        .values_list(\"locale_entity\", flat=True)\n        .distinct()\n    )\n\n    translated_entities = list(translated_entities)\n\n    translations = []\n\n    # To keep track of changed TranslatedResources and their latest_translation\n    tr_dict = {}\n\n    tr_filter = []\n    index = -1\n\n    for locale in locales:\n        log.info(f\"Fetching pretranslations for locale {locale.code} started\")\n        for entity in entities:\n            locale_entity = f\"{locale.id}-{entity.id}\"\n            locale_resource = f\"{locale.id}-{entity.resource.id}\"\n            if locale_entity in translated_entities or locale_resource not in tr_pairs:\n                continue\n\n            pretranslations = get_pretranslations(entity, locale)\n\n            if not pretranslations:\n                continue\n\n            for string, plural_form, user in pretranslations:\n                t = Translation(\n                    entity=entity,\n                    locale=locale,\n                    string=string,\n                    user=user,\n                    approved=False,\n                    pretranslated=True,\n                    active=True,\n                    plural_form=plural_form,\n                )\n\n                index += 1\n                translations.append(t)\n\n                if locale_resource not in tr_dict:\n                    tr_dict[locale_resource] = index\n\n                    # Add query for fetching respective TranslatedResource.\n                    tr_filter.append(\n                        Q(locale__id=locale.id) & Q(resource__id=entity.resource.id)\n                    )\n\n                # Update the latest translation index\n                tr_dict[locale_resource] = index\n\n        log.info(f\"Fetching pretranslations for locale {locale.code} done\")\n\n    if len(translations) == 0:\n        return\n\n    translations = Translation.objects.bulk_create(translations)\n\n    # Log creating actions\n    actions_to_log = [\n        ActionLog(\n            action_type=ActionLog.ActionType.TRANSLATION_CREATED,\n            performed_by=t.user,\n            translation=t,\n        )\n        for t in translations\n    ]\n\n    ActionLog.objects.bulk_create(actions_to_log)\n\n    # Run checks on all translations\n    translation_pks = {translation.pk for translation in translations}\n    bulk_run_checks(Translation.objects.for_checks().filter(pk__in=translation_pks))\n\n    # Mark translations as changed\n    changed_translations = Translation.objects.filter(\n        pk__in=translation_pks,\n        # Do not sync translations with errors and warnings\n        errors__isnull=True,\n        warnings__isnull=True,\n    )\n    changed_translations.bulk_mark_changed()\n\n    # Update latest activity and stats for changed instances.\n    update_changed_instances(tr_filter, tr_dict, translations)\n\n    log.info(f\"Fetching pretranslations for project {project.name} done\")\n", "path": "pontoon/pretranslation/tasks.py"}]}