internlm/SWE-Fixer-Train-110K huggingface dataset:
Repository: mozilla/pontoon

Issue:
Remove aurora redirects
I just looked at our root urls.py, and saw a bunch of aurora-related redirects.

It's been ... a decade or so, let's get rid of them.

CC @flodolo 


Discussion:

Resolving patch:
diff --git a/pontoon/urls.py b/pontoon/urls.py
--- a/pontoon/urls.py
+++ b/pontoon/urls.py
@@ -22,51 +22,6 @@ class LocaleConverter(StringConverter):
 server_error_view = TemplateView.as_view(template_name="500.html")
 
 urlpatterns = [
-    # Redirect legacy Aurora projects
-    path(
-        "projects/firefox-aurora/<path:url>",
-        RedirectView.as_view(url="/projects/firefox/%(url)s", permanent=True),
-    ),
-    path(
-        "projects/firefox-for-android-aurora/<path:url>",
-        RedirectView.as_view(
-            url="/projects/firefox-for-android/%(url)s", permanent=True
-        ),
-    ),
-    path(
-        "projects/thunderbird-aurora/<path:url>",
-        RedirectView.as_view(url="/projects/thunderbird/%(url)s", permanent=True),
-    ),
-    path(
-        "projects/lightning-aurora/<path:url>",
-        RedirectView.as_view(url="/projects/lightning/%(url)s", permanent=True),
-    ),
-    path(
-        "projects/seamonkey-aurora/<path:url>",
-        RedirectView.as_view(url="/projects/seamonkey/%(url)s", permanent=True),
-    ),
-    path(
-        "<locale:locale>/firefox-aurora/<path:url>",
-        RedirectView.as_view(url="/%(locale)s/firefox/%(url)s", permanent=True),
-    ),
-    path(
-        "<locale:locale>/firefox-for-android-aurora/<path:url>",
-        RedirectView.as_view(
-            url="/%(locale)s/firefox-for-android/%(url)s", permanent=True
-        ),
-    ),
-    path(
-        "<locale:locale>/thunderbird-aurora/<path:url>",
-        RedirectView.as_view(url="/%(locale)s/thunderbird/%(url)s", permanent=True),
-    ),
-    path(
-        "<locale:locale>/lightning-aurora/<path:url>",
-        RedirectView.as_view(url="/%(locale)s/lightning/%(url)s", permanent=True),
-    ),
-    path(
-        "<locale:locale>/seamonkey-aurora/<path:url>",
-        RedirectView.as_view(url="/%(locale)s/seamonkey/%(url)s", permanent=True),
-    ),
     # Accounts
     path("accounts/", include("pontoon.allauth_urls")),
     # Admin


Test patch:
Repository: mozilla/pontoon

Issue:
Microsoft Terminology Service returning 500
Requests to Microsoft Terminology Service API used by Machinery and Concordance Search currently return "500 Internal Server Error". Let's fix that.


Discussion:

Resolving patch:
diff --git a/pontoon/machinery/views.py b/pontoon/machinery/views.py
--- a/pontoon/machinery/views.py
+++ b/pontoon/machinery/views.py
@@ -312,16 +312,20 @@ def microsoft_terminology(request):
         r.raise_for_status()
 
         translations = []
-        xpath = ".//{http://api.terminology.microsoft.com/terminology}"
+        namespaces = {"a": "https://api.terminology.microsoft.com/terminology"}
         root = ET.fromstring(r.content)
-        results = root.find(xpath + "GetTranslationsResult")
+        results = root.find(
+            ".//{http://api.terminology.microsoft.com/terminology}GetTranslationsResult"
+        )
 
         if results is not None:
             for translation in results:
                 translations.append(
                     {
-                        "source": translation.find(xpath + "OriginalText").text,
-                        "target": translation.find(xpath + "TranslatedText").text,
+                        "source": translation.find("a:OriginalText", namespaces).text,
+                        "target": translation.find(
+                            ".//a:TranslatedText", namespaces
+                        ).text,
                     }
                 )
 


Test patch:
Repository: mozilla/pontoon

Issue:
When editing existing strings in rich editor cursor jumps to the end
As reported on Matrix:

"When editing existing strings which have translations for "One" and "More", after each input, the cursor jumps to the end of the string."

The problem no longer appears after reverting back to f765fa994d71f6ea21c99dcd527ead4d0c4e1ea0.


Discussion:

Resolving patch:
diff --git a/pontoon/machinery/views.py b/pontoon/machinery/views.py
--- a/pontoon/machinery/views.py
+++ b/pontoon/machinery/views.py
@@ -128,6 +128,7 @@ def microsoft_translator(request):
     }
     body = [{"Text": text}]
 
+    r = None
     try:
         r = requests.post(url, params=payload, headers=headers, json=body)
         r.raise_for_status()
@@ -146,7 +147,7 @@ def microsoft_translator(request):
     except requests.exceptions.RequestException as e:
         return JsonResponse(
             {"status": False, "message": f"{e}"},
-            status=r.status_code,
+            status=r.status_code if r is not None else 500,
         )
 
 
@@ -207,6 +208,7 @@ def systran_translate(request):
         "format": "text",
     }
 
+    r = None
     try:
         r = requests.post(url, params=payload)
         r.raise_for_status()
@@ -225,7 +227,7 @@ def systran_translate(request):
     except requests.exceptions.RequestException as e:
         return JsonResponse(
             {"status": False, "message": f"{e}"},
-            status=r.status_code,
+            status=r.status_code if r is not None else 500,
         )
 
 
@@ -256,6 +258,7 @@ def caighdean(request):
         "foinse": "gd",
     }
 
+    r = None
     try:
         r = requests.post(url, data=data)
         r.raise_for_status()
@@ -271,7 +274,7 @@ def caighdean(request):
     except requests.exceptions.RequestException as e:
         return JsonResponse(
             {"status": False, "message": f"{e}"},
-            status=r.status_code,
+            status=r.status_code if r is not None else 500,
         )
 
 
@@ -307,6 +310,7 @@ def microsoft_terminology(request):
 
     payload = template.render(payload)
 
+    r = None
     try:
         r = requests.post(url, data=payload, headers=headers)
         r.raise_for_status()
@@ -335,5 +339,5 @@ def microsoft_terminology(request):
     except requests.exceptions.RequestException as e:
         return JsonResponse(
             {"status": False, "message": f"{e}"},
-            status=r.status_code,
+            status=r.status_code if r is not None else 500,
         )


Test patch:
Repository: mozilla/pontoon

Issue:
Add User Bio field
Reference: [spec](https://github.com/mozilla/pontoon/blob/master/specs/0111-redesign-profile-page.md)

Users should be able to provide a short bio.


Discussion:

Resolving patch:
diff --git a/pontoon/base/forms.py b/pontoon/base/forms.py
--- a/pontoon/base/forms.py
+++ b/pontoon/base/forms.py
@@ -216,6 +216,7 @@ class Meta:
         model = UserProfile
         fields = (
             "username",
+            "bio",
             "bugzilla",
             "matrix",
             "github",
diff --git a/pontoon/base/migrations/0031_userprofile_bio.py b/pontoon/base/migrations/0031_userprofile_bio.py
new file mode 100644
--- /dev/null
+++ b/pontoon/base/migrations/0031_userprofile_bio.py
@@ -0,0 +1,18 @@
+# Generated by Django 3.2.13 on 2022-08-04 14:26
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ("base", "0030_userprofile_username"),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name="userprofile",
+            name="bio",
+            field=models.TextField(blank=True, max_length=160, null=True),
+        ),
+    ]
diff --git a/pontoon/base/models.py b/pontoon/base/models.py
--- a/pontoon/base/models.py
+++ b/pontoon/base/models.py
@@ -1584,6 +1584,7 @@ class UserProfile(models.Model):
 
     # Personal information
     username = models.SlugField(unique=True, blank=True, null=True)
+    bio = models.TextField(max_length=160, blank=True, null=True)
 
     # Translation settings
     quality_checks = models.BooleanField(default=True)


Test patch:
Repository: mozilla/pontoon

Issue:
Hide Term.entity from the Add form
The `Term.entity` field should be hidden in the Add form. The [docs](https://github.com/mozilla-l10n/documentation/blob/main/src/tools/pontoon/adding_new_terminology.md) should be updated accordingly.


Discussion:

Resolving patch:
diff --git a/pontoon/terminology/admin.py b/pontoon/terminology/admin.py
--- a/pontoon/terminology/admin.py
+++ b/pontoon/terminology/admin.py
@@ -19,7 +19,6 @@ class TermAdmin(admin.ModelAdmin):
         "usage",
         "notes",
         "case_sensitive",
-        "exact_match",
         "do_not_translate",
         "forbidden",
     )
@@ -27,12 +26,22 @@ class TermAdmin(admin.ModelAdmin):
         "status",
         "part_of_speech",
         "case_sensitive",
-        "exact_match",
         "do_not_translate",
         "forbidden",
     )
     raw_id_fields = ("entity",)
 
+    def save_model(self, request, obj, form, change):
+        obj.created_by = request.user
+        obj.save()
+
+    def get_fields(self, request, obj=None):
+        fields = super().get_fields(request, obj)
+        if obj is None:
+            fields.remove("created_by")
+            fields.remove("entity")
+        return fields
+
 
 class TermTranslationAdmin(admin.ModelAdmin):
     search_fields = [
diff --git a/pontoon/terminology/migrations/0004_remove_term_exact_match.py b/pontoon/terminology/migrations/0004_remove_term_exact_match.py
new file mode 100644
--- /dev/null
+++ b/pontoon/terminology/migrations/0004_remove_term_exact_match.py
@@ -0,0 +1,17 @@
+# Generated by Django 3.2.14 on 2022-09-19 13:45
+
+from django.db import migrations
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ("terminology", "0003_auto_20200703_0710"),
+    ]
+
+    operations = [
+        migrations.RemoveField(
+            model_name="term",
+            name="exact_match",
+        ),
+    ]
diff --git a/pontoon/terminology/models.py b/pontoon/terminology/models.py
--- a/pontoon/terminology/models.py
+++ b/pontoon/terminology/models.py
@@ -80,7 +80,6 @@ class Status(models.TextChoices):
     )
 
     case_sensitive = models.BooleanField(default=False)
-    exact_match = models.BooleanField(default=False)
     do_not_translate = models.BooleanField(default=False)
     forbidden = models.BooleanField(default=False)
 


Test patch:
Repository: mozilla/pontoon

Issue:
Sync should run locales in order of locale code, not language name
*This issue was created automatically by a [script](https://github.com/mathjazz/bugzilla2github/).*
## [Bug 1703773](https://bugzilla.mozilla.org/show_bug.cgi?id=1703773)
Bug Reporter: @flodolo
CC:   @mathjazz

Currently sync runs following the alphabetical order of language names, not locale codes. That's not intuitive, and makes debugging sync issues harder.


Discussion:

Resolving patch:
diff --git a/pontoon/sync/tasks.py b/pontoon/sync/tasks.py
--- a/pontoon/sync/tasks.py
+++ b/pontoon/sync/tasks.py
@@ -187,7 +187,7 @@ def sync_translations(
         project_sync_log=project_sync_log, repository=repo, start_time=timezone.now()
     )
 
-    locales = db_project.locales.all()
+    locales = db_project.locales.order_by("code")
 
     if not locales:
         log.info(
@@ -363,6 +363,8 @@ def sync_translations(
 
         db_project.aggregate_stats()
 
+    synced_locales = sorted(synced_locales)
+
     if synced_locales:
         log.info(
             "Synced translations for project {} in locales {}.".format(


Test patch:
Repository: mozilla/pontoon

Issue:
Upgrade jQuery to v3.0
Pontoon is still using [jQuery v1.x](https://github.com/mozilla/pontoon/blob/master/pontoon/settings/base.py#L428). Since this is an [EOL/Obsolete Software](https://github.com/jquery/jquery.com/issues/162), is it possible to bump to 3.x?  Do you have this on your roadmap? 


Discussion:

Resolving patch:
diff --git a/pontoon/settings/base.py b/pontoon/settings/base.py
--- a/pontoon/settings/base.py
+++ b/pontoon/settings/base.py
@@ -425,7 +425,7 @@ def _default_from_email():
 PIPELINE_JS = {
     "base": {
         "source_filenames": (
-            "js/lib/jquery-1.11.1.min.js",
+            "js/lib/jquery-3.6.1.js",
             "js/lib/jquery.timeago.js",
             "js/lib/jquery.color-2.1.2.js",
             "js/lib/nprogress.js",
@@ -443,7 +443,6 @@ def _default_from_email():
     },
     "admin_project": {
         "source_filenames": (
-            "js/lib/jquery-ui.js",
             "js/double_list_selector.js",
             "js/multiple_team_selector.js",
             "js/admin_project.js",
@@ -519,7 +518,7 @@ def _default_from_email():
     },
     "settings": {
         "source_filenames": (
-            "js/lib/jquery-ui.js",
+            "js/lib/jquery-ui-1.13.2.js",
             "js/multiple_team_selector.js",
             "js/team_selector.js",
             "js/settings.js",


Test patch:
Repository: mozilla/pontoon

Issue:
AutoML Translate slowness, possibly on cold start
First request to AutoML Translate after deployment is very slow. It takes over 30 seconds and times out or returns 503 Service Unavailable. After timeout or 503 the response starts getting back in a reasonable amount of time. 

If you switch between strings without waiting for 30 seconds for the request to complete (very likely), the request will be interrupted and the slow scenario will repeat in the next string. You'll never get a response from the service, unless the slow request (sometimes more than one) completes.

To make things worse, after you stop using AutoML Translate for a while, you again need to wait for a response for such a long time before it starts completing in a reasonable amount of time.

It seems like the service needs to perform a cold start every now and then. And that's for each locale separately: each locale needs to "warms up" the service separately.


Discussion:

Resolving patch:
diff --git a/pontoon/machinery/management/__init__.py b/pontoon/machinery/management/__init__.py
new file mode 100644
diff --git a/pontoon/machinery/management/commands/__init__.py b/pontoon/machinery/management/commands/__init__.py
new file mode 100644
diff --git a/pontoon/machinery/management/commands/warm_up_automl_models.py b/pontoon/machinery/management/commands/warm_up_automl_models.py
new file mode 100644
--- /dev/null
+++ b/pontoon/machinery/management/commands/warm_up_automl_models.py
@@ -0,0 +1,39 @@
+import logging
+
+from django.core.management.base import BaseCommand
+
+from pontoon.base.models import Locale
+from pontoon.machinery.utils import get_google_automl_translation
+
+
+log = logging.getLogger(__name__)
+
+
+class Command(BaseCommand):
+    help = """
+        The Google AutoML Translation has latency of ~15s caused by the loading time of
+        a custom model into the chip. Since there are replicas, the high tail latency
+        occurs for first N requests - one replica may successfully load the model, but
+        the request may be routed to other replicas which are still loading. Once all
+        replicas load the model, the normal latency should be 200 - 500ms.
+
+        Also, since the chips are shared with other models, models gets evicted from the
+        chips if they aren't used for a longer period of time, resulting in high latency
+        on the next following request.
+
+        To keep latency low, we need to make regular dummy warm-up requests using this
+        management command, which needs to run at least every 10 minutes.
+
+        See https://github.com/mozilla/pontoon/issues/2655 for more details.
+        """
+
+    def handle(self, *args, **options):
+        log.info("Google AutoML Warmup process started.")
+
+        locales = Locale.objects.exclude(google_automl_model="").order_by("code")
+
+        for locale in locales:
+            get_google_automl_translation("t", locale)
+            log.info(f"Google AutoML Warmup for {locale.code} complete.")
+
+        log.info("Google AutoML Warmup process complete for all locales.")


Test patch:
Repository: mozilla/pontoon

Issue:
Entities of mass deleted terms do not get obsolete
When terms are deleted from the Django Admin, we [obsolete corresponding Entities](https://github.com/mozilla/pontoon/blob/01cddfd0df2f5ddf85d1b5e26a13003f9f320d97/pontoon/terminology/models.py#L239). However, this function doesn't trigger in mass delete actions, which results in the following error when trying to translate deleted Terms:

```
RelatedObjectDoesNotExist: Entity has no term
```


Discussion:

Resolving patch:
diff --git a/pontoon/terminology/models.py b/pontoon/terminology/models.py
--- a/pontoon/terminology/models.py
+++ b/pontoon/terminology/models.py
@@ -52,6 +52,16 @@ def for_string(self, string):
 
         return terms
 
+    def delete(self, *args, **kwargs):
+        """
+        Before deleting Terms, obsolete their Entities
+        """
+        for term in self:
+            term.obsolete_entity()
+        update_terminology_project_stats()
+
+        super().delete(*args, **kwargs)
+
 
 class Term(models.Model):
     text = models.CharField(max_length=255)


Test patch:
Repository: mozilla/pontoon

Issue:
en-GB team get notified of approvals from Tutorial
In the last 24 hours I have had a notification through for an approval in Tutorial, I don't remember seeing one before:
[Alexander](https://pontoon.mozilla.org/contributors/5qvmInirgyG9G9tHuWsA88tEqsc/) has made their first contribution to [English (Great Britain) (en-GB)](https://pontoon.mozilla.org/en-GB/). Please welcome them to the team, and make sure to [review their suggestions](https://pontoon.mozilla.org/en-GB/tutorial/playground/?string=209140).


Discussion:

Resolving patch:
diff --git a/pontoon/base/models.py b/pontoon/base/models.py
--- a/pontoon/base/models.py
+++ b/pontoon/base/models.py
@@ -290,7 +290,11 @@ def can_translate(self, locale, project):
 
 def is_new_contributor(self, locale):
     """Return True if the user hasn't made contributions to the locale yet."""
-    return not self.translation_set.filter(locale=locale).exists()
+    return (
+        not self.translation_set.filter(locale=locale)
+        .exclude(entity__resource__project__system_project=True)
+        .exists()
+    )
 
 
 @property
diff --git a/pontoon/translations/views.py b/pontoon/translations/views.py
--- a/pontoon/translations/views.py
+++ b/pontoon/translations/views.py
@@ -80,7 +80,6 @@ def create_translation(request):
     # Checks are disabled for the tutorial.
     use_checks = project.slug != "tutorial"
     user = request.user
-    first_contribution = user.is_new_contributor(locale)
 
     failed_checks = None
     if use_checks:
@@ -126,6 +125,7 @@ def create_translation(request):
         )
 
     # When user makes their first contribution to the team, notify team managers
+    first_contribution = not project.system_project and user.is_new_contributor(locale)
     if first_contribution:
         desc = """
         <a href="{user_href}">{user}</a> has made their first contribution to


Test patch:
Repository: mozilla/pontoon

Issue:
Notification link for new strings should include pre-translated strings
Right now I'm getting notifications for new strings, but it's empty, because they're not missing but pre-translated.

The long term fix would be to link to strings actually added when the notification is sent, independently from their current status (I think there is an issue on file for it). A short term fix is to include both `status=missing,pretranslated` in the link.


Discussion:

Resolving patch:
diff --git a/pontoon/base/models.py b/pontoon/base/models.py
--- a/pontoon/base/models.py
+++ b/pontoon/base/models.py
@@ -349,7 +349,7 @@ def serialized_notifications(self):
                             "part": "all-resources",
                         },
                     )
-                    + "?status=missing",
+                    + "?status=missing,pretranslated",
                 }
             else:
                 actor = {


Test patch:
Repository: mozilla/pontoon

Issue:
Show "All contributions" by default when accessing own profile
We currently use "Suggestions and reviews" as the default contribution type filter on the profile page. That allows managers, admins and also external users (e.g. employers) to get a quick overview over user's own activity right after the page is loaded.

But when the user is looking at their own profile, they are more likely interested in "All contributions", which also includes activity of other users on their translations (received reviews).

Such page has a potential to be used as the user homepage, because it aggregates all recent activity relevant for the user in one place.


Discussion:

Resolving patch:
diff --git a/pontoon/contributors/views.py b/pontoon/contributors/views.py
--- a/pontoon/contributors/views.py
+++ b/pontoon/contributors/views.py
@@ -51,8 +51,12 @@ def contributor_username(request, username):
 
 def contributor(request, user):
     """Contributor profile."""
-    graph_data, graph_title = utils.get_contribution_graph_data(user)
-    timeline_data, timeline_title = utils.get_contribution_timeline_data(user)
+    graph_data, graph_title = utils.get_contribution_graph_data(
+        user, "all_contributions"
+    )
+    timeline_data, timeline_title = utils.get_contribution_timeline_data(
+        user, "all_contributions"
+    )
 
     context = {
         "contributor": user,


Test patch:
Repository: mozilla/pontoon

Issue:
CC requester to the email sent when requesting a new project
Hopefully that will reduce the number of duplicate requests we receive.


Discussion:

Resolving patch:
diff --git a/pontoon/base/models.py b/pontoon/base/models.py
--- a/pontoon/base/models.py
+++ b/pontoon/base/models.py
@@ -119,6 +119,11 @@ def user_name_or_email(self):
     return self.first_name or self.email
 
 
+@property
+def user_contact_email(self):
+    return self.profile.contact_email or self.email
+
+
 @property
 def user_display_name(self):
     return self.first_name or self.email.split("@")[0]
@@ -456,6 +461,7 @@ def latest_action(self):
 User.add_to_class("gravatar_url", user_gravatar_url)
 User.add_to_class("gravatar_url_small", user_gravatar_url_small)
 User.add_to_class("name_or_email", user_name_or_email)
+User.add_to_class("contact_email", user_contact_email)
 User.add_to_class("display_name", user_display_name)
 User.add_to_class("display_name_and_email", user_display_name_and_email)
 User.add_to_class("display_name_or_blank", user_display_name_or_blank)
diff --git a/pontoon/teams/views.py b/pontoon/teams/views.py
--- a/pontoon/teams/views.py
+++ b/pontoon/teams/views.py
@@ -221,7 +221,7 @@ def request_item(request, locale=None):
         # Validate projects
         project_list = (
             Project.objects.visible()
-            .visible_for(request.user)
+            .visible_for(user)
             .filter(slug__in=slug_list, can_be_requested=True)
         )
         if not project_list:
@@ -270,18 +270,19 @@ def request_item(request, locale=None):
     if settings.PROJECT_MANAGERS[0] != "":
         template = get_template("teams/email_request_item.jinja")
         mail_body = template.render(payload)
+        cc = {user.contact_email}
+        if locale:
+            cc.update(
+                set(locale.managers_group.user_set.values_list("email", flat=True))
+            )
 
         EmailMessage(
             subject=mail_subject,
             body=mail_body,
             from_email=settings.LOCALE_REQUEST_FROM_EMAIL,
             to=settings.PROJECT_MANAGERS,
-            cc=locale.managers_group.user_set.exclude(pk=user.pk).values_list(
-                "email", flat=True
-            )
-            if locale
-            else "",
-            reply_to=[user.email],
+            cc=cc,
+            reply_to=[user.contact_email],
         ).send()
     else:
         raise ImproperlyConfigured(


Test patch: