django-rosetta/rosetta/translate_utils.py

162 lines
5.5 KiB
Python

import json
import uuid
import requests
from django.conf import settings
class TranslationException(Exception):
pass
def translate(text, from_language, to_language):
AZURE_CLIENT_SECRET = getattr(settings, "AZURE_CLIENT_SECRET", None)
GOOGLE_APPLICATION_CREDENTIALS_PATH = getattr(
settings, "GOOGLE_APPLICATION_CREDENTIALS_PATH", None
)
GOOGLE_PROJECT_ID = getattr(settings, "GOOGLE_PROJECT_ID", None)
DEEPL_AUTH_KEY = getattr(settings, "DEEPL_AUTH_KEY", None)
if DEEPL_AUTH_KEY:
deepl_language_code = None
DEEPL_LANGUAGES = getattr(settings, "DEEPL_LANGUAGES", None)
if type(DEEPL_LANGUAGES) is dict:
deepl_language_code = DEEPL_LANGUAGES.get(to_language, None)
if deepl_language_code is None:
deepl_language_code = to_language[:2].upper()
return translate_by_deepl(
text,
deepl_language_code.upper(),
DEEPL_AUTH_KEY,
)
elif AZURE_CLIENT_SECRET:
return translate_by_azure(text, from_language, to_language, AZURE_CLIENT_SECRET)
elif GOOGLE_APPLICATION_CREDENTIALS_PATH and GOOGLE_PROJECT_ID:
return translate_by_google(
text,
from_language,
to_language,
GOOGLE_APPLICATION_CREDENTIALS_PATH,
GOOGLE_PROJECT_ID,
)
else:
raise TranslationException("No translation API service is configured.")
def translate_by_deepl(text, to_language, auth_key):
if auth_key.lower().endswith(":fx"):
endpoint = "https://api-free.deepl.com"
else:
endpoint = "https://api.deepl.com"
r = requests.post(
f"{endpoint}/v2/translate",
headers={"Authorization": f"DeepL-Auth-Key {auth_key}"},
data={
"target_lang": to_language.upper(),
"text": text,
},
)
return r.json().get("translations")[0].get("text")
def translate_by_azure(text, from_language, to_language, subscription_key):
"""
This method does the heavy lifting of connecting to the translator API and fetching a response
:param text: The source text to be translated
:param from_language: The language of the source text
:param to_language: The target language to translate the text into
:param subscription_key: An API key that grants you access to the Azure translation service
:return: Returns the response from the AZURE service as a python object. For more information about the
response, please visit
https://docs.microsoft.com/en-us/azure/cognitive-services/translator/reference/v3-0-translate?tabs=curl
"""
AZURE_TRANSLATOR_HOST = "https://api.cognitive.microsofttranslator.com"
AZURE_TRANSLATOR_PATH = "/translate?api-version=3.0"
headers = {
"Ocp-Apim-Subscription-Key": subscription_key,
"Content-type": "application/json",
"X-ClientTraceId": str(uuid.uuid4()),
}
url_parameters = {"from": from_language, "to": to_language}
request_data = [{"text": text}]
api_hostname = AZURE_TRANSLATOR_HOST + AZURE_TRANSLATOR_PATH
r = requests.post(
api_hostname,
headers=headers,
params=url_parameters,
data=json.dumps(request_data),
)
api_response = json.loads(r.text)
try:
# result will be a dict if there is an error, e.g.
# {
# "success": false,
# "error": "Microsoft Translation API error: Error code 401000,
# The request is not authorized because credentials are missing or invalid."
# }
if isinstance(api_response, dict):
api_error = api_response.get("error")
error_code = api_error.get("code")
error_message = api_error.get("message")
raise TranslationException(
"Microsoft Translation API error: Error code {}, {}".format(
error_code, error_message
)
)
else:
# response body will be of the form:
# [
# {
# "translations":[
# {"text": "some chinese text that gave a build error on travis ci", "to": "zh-Hans"}
# ]
# }
# ]
# for more information, please visit
# https://docs.microsoft.com/en-us/azure/cognitive-services/translator/reference/v3-0-translate?tabs=curl
translations = api_response[0].get("translations")
translated_text = translations[0].get("text")
return translated_text
except requests.exceptions.RequestException as err:
raise TranslationException(
"Error connecting to Microsoft Translation Service: {0}".format(err)
)
def translate_by_google(
text, input_language, output_language, creadentials_path, project_id
):
from google.cloud import translate as google_translate
client = google_translate.TranslationServiceClient.from_service_account_json(
creadentials_path
)
parent = "projects/{}/locations/{}".format(project_id, "global")
try:
api_response = client.translate_text(
request=dict(
parent=parent,
contents=[text],
mime_type="text/plain",
source_language_code=input_language,
target_language_code=output_language.split(".", 1)[0],
)
)
except Exception as e:
raise TranslationException("Google API error: {}".format(e))
else:
return str(api_response.translations[0].translated_text)