Repository: WeblateOrg/weblate

Issue:
Update google-cloud-translate requirement from <2.1.0,>=2.0.1 to >=2.0.1,<3.1.0
Updates the requirements on [google-cloud-translate](https://github.com/googleapis/python-translate) to permit the latest version.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a href="https://github.com/googleapis/python-translate/releases">google-cloud-translate's releases</a>.</em></p>
<blockquote>
<h2>v3.0.0</h2>
<h3>⚠ BREAKING CHANGES</h3>
<ul>
<li>migrate API to microgenerator (<a href="https://github-redirect.dependabot.com/googleapis/python-translate/issues/31">#31</a>)</li>
</ul>
<h3>Features</h3>
<ul>
<li>migrate API to microgenerator (<a href="https://www.github-redirect.dependabot.com/googleapis/python-translate/issues/31">#31</a>) (<a href="https://www.github.com/googleapis/python-translate/commit/1c5b6e89a0a3b55c41c909e4ee27e0bd23e4b579">1c5b6e8</a>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a href="https://github.com/googleapis/python-translate/blob/master/CHANGELOG.md">google-cloud-translate's changelog</a>.</em></p>
<blockquote>
<h2><a href="https://www.github.com/googleapis/python-translate/compare/v2.0.2...v3.0.0">3.0.0</a> (2020-08-05)</h2>
<h3>⚠ BREAKING CHANGES</h3>
<ul>
<li>migrate API to microgenerator (<a href="https://github-redirect.dependabot.com/googleapis/python-translate/issues/31">#31</a>)</li>
</ul>
<h3>Features</h3>
<ul>
<li>migrate API to microgenerator (<a href="https://www.github-redirect.dependabot.com/googleapis/python-translate/issues/31">#31</a>) (<a href="https://www.github.com/googleapis/python-translate/commit/1c5b6e89a0a3b55c41c909e4ee27e0bd23e4b579">1c5b6e8</a>)</li>
</ul>
<h3><a href="https://www.github.com/googleapis/python-translate/compare/v2.0.1...v2.0.2">2.0.2</a> (2020-08-03)</h3>
<h3>Bug Fixes</h3>
<ul>
<li>refactored MP3 file creation test for Hybrid glossaries samples [(<a href="https://www.github-redirect.dependabot.com/googleapis/python-translate/issues/2379">#2379</a>)](<a href="https://github-redirect.dependabot.com/GoogleCloudPlatform/python-docs-samples/issues/2379">GoogleCloudPlatform/python-docs-samples#2379</a>) (<a href="https://www.github.com/googleapis/python-translate/commit/b8b5101be28d0d0d17a4d688eea81af6754a394c">b8b5101</a>)</li>
<li>translate test [(<a href="https://www.github-redirect.dependabot.com/googleapis/python-translate/issues/2671">#2671</a>)](<a href="https://github-redirect.dependabot.com/GoogleCloudPlatform/python-docs-samples/issues/2671">GoogleCloudPlatform/python-docs-samples#2671</a>) (<a href="https://www.github.com/googleapis/python-translate/commit/a3d9f804576caeb4fdcdbbd4479caeb926efd8d0">a3d9f80</a>)</li>
<li>update default retry config (<a href="https://www.github-redirect.dependabot.com/googleapis/python-translate/issues/15">#15</a>) (<a href="https://www.github.com/googleapis/python-translate/commit/dddf0bf33463968932031cc0be5bc8a0d4a96455">dddf0bf</a>)</li>
</ul>
<h3><a href="https://www.github.com/googleapis/python-translate/compare/v2.0.0...v2.0.1">2.0.1</a> (2020-01-31)</h3>
<h3>Bug Fixes</h3>
<ul>
<li><strong>translate:</strong>  add py2 deprecation warning; bump copyright year to 2020; add 3.8 unit tests (via synth) (<a href="https://www.github-redirect.dependabot.com/googleapis/python-translate/issues/9943">#9943</a>) (<a href="https://www.github.com/googleapis/python-translate/commit/b57f09a5f804daca1a96918a29746f24ae7bc4a5">b57f09a</a>)</li>
<li><strong>translate:</strong> update test assertion and core version pins (<a href="https://www.github-redirect.dependabot.com/googleapis/python-translate/issues/10098">#10098</a>) (<a href="https://www.github.com/googleapis/python-translate/commit/74b77579a1770c743353bdafde3e1744cbbe7842">74b7757</a>)</li>
</ul>
<h2>2.0.0</h2>
<p>10-23-2019 11:13 PDT</p>
<h3>New Features</h3>
<ul>
<li>Make v3 the default client. (<a href="https://github-redirect.dependabot.com/googleapis/google-cloud-python/pull/9498">#9498</a>)</li>
</ul>
<h3>Internal / Testing Changes</h3>
<ul>
<li>Add VPC-SC system tests. (<a href="https://github-redirect.dependabot.com/googleapis/google-cloud-python/pull/9272">#9272</a>)</li>
</ul>
<h2>1.7.0</h2>
<p>10-07-2019 14:57 PDT</p>
<h3>Implementation Changes</h3>
<ul>
<li>Update docstrings, client confg (via synth). (<a href="https://github-redirect.dependabot.com/googleapis/google-cloud-python/pull/9411">#9411</a>)</li>
<li>Remove send / receive message size limit (via synth). (<a href="https://github-redirect.dependabot.com/googleapis/google-cloud-python/pull/8974">#8974</a>)</li>
</ul>
<h3>New Features</h3>
<ul>
<li>Add support for V3 of the API. (<a href="https://github-redirect.dependabot.com/googleapis/google-cloud-python/pull/9020">#9020</a>)</li>
<li>Make <code>parent</code> argument required for all client methods in v3beta1; add <code>labels</code> argument (via synth). (<a href="https://github-redirect.dependabot.com/googleapis/google-cloud-python/pull/9354">#9354</a>)</li>
<li>Add client options to translate_v2. (<a href="https://github-redirect.dependabot.com/googleapis/google-cloud-python/pull/8737">#8737</a>)</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a href="https://github.com/googleapis/python-translate/commit/3758c8fc27e7ef052e215c720c5d64a8cb349bf1"><code>3758c8f</code></a> chore: release 3.0.0 (<a href="https://github-redirect.dependabot.com/googleapis/python-translate/issues/36">#36</a>)</li>
<li><a href="https://github.com/googleapis/python-translate/commit/7fd7fbd82bdd878aee4aae9750f0e0fd07bb80f0"><code>7fd7fbd</code></a> chore: config template changes from synthtool (<a href="https://github-redirect.dependabot.com/googleapis/python-translate/issues/35">#35</a>)</li>
<li><a href="https://github.com/googleapis/python-translate/commit/1c5b6e89a0a3b55c41c909e4ee27e0bd23e4b579"><code>1c5b6e8</code></a> feat!: migrate API to microgenerator (<a href="https://github-redirect.dependabot.com/googleapis/python-translate/issues/31">#31</a>)</li>
<li><a href="https://github.com/googleapis/python-translate/commit/e5182377b07c376a78b9e6c9ca71fa64dc82bd3e"><code>e518237</code></a> chore: release 2.0.2 (<a href="https://github-redirect.dependabot.com/googleapis/python-translate/issues/23">#23</a>)</li>
<li><a href="https://github.com/googleapis/python-translate/commit/82d4b2e8e6cd0aa18cbf0d362b298cfd4f284641"><code>82d4b2e</code></a> chore(deps): update ubuntu docker tag to v20.10 (<a href="https://github-redirect.dependabot.com/googleapis/python-translate/issues/29">#29</a>)</li>
<li><a href="https://github.com/googleapis/python-translate/commit/c96ca49f76c98206c13cc19b7c07a43febcd4334"><code>c96ca49</code></a> chore: updates build templates (docs-presubmit) (<a href="https://github-redirect.dependabot.com/googleapis/python-translate/issues/28">#28</a>)</li>
<li><a href="https://github.com/googleapis/python-translate/commit/51cf8a6b2d215281350d80c0a007a14db7cff887"><code>51cf8a6</code></a> chore(deps): update dependency google-cloud-storage to v1.30.0 (<a href="https://github-redirect.dependabot.com/googleapis/python-translate/issues/26">#26</a>)</li>
<li><a href="https://github.com/googleapis/python-translate/commit/3aad1dae70b7b2ca15fcbcdefe1966181e8bb4a1"><code>3aad1da</code></a> chore: narrows samples CODEOWNERS to .py only</li>
<li><a href="https://github.com/googleapis/python-translate/commit/5526dd2ccaaebf27a09ef36f0b0b76a908ad064d"><code>5526dd2</code></a> chore: update templates</li>
<li><a href="https://github.com/googleapis/python-translate/commit/1352496f8b76e34e85d5ad66befa42d972c32ed2"><code>1352496</code></a> testing(translate): bump the timeout for operations [(<a href="https://github-redirect.dependabot.com/googleapis/python-translate/issues/4258">#4258</a>)](<a href="https://github">https://github</a>....</li>
<li>Additional commits viewable in <a href="https://github.com/googleapis/python-translate/compare/v2.0.1...v3.0.0">compare view</a></li>
</ul>
</details>
<br />


Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
- `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)


</details>


Discussion:
The code needs rewrite for new version, see https://googleapis.dev/python/translation/latest/UPGRADING.html
This pull request has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.


Resolving patch:
diff --git a/weblate/machinery/googlev3.py b/weblate/machinery/googlev3.py
--- a/weblate/machinery/googlev3.py
+++ b/weblate/machinery/googlev3.py
@@ -35,33 +35,35 @@ class GoogleV3Translation(GoogleBaseTranslation):
     def __init__(self):
         """Check configuration."""
         super().__init__()
-        if settings.MT_GOOGLE_CREDENTIALS is None or settings.MT_GOOGLE_PROJECT is None:
+        credentials = settings.MT_GOOGLE_CREDENTIALS
+        project = settings.MT_GOOGLE_PROJECT
+        location = settings.MT_GOOGLE_LOCATION
+
+        if credentials is None or project is None:
             raise MissingConfiguration("Google Translate requires API key and project")
 
-        credentials = service_account.Credentials.from_service_account_file(
-            settings.MT_GOOGLE_CREDENTIALS
-        )
+        credentials = service_account.Credentials.from_service_account_file(credentials)
 
         self.client = TranslationServiceClient(credentials=credentials)
-        self.parent = self.client.location_path(
-            settings.MT_GOOGLE_PROJECT, settings.MT_GOOGLE_LOCATION
-        )
+        self.parent = f"projects/{project}/locations/{location}"
 
     def download_languages(self):
         """List of supported languages."""
-        return [
-            language.language_code
-            for language in self.client.get_supported_languages(self.parent).languages
-        ]
+        response = self.client.get_supported_languages(request={"parent": self.parent})
+        return [language.language_code for language in response.languages]
 
     def download_translations(self, source, language, text, unit, user, search):
         """Download list of possible translations from a service."""
-        trans = self.client.translate_text(
-            [text], language, self.parent, source_language_code=source
-        )
+        request = {
+            "parent": self.parent,
+            "contents": [text],
+            "target_language_code": language,
+            "source_language_code": source,
+        }
+        response = self.client.translate_text(request)
 
         yield {
-            "text": trans.translations[0].translated_text,
+            "text": response.translations[0].translated_text,
             "quality": self.max_score,
             "service": self.name,
             "source": text,


Test patch:
diff --git a/weblate/machinery/tests.py b/weblate/machinery/tests.py
--- a/weblate/machinery/tests.py
+++ b/weblate/machinery/tests.py
@@ -27,6 +27,11 @@
 from django.conf import settings
 from django.test import TestCase
 from django.test.utils import override_settings
+from google.cloud.translate_v3 import (
+    SupportedLanguages,
+    TranslateTextResponse,
+    TranslationServiceClient,
+)
 
 from weblate.checks.tests.test_checks import MockUnit
 from weblate.machinery.apertium import ApertiumAPYTranslation
@@ -664,28 +669,33 @@ def mock_error(self):
         raise SkipTest("Not tested")
 
     def mock_response(self):
-        # TODO: Patch methods instead of our own ones:
-        # google.cloud.translate_v3.gapic.translation_service_client
-        # .TranslationServiceClient.{translate_text,get_supported_languages}
+        # Mock get supported languages
         patcher = patch.object(
-            GoogleV3Translation,
-            "download_languages",
-            Mock(return_value=["cs", "en", "es"]),
+            TranslationServiceClient,
+            "get_supported_languages",
+            Mock(
+                return_value=SupportedLanguages(
+                    {
+                        "languages": [
+                            {"language_code": "cs"},
+                            {"language_code": "en"},
+                            {"language_code": "es"},
+                        ]
+                    }
+                )
+            ),
         )
         patcher.start()
         self.addCleanup(patcher.stop)
+
+        # Mock translate
         patcher = patch.object(
-            GoogleV3Translation,
-            "download_translations",
+            TranslationServiceClient,
+            "translate_text",
             Mock(
-                return_value=[
-                    {
-                        "text": "Ahoj",
-                        "quality": 90,
-                        "service": "Google Translate API v3",
-                        "source": "Hello",
-                    }
-                ]
+                return_value=TranslateTextResponse(
+                    {"translations": [{"translated_text": "Ahoj"}]}
+                ),
             ),
         )
         patcher.start()