From 90b2f3270abdc56836874f8e970d2e4e4d4dff09 Mon Sep 17 00:00:00 2001 From: Dan Goje Date: Mon, 18 Jan 2021 08:50:50 +0000 Subject: [PATCH 1/2] fix: update microsoft provider api version --- translate/providers/microsoft.py | 65 ++++++++------------------------ 1 file changed, 16 insertions(+), 49 deletions(-) diff --git a/translate/providers/microsoft.py b/translate/providers/microsoft.py index 368dfd8..c4bbefd 100644 --- a/translate/providers/microsoft.py +++ b/translate/providers/microsoft.py @@ -3,51 +3,12 @@ from datetime import timedelta from datetime import datetime -from lxml import etree import requests +import json from .base import BaseProvider from ..constants import TRANSLATION_FROM_DEFAULT - -class AzureAuthClient: - """ - Provides a client for obtaining an OAuth token from the authentication service - for Microsoft Translator in Azure Cognitive Services. - - PS: - token field is used to store the last token obtained from the token service - the cached token is re-used until the time specified in reuse_token_until. - """ - base_url = 'https://api.cognitive.microsoft.com/sts/v1.0/issueToken' - - def __init__(self, client_secret): - self.client_secret = client_secret - self.token = None - self.reuse_token_until = None - - def get_access_token(self): - ''' - Returns an access token for the specified subscription. - - This method uses a cache to limit the number of requests to the token service. - A fresh token can be re-used during its lifetime of 10 minutes. After a successful - request to the token service, this method caches the access token. Subsequent - invocations of the method return the cached token for the next 5 minutes. After - 5 minutes, a new token is fetched from the token service and the cache is updated. - ''' - - if (self.token is None) or (datetime.utcnow() > self.reuse_token_until): - headers = {'Ocp-Apim-Subscription-Key': self.client_secret} - response = requests.post(self.base_url, headers=headers) - response.raise_for_status() - - self.token = response.content - self.reuse_token_until = datetime.utcnow() + timedelta(minutes=5) - - return self.token.decode('utf-8') - - class MicrosoftProvider(BaseProvider): ''' @MicrosoftProvider: This is a integration with Microsoft Translator API. @@ -55,23 +16,29 @@ class MicrosoftProvider(BaseProvider): Documentation: http://docs.microsofttranslator.com/text-translate.html ''' name = 'Microsoft' - base_url = 'http://api.microsofttranslator.com/v2/Http.svc/Translate' + base_url = 'https://api.cognitive.microsofttranslator.com/translate' def _make_request(self, text): - auth_client = AzureAuthClient(self.secret_access_key) - access_token = 'Bearer {}'.format(auth_client.get_access_token()) - self.headers.update({"Authorization ": access_token}) + self.headers.update({"Ocp-Apim-Subscription-Key": self.secret_access_key}) + self.headers.update({"Ocp-Apim-Subscription-Region": "westeurope"}) + + params = { + 'to': self.to_lang, + 'api-version': '3.0' + } + + data = [{ + 'text': text + }] - params = {'text': text, 'to': self.to_lang} if self.from_lang != TRANSLATION_FROM_DEFAULT: params['from'] = self.from_lang - response = requests.get(self.base_url, params=params, headers=self.headers) + response = requests.post(self.base_url, params=params, headers=self.headers, json=data) - return response.text + return json.loads(response.text) def get_translation(self, text): data = self._make_request(text) - translation = etree.fromstring(data.encode('utf-8')) - return translation.text + return data[0]["translations"][0]["text"] From e4256bdb8520f7ed8ba9daa93b8ce1aecf953c29 Mon Sep 17 00:00:00 2001 From: Dan Goje Date: Mon, 18 Jan 2021 09:01:59 +0000 Subject: [PATCH 2/2] fix: parameterise microsoft translator api region --- translate/exceptions.py | 3 +++ translate/providers/base.py | 3 ++- translate/providers/microsoft.py | 7 ++++++- translate/translate.py | 3 ++- 4 files changed, 13 insertions(+), 3 deletions(-) diff --git a/translate/exceptions.py b/translate/exceptions.py index fa54703..0acb969 100644 --- a/translate/exceptions.py +++ b/translate/exceptions.py @@ -1,2 +1,5 @@ class InvalidProviderError(Exception): pass + +class TranslationError(Exception): + pass \ No newline at end of file diff --git a/translate/providers/base.py b/translate/providers/base.py index 9d899da..aa9a7d4 100644 --- a/translate/providers/base.py +++ b/translate/providers/base.py @@ -10,12 +10,13 @@ class BaseProvider: name = '' base_url = '' - def __init__(self, to_lang, from_lang='en', secret_access_key=None, **kwargs): + def __init__(self, to_lang, from_lang='en', secret_access_key=None, region=None, **kwargs): self.headers = {'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_6_8) AppleWebit/535.19' '(KHTML, like Gecko) Chrome/18.0.1025.168 Safari/535.19'} self.from_lang = from_lang self.to_lang = to_lang self.secret_access_key = secret_access_key + self.region = region @abstractmethod def get_translation(self, params): diff --git a/translate/providers/microsoft.py b/translate/providers/microsoft.py index c4bbefd..345ebed 100644 --- a/translate/providers/microsoft.py +++ b/translate/providers/microsoft.py @@ -8,6 +8,7 @@ from .base import BaseProvider from ..constants import TRANSLATION_FROM_DEFAULT +from ..exceptions import TranslationError class MicrosoftProvider(BaseProvider): ''' @@ -20,7 +21,8 @@ class MicrosoftProvider(BaseProvider): def _make_request(self, text): self.headers.update({"Ocp-Apim-Subscription-Key": self.secret_access_key}) - self.headers.update({"Ocp-Apim-Subscription-Region": "westeurope"}) + if self.region is not None: + self.headers.update({"Ocp-Apim-Subscription-Region": "westeurope"}) params = { 'to': self.to_lang, @@ -41,4 +43,7 @@ def _make_request(self, text): def get_translation(self, text): data = self._make_request(text) + if "error" in data: + raise TranslationError(data["error"]["message"]) + return data[0]["translations"][0]["text"] diff --git a/translate/translate.py b/translate/translate.py index 17e6d14..be71550 100644 --- a/translate/translate.py +++ b/translate/translate.py @@ -15,7 +15,7 @@ class Translator: - def __init__(self, to_lang, from_lang='en', provider=None, secret_access_key=None, **kwargs): + def __init__(self, to_lang, from_lang='en', provider=None, secret_access_key=None, region=None, **kwargs): self.available_providers = list(PROVIDERS_CLASS.keys()) self.from_lang = from_lang self.to_lang = to_lang @@ -31,6 +31,7 @@ def __init__(self, to_lang, from_lang='en', provider=None, secret_access_key=Non from_lang=from_lang, to_lang=to_lang, secret_access_key=secret_access_key, + region=region, **kwargs )