File size: 5,507 Bytes
8d368b7 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 |
# -*- coding: utf-8 -*-
import requests
# import uuid
import logging
import sys
from deep_translator.constants import BASE_URLS, MICROSOFT_CODES_TO_LANGUAGES
from deep_translator.exceptions import LanguageNotSupportedException, ServerException, MicrosoftAPIerror
class MicrosoftTranslator:
"""
the class that wraps functions, which use the Microsoft translator under the hood to translate word(s)
"""
_languages = MICROSOFT_CODES_TO_LANGUAGES
supported_languages = list(_languages.values())
def __init__(self, api_key=None, region=None, source=None, target=None, **kwargs):
"""
@params api_key and target are the required params
@param api_key: your Microsoft API key
@param region: your Microsoft Location
"""
if not api_key:
raise ServerException(401)
else:
self.api_key = api_key
self.headers = {
"Ocp-Apim-Subscription-Key": self.api_key,
"Content-type": "application/json",
}
# region is not required but very common and goes to headers if passed
if region:
self.region = region
self.headers["Ocp-Apim-Subscription-Region"] = self.region
if not target:
raise ServerException(401)
else:
if type(target) is str:
self.target = target.lower()
else:
self.target = [i.lower() for i in target]
if self.is_language_supported(self.target):
self.target = self._map_language_to_code(self.target)
self.url_params = {'to': self.target, **kwargs}
if source:
self.source = source.lower()
if self.is_language_supported(self.source):
self.source = self._map_language_to_code(self.source)
self.url_params['from'] = self.source
self.__base_url = BASE_URLS.get("MICROSOFT_TRANSLATE")
@staticmethod
def get_supported_languages(as_dict=False):
"""
return the languages supported by the microsoft translator
@param as_dict: if True, the languages will be returned as a dictionary mapping languages to their abbreviations
@return: list or dict
"""
return MicrosoftTranslator.supported_languages if not as_dict else MicrosoftTranslator._languages
def _map_language_to_code(self, language):
"""
map the language to its corresponding code (abbreviation) if the language was passed by its full name by the user
@param languages: a string (if 1 lang) or a list (if multiple langs)
@return: mapped value of the language or raise an exception if the language is not supported
"""
if type(language) is str:
language = [language]
for lang in language:
if lang in self._languages.values():
yield lang
elif lang in self._languages.keys():
yield self._languages[lang]
else:
raise LanguageNotSupportedException(lang)
def is_language_supported(self, language):
"""
check if the language is supported by the translator
@param languages: a string (if 1 lang) or a list (if multiple langs)
@return: bool or raise an Exception
"""
if type(language) is str:
language = [language]
for lang in language:
if lang not in self._languages.keys():
if lang not in self._languages.values():
raise LanguageNotSupportedException(lang)
return True
def translate(self, text):
"""
function that uses microsoft translate to translate a text
@param text: desired text to translate
@return: str: translated text
"""
# a body must be a list of dicts to process multiple texts;
# I have not added multiple text processing here since it is covered by the translate_batch method
valid_microsoft_json = [{'text': text}]
try:
requested = requests.post(self.__base_url, params=self.url_params, headers=self.headers, json=valid_microsoft_json)
except requests.exceptions.RequestException:
exc_type, value, traceback = sys.exc_info()
logging.warning(f"Returned error: {exc_type.__name__}")
# Where Microsoft API responds with an api error, it returns a dict in response.json()
if type(requested.json()) is dict:
error_message = requested.json()['error']
raise MicrosoftAPIerror(error_message)
# Where it responds with a translation, its response.json() is a list e.g. [{'translations': [{'text': 'Hello world!', 'to': 'en'}]}]
elif type(requested.json()) is list:
all_translations = [i['text'] for i in requested.json()[0]['translations']]
return "\n".join(all_translations)
def translate_file(self, path):
"""
translate from a file
@param path: path to file
@return: translated text
"""
try:
with open(path) as f:
text = f.read()
return self.translate(text)
except Exception as e:
raise e
def translate_batch(self, batch):
"""
translate a batch of texts
@param batch: list of texts to translate
@return: list of translations
"""
return [self.translate(text) for text in batch]
|