Repository: WeblateOrg/weblate

Issue:
Automatic translation trigger via API
**Is your feature request related to a problem? Please describe.**
I would like to trigger auto translation for a language based on `Translation Memory`. Currently I add a new language for the component via API and then manually apply the auto translation for the language.

**Describe the solution you'd like**
I would like to have an API which could trigger auto translation for the strings listed under a language under a translation component. Maybe under the component APIs.

**Additional context**
The auto-translation parameters and action is available in the GUI at Project -> Component -> Language -> Tools -> Automatic Translation
<img width="1422" alt="Screenshot 2020-05-22 at 11 08 14 AM" src="https://user-images.githubusercontent.com/3179427/82634932-ad602c80-9c1c-11ea-858d-5f6455b588ab.png">

Split of https://github.com/WeblateOrg/weblate/issues/3930


Discussion:
Desired implementation:

* New POST endpoint `/api/translations/(string: project)/(string: component)/(string: language)/autotranslate/`
* The request shall be parsed using AutoForm to reuse existing validation logic
* The code for UI view is at `weblate.trans.views.edit.auto_translation`
* Documentation should cover all parameters
* Test for triggered autotranslation and invalid params

Resolving patch:
diff --git a/weblate/api/views.py b/weblate/api/views.py
--- a/weblate/api/views.py
+++ b/weblate/api/views.py
@@ -66,6 +66,7 @@
 from weblate.formats.exporters import EXPORTERS
 from weblate.lang.models import Language
 from weblate.screenshots.models import Screenshot
+from weblate.trans.forms import AutoForm
 from weblate.trans.models import (
     Change,
     Component,
@@ -76,7 +77,7 @@
     Unit,
 )
 from weblate.trans.stats import get_project_stats
-from weblate.trans.tasks import component_removal, project_removal
+from weblate.trans.tasks import auto_translate, component_removal, project_removal
 from weblate.utils.celery import get_queue_stats
 from weblate.utils.docs import get_doc_url
 from weblate.utils.errors import report_error
@@ -927,6 +928,35 @@ def units(self, request, **kwargs):
 
         return self.get_paginated_response(serializer.data)
 
+    @action(detail=True, methods=["post"])
+    def autotranslate(self, request, **kwargs):
+        translation = self.get_object()
+        if not request.user.has_perm("translation.auto", translation):
+            self.permission_denied(request, message="Can not auto translate")
+        autoform = AutoForm(translation.component, request.data)
+        if translation.component.locked or not autoform.is_valid():
+            return Response(
+                data={
+                    "result": "Unsuccessful",
+                    "detail": "Failed to process autotranslation data!",
+                },
+                status=status.HTTP_400_BAD_REQUEST,
+            )
+        args = (
+            request.user.id,
+            translation.id,
+            autoform.cleaned_data["mode"],
+            autoform.cleaned_data["filter_type"],
+            autoform.cleaned_data["auto_source"],
+            autoform.cleaned_data["component"],
+            autoform.cleaned_data["engines"],
+            autoform.cleaned_data["threshold"],
+        )
+        return Response(
+            data={"result": "Success", "details": auto_translate(*args)},
+            status=status.HTTP_200_OK,
+        )
+
     def destroy(self, request, *args, **kwargs):
         instance = self.get_object()
         if not request.user.has_perm("translation.delete", instance):


Test patch:
diff --git a/weblate/api/tests.py b/weblate/api/tests.py
--- a/weblate/api/tests.py
+++ b/weblate/api/tests.py
@@ -1498,6 +1498,39 @@ def test_units(self):
         request = self.do_request("api:translation-units", self.translation_kwargs)
         self.assertEqual(request.data["count"], 4)
 
+    def test_autotranslate(self):
+        self.do_request(
+            "api:translation-autotranslate",
+            self.translation_kwargs,
+            method="post",
+            request={"mode": "invalid"},
+            code=403,
+        )
+        self.do_request(
+            "api:translation-autotranslate",
+            self.translation_kwargs,
+            superuser=True,
+            method="post",
+            request={"mode": "invalid"},
+            code=400,
+        )
+        response = self.do_request(
+            "api:translation-autotranslate",
+            self.translation_kwargs,
+            superuser=True,
+            method="post",
+            request={
+                "mode": "suggest",
+                "filter_type": "todo",
+                "auto_source": "others",
+                "threshold": "100",
+            },
+            code=200,
+        )
+        self.assertContains(
+            response, "Automatic translation completed",
+        )
+
     def test_add_monolingual(self):
         self.create_acl()
         self.do_request(