Texto original de Jack McKew, publicado en su blog jackmckew.dev, donde nos explica cómo generar una traducción automática usando Python y la API de Google Translate o la API de DeepL, los 2 mejores motores de Traducción Automática (Machine Translation) del momento.
Trabajar con datos en un mundo digital interconectado, significa que posiblemente te encontrarás con datos en idiomas distintos al tuyo. En este post analizaremos cómo traducir estos datos sólo con Python, sin contactar con ningún traductor ni ninguna agencia de traducción.
Disclaimer: Traducción básica realizada por un traductor en el marco de sus estudios de formación en Ibidem Group, nuestra agencia de traducción en Barcelona. La traducción automática es muy útil (también se usa a nivel profesional) pero si estás buscando traducciones profesionales de documentos, no basta con una traducción automática. Necesitas traductores profesionales que al menos revisen ese texto (lo que se conoce como PEMT). Contacta con nuestra agencia de traducción en Madrid o cualquier de nuestras empresa de traducción y te ayudaremos a plantear un enfoque híbrido.
Para empezar a traducir necesitamos en primer lugar un texto de muestra, ¡y qué mejor que un texto en italiano sobre pizzas!
En [1]:
# Fuente: http://saberitaliano.com.ar/reading/pizza.html
# Source: http://saberitaliano.com.ar/reading/pizza.html sample_text_it = """La pizza è un prodotto gastronomico che ha per base un impasto di acqua, farina di frumento, e lievito, lavorato fino a ottenere una forma piatta, cotto al forno e variamente condito. Benché si tratti ormai di un prodotto diffuso in quasi tutto il mondo, la pizza è generalmente considerata un piatto originario della cucina italiana ed in particolar modo napoletana. Nel sentire comune, infatti, ci si riferisce con questo termine alla pizza tonda condita con pomodoro e mozzarella, ossia la variante più conosciuta della cosiddetta pizza napoletana. La vera e propria origine della pizza è tuttavia argomento controverso: oltre a Napoli, altre città ne rivendicano la paternità. Esiste, del resto, anche un significato più ampio del termine "pizza". Infatti, trattandosi in ultima analisi di una particolare specie di pane o focaccia, la pizza si presenta in innumerevoli derivazioni e varianti, cambiando nome e caratteristiche a seconda delle diverse tradizioni locali. In particolare, in alcune aree dell'Italia centrale, viene chiamata "pizza" qualsiasi tipo di torta cotta al forno, salata o dolce e alta o bassa che sia."""
Tenga en cuenta que utilizamos las comillas triples para contener esta cadena, porque se trata de una cadena multilínea. Hay que tener cuidado al utilizar las comillas triples, ya que estas cadenas también contendrán caracteres especiales como el salto de línea, los tabuladores y otros.
INDICE
Si alguna vez has necesitado traducir algo de un idioma que no conoces, es probable que hayas utilizado Google Translate. Es casi mágico lo bien que funciona este software, y las funciones de las que hace gala son nada menos que increíbles. Además de todo esto, ofrecen una API gratuita a la que podemos acceder directamente desde nuestro código. Si bien hay algunas limitaciones, esto sigue siendo un comienzo increíble y si el programa no se requiere para traducir cantidades masivas de texto, esto sería una solución directa.
Para hacer esto aún más simple en Python, hay un paquete llamado googletrans, que interactúa con la API de Google Translate https://pypi.org/project/googletrans/. Empecemos por importar el paquete, y ver qué idiomas están soportados.
En [2]:
import googletrans
print(googletrans.LANGUAGES)
{'af': 'afrikaans', 'sq': 'albanian', 'am': 'amharic', 'ar': 'arabic', 'hy': 'armenian', 'az': 'azerbaijani', 'eu': 'basque', 'be': 'belarusian', 'bn': 'bengali', 'bs': 'bosnian', 'bg': 'bulgarian', 'ca': 'catalan', 'ceb': 'cebuano', 'ny': 'chichewa', 'zh-cn': 'chinese (simplified)', 'zh-tw': 'chinese (traditional)', 'co': 'corsican', 'hr': 'croatian', 'cs': 'czech', 'da': 'danish', 'nl': 'dutch', 'en': 'english', 'eo': 'esperanto', 'et': 'estonian', 'tl': 'filipino', 'fi': 'finnish', 'fr': 'french', 'fy': 'frisian', 'gl': 'galician', 'ka': 'georgian', 'de': 'german', 'el': 'greek', 'gu': 'gujarati', 'ht': 'haitian creole', 'ha': 'hausa', 'haw': 'hawaiian', 'iw': 'hebrew', 'hi': 'hindi', 'hmn': 'hmong', 'hu': 'hungarian', 'is': 'icelandic', 'ig': 'igbo', 'id': 'indonesian', 'ga': 'irish', 'it': 'italian', 'ja': 'japanese', 'jw': 'javanese', 'kn': 'kannada', 'kk': 'kazakh', 'km': 'khmer', 'ko': 'korean', 'ku': 'kurdish (kurmanji)', 'ky': 'kyrgyz', 'lo': 'lao', 'la': 'latin', 'lv': 'latvian', 'lt': 'lithuanian', 'lb': 'luxembourgish', 'mk': 'macedonian', 'mg': 'malagasy', 'ms': 'malay', 'ml': 'malayalam', 'mt': 'maltese', 'mi': 'maori', 'mr': 'marathi', 'mn': 'mongolian', 'my': 'myanmar (burmese)', 'ne': 'nepali', 'no': 'norwegian', 'ps': 'pashto', 'fa': 'persian', 'pl': 'polish', 'pt': 'portuguese', 'pa': 'punjabi', 'ro': 'romanian', 'ru': 'russian', 'sm': 'samoan', 'gd': 'scots gaelic', 'sr': 'serbian', 'st': 'sesotho', 'sn': 'shona', 'sd': 'sindhi', 'si': 'sinhala', 'sk': 'slovak', 'sl': 'slovenian', 'so': 'somali', 'es': 'spanish', 'su': 'sundanese', 'sw': 'swahili', 'sv': 'swedish', 'tg': 'tajik', 'ta': 'tamil', 'te': 'telugu', 'th': 'thai', 'tr': 'turkish', 'uk': 'ukrainian', 'ur': 'urdu', 'uz': 'uzbek', 'vi': 'vietnamese', 'cy': 'welsh', 'xh': 'xhosa', 'yi': 'yiddish', 'yo': 'yoruba', 'zu': 'zulu', 'fil': 'Filipino', 'he': 'Hebrew'}
A continuación tenemos que crear una instancia de la clase traductor dentro de googletrans. Otra característica de Google Translate, es que puede detectar automáticamente el idioma en el que se encuentra el texto, ¡y también podemos utilizar esta característica en nuestro código! Esto es sencillo pasando nuestra cadena al método translator.detect(). Esto devolverá una instancia de una clase llamada Detected, en la que podemos ver el idioma detectado y la confianza del paquete en su predicción.
En [3]:
translator = googletrans.Translator() print(translator.detect(sample_text_it))
Detected(lang=it, confidence=1.0)
¡Ahora es el momento de empezar a traducir! Una vez más, se utiliza un método directo de translator.translate() pasando la cadena. También podemos definir el idioma de origen y el de destino para traducir. Esto devuelve una instancia de la clase Translated que contiene atributos de:
En [4]:
translated = translator.translate(sample_text_it, src='it', dest='en') print(translated)
Translated(src=it, dest=en, text=The pizza is a gourmet product that has as its base a mixture of water, wheat flour, and yeast, worked up to obtain a flat shape, baked and variously seasoned. Although it now is a widespread product in almost all over the world, pizza is generally considered an original dish of Italian cuisine and especially Neapolitan way. In common feeling, in fact, we are referring to with this term round pizza topped with tomato sauce and mozzarella, which is the most well-known variant of the so-called Neapolitan pizza. The real origin of pizza, however, is controversial: in addition to Naples, other cities claim its paternity. There is, moreover, also a broader meaning of the term "pizza". In fact, since in the final analysis of a particular kind of bread or focaccia, pizza presents itself in countless derivations and variations, changing name and characteristics depending on the different local traditions. In particular, in some areas of central Italy, it is called "pizza" any type of baked cake baked, salty or sweet, high or low it is., pronunciation=None, extra_data="{'translat...")
¿Qué pasa si tenemos muchas cadenas que necesitan ser traducidas? Empecemos por dividir nuestro texto de muestra en secciones con el método str.splitlines(), esto creará una lista de cada cadena separada por una nueva línea (párrafos separados).
We use the filter()
function to rid the list of empty strings for neatness sake
En [5]:
sentence_list = sample_text_it.splitlines()
# Remove empty strings
sentence_list = list(filter(None, sentence_list))
print(sentence_list)
['La pizza è un prodotto gastronomico che ha per base un impasto di acqua, farina di frumento, e lievito, lavorato fino a ottenere una forma piatta, cotto al forno e variamente condito.', 'Benché si tratti ormai di un prodotto diffuso in quasi tutto il mondo, la pizza è generalmente considerata un piatto originario della cucina italiana ed in particolar modo napoletana. Nel sentire comune, infatti, ci si riferisce con questo termine alla pizza tonda condita con pomodoro e mozzarella, ossia la variante più conosciuta della cosiddetta pizza napoletana.', 'La vera e propria origine della pizza è tuttavia argomento controverso: oltre a Napoli, altre città ne rivendicano la paternità. Esiste, del resto, anche un significato più ampio del termine "pizza". Infatti, trattandosi in ultima analisi di una particolare specie di pane o focaccia, la pizza si presenta in innumerevoli derivazioni e varianti, cambiando nome e caratteristiche a seconda delle diverse tradizioni locali. In particolare, in alcune aree dell\'Italia centrale, viene chiamata "pizza" qualsiasi tipo di torta cotta al forno, salata o dolce e alta o bassa che sia.']
Vamos a crear una función para manejar el paso de la traducción. Instanciamos un nuevo traductor cada vez que se llama a la función, esto también ayuda a reiniciar la API de Google Translate cada vez que traducimos. Si el src_lang no está definido la llamada a la función, vamos a utilizar el método mágico translator.detect() para hacer una predicción por nosotros.
Ahora iteramos sobre la lista, llamando a nuestra nueva función repetidamente y finalmente añadiendo los datos traducidos en una nueva lista translated_list.
En [6]:
def translate_text(text:str,src_lang:str=None,dest_lang:str="en"): translator = googletrans.Translator()
if src_lang is None:
src_lang = translator.detect(text).lang
returntranslator.translate(text,src=src_lang,dest=dest_lang).text
translated_list = []
for sentence in sentence_list: translated_list.append(translate_text(sentence))
print(translated_list)
['The pizza is a gourmet product that has as its base a mixture of water, wheat flour, and yeast, worked up to obtain a flat shape, baked and variously seasoned.', 'Although it now is a widespread product in almost all over the world, pizza is generally considered an original dish of Italian cuisine and especially Neapolitan way. In common feeling, in fact, we are referring to with this term round pizza topped with tomato sauce and mozzarella, which is the most well-known variant of the so-called Neapolitan pizza.', 'The real origin of pizza, however, is controversial: in addition to Naples, other cities claim its paternity. There is, moreover, also a broader meaning of the term "pizza". In fact, since in the final analysis of a particular kind of bread or focaccia, pizza presents itself in countless derivations and variations, changing name and characteristics depending on the different local traditions. In particular, in some areas of central Italy, it is called "pizza" any type of baked cake baked, salty or sweet, high or low it is.']
A veces tenemos que traducir conjuntos de datos mucho más grandes. Hace poco me enfrenté a este problema mientras trabajaba como voluntario en un proyecto de COVID-19 en el que queríamos realizar un análisis de los tuits de Italia durante la pandemia. Recibimos millones de tuits durante semanas en mayo de 2020, todos en italiano. Como la mayor parte del equipo sólo hablaba inglés y, por lo que sabíamos, el análisis de sentimientos se había desarrollado ampliamente para el inglés, tendríamos que traducir todos estos datos. Google Translate es de pago, pero el equipo de DeepL nos donó amablemente una clave API para nuestra causa. A continuación, veremos cómo el equipo y yo configuramos el traductor masivo con pandas, peticiones y la API de DeepL Translator.
As to not share the donated API key, responses from the DeepL translator will not be shown in this post.
En primer lugar, inicializaremos nuestro texto de muestra (dividido por párrafos) de antes, en un DataFrame de pandas para representar nuestros conjuntos de datos masivos.
En [7]:
import pandas as pd
import numpy as np
import requests
import json
En [8]:
source_text_df = pd.DataFrame(sentence_list,columns=["Source Text"]) source_text_df
Fuera[8]:
Texto fuente | |
0 | La pizza es un producto gastronómico que tiene por… |
1 | Benché si tratti ormai di un prodotto diffuso … |
2 | El verdadero y propio origen de la pizza es todo… |
Ahora que tenemos nuestros datos organizados en un DataFrame de pandas, creamos una función para interactuar con la API del traductor DeepL.
La documentación de la API del traductor DeepL es fantástica, y puede consultarse en https://www.deepl.com/docs-api/introduction/.
Usando construir nuestra solicitud como un diccionario para ser usado con el paquete requests. Lea más detalles sobre cómo se formatean las cargas útiles en la documentación de requests.
La respuesta de DeepL está en formato JSON, que podemos convertir en un diccionario con el método response.json().
Finalmente, hacemos un bucle a través de la respuesta devuelta, y reconstruimos una lista de los datos traducidos para devolverlos desde la función.
En [9]:
def translate_text_deepl(data,api_key,src_lang:str="IT",target_lang:str="EN"): # Create empty list
translated_list = []
try:
# Translate all tweets and add to list
# Request should not exceed 30KB
parameters = {
"text": data,
"source_lang": src_lang,
"target_lang": target_lang,
"auth_key": api_key,
}
response = requests.get("https://api.deepl.com/v2/translate", params=parameters)
deepl_response_data = response.json()
for item in deepl_response_data.values():
for key in item: translated_list.append(key["text"])
except json.decoder.JSONDecodeError:
# Insert error for each line in data
for _ in data:
translated_list.append("Error")
print(f"Error translating.. `Error` placed in output dataset") return translated_list
Ahora que tenemos nuestra función que interactúa con la API del Traductor DeepL, podemos usarla para traducir todos nuestros datos fácilmente llamando a la función, ¡eso es todo, hecho!
The output shows Error due to the API Key not being valid
En [10]:
source_text_df['Translated Text'] = translate_text_deepl(source_text_df['Source Text'],"APIKEY","IT","EN")
Error translating.. `Error` placed in output dataset
Si el DataFrame tiene un tamaño mucho mayor, es posible que necesitemos procesar estos datos en trozos. Esto puede hacerse utilizando nuestra nueva función translate_text_deepl desde una perspectiva diferente.
Del mismo modo, creamos una nueva lista para almacenar todos nuestros datos traducidos, y añadimos nuevos datos de forma iterativa en trozos en nuestro DataFrame. Los trozos pueden ser iterados a través de un DataFrame usando el método groupby, junto con la función arange en numpy.
The output shows Error due to the API Key not being valid
En [11]:
all_translated_data = []
chunk_size = 2
for _, chunk in source_text_df.groupby(np.arange(len(source_text_df)) // chunk_size):
# Add new data to list
# We use extend as the function returns a list all_translated_data.extend(translate_text_deepl(chunk['Source Text'],"APIKEY","IT","EN")) source_text_df['Translated Text'] = all_translated_data
Error translating.. `Error` placed in output dataset
Error translating.. `Error` placed in output dataset
Articulos relacionados
Traducción de un interesantísimo artículo de Jordan Kalebu explicando cómo utilizar Python para realizar traducción automática de idiomas, usando 3 bibliotecas alternativas: Goslate, Googletrans y TextBlob. Una forma super sencilla y gratuita de traducir de forma automática todos...
Traducción de un texto original de Behic Guven, publicado el 8/6/2020 en su blog https://sonsuzdesign.blog, donde explica cómo crear un traductor de voz en Python, un proyecto sencillo para traducir de forma automática lo que dices sin necesidad de escribir nada.
Traducción a Español de un artículo de Nicolas Bertagnolli, donde nos explica lo mucho que ha avanzado la Traducción Automática en los últimos años, y cómo hoy en día, permite traducir 2 idiomas con sólo 60 líneas de código Python.