Original article: React Tutorial – How to Build a Text Translation PWA
En este artículo, te mostraré como crear una aplicación de traducción de texto con React. Admitirá 17 idiomas, y también podrás hacer traducciones cruzadas.
Esto es que crearemos:

Así es como se verá nuestra aplicación después de que hayamos terminado de construirla. Tiene dos áreas de entrada de texto - una tendrá el código fuente, y la otra tendrá el texto resultante de la traducción. Tenemos también un campo seleccionable donde el usuario podrá elegir los idiomas que desee.
Entonces, entremos de lleno en ello.
Como construir la Interfaz de usuario
Para crear la interfaz fácilmente, usaremos una librería de Interfaces de Usuario llamado Semantic UI.
Por lo tanto, navegue al sitio web de Semantic UI en https://react.semantic-ui.com/.
A continuación, selecciona "Get Started" en el menú lateral:

Instalemos la librería usando uno de los siguientes comandos. Puedes utilizar yarn add o npm install.
$ yarn add semantic-ui-react semantic-ui-css
## O
$ npm install semantic-ui-react semantic-ui-css
Después de que finalizó la instalación, debemos importar el paquete dentro de nuestro archivo index.js de la siguiente manera:
import 'semantic-ui-css/semantic.min.css'
Ahora, ya podemos usar Semantic UI.
Como crear los componentes de la aplicación
Vamos a crear un componente llamado Traductor. Este tendrá todos los elementos que necesitamos.
Primero, necesitamos un título principal para la aplicación. Entonces, dentro del componente Traductor, crea un encabezado como este:
import React from 'react';
export default function Traductor() {
return (
<div>
<div className="app-header">
<h2 className="header">Traductor de texto</h2>
</div>
</div>
)
}
Ahora vamos a agregarle un poco de estilos con CSS. En el archivo App.css quitaremos los estilos que vienen por defecto, y agregaremos los nuestros:
@import url('https://fonts.googleapis.com/css2?family=Azeret+Mono&display=swap');
.app-header{
text-align: center;
padding: 20px;
}
.header{
font-family: 'Azeret Mono', monospace;
font-size: 30px;
}
Acá, estamos usando una fuente llamada Azeret Mono de Google Fonts, y hemos alineado el encabezado (header) y le dimos un poco de relleno (padding).
Para lograr ver los cambios, en el archivo App.js debemos reemplazar todas las líneas de código del return de la función App por un <div> con el componente Traductor. Quedando de esta manera:
import './App.css';
import Traductor from './componentes/Traductor';
function App() {
return (
<div>
<Traductor />
</div>
);
}
export default App;
Al hacer npm start
, así es como se verá nuestro encabezado en este punto:

También necesitamos otros cuatro elementos. En primer lugar, nuestra área de entrada de texto, segundo el menú desplegable para seleccionar el idioma, tercero es el área de texto de salida donde se reflejará nuestro texto traducido, y por último es un botón que traducirá nuestro texto.
Podemos importar los elementos Form, TextArea, Button e Icon directamente desde Semantic UI de esta manera:
import {
Form,
TextArea,
Button,
Icon
} from 'semantic-ui-react';
A continuación, crearemos otro div después de app-header
llamado app-body
con el siguiente código:
import React from 'react';
import {
Form,
TextArea,
Button,
Icon
} from 'semantic-ui-react';
export default function Traductor() {
return (
<div>
<div className="app-header">
<h2 className="header">Traductor de texto</h2>
</div>
<div className='app-body'>
<div>
<Form>
<Form.Field
control={TextArea}
placeholder='Escribe el texto a traducir..'
/>
<select className="select-idioma">
<option>Por favor selecciona un idioma..</option>
</select>
<Form.Field
control={TextArea}
placeholder='El resultado de la traducción..'
/>
<Button
color="orange"
size="large"
>
<Icon name='traducir' />
Traducir</Button>
</Form>
</div>
</div>
</div>
)
}
Y le agregaremos un poco de estilo con el siguiente CSS:
@import url('https://fonts.googleapis.com/css2?family=Azeret+Mono&display=swap');
.app-header{
text-align: center;
padding: 20px;
}
.header{
font-family: 'Azeret Mono', monospace;
font-size: 30px;
}
.app-body{
padding: 20px;
text-align: center;
}
.select-idioma{
height: 40px !important;
margin-bottom: 15px;
outline: none !important;
}
Así es como se verá nuestra aplicación ahora. Puedes ver que tenemos las áreas de texto, seleccionar opciones y un botón para traducir.

Cómo configurar las APIs
Para habilitar la traducción, usaremos la API LibreTranslate. Por lo tanto, vaya a su sitio web para elegir tu API.

Como puedes ver en la imagen de arriba, tiene cuatro APIs.
Para empezar, necesitamos detectar nuestro idioma de entrada utilizando la API /detect que es de tipo POST.
Cómo instalar Axios
Primeramente, vamos a instalar Axios, ya que necesitaremos usarlo para realizar solicitudes a la API.
Para instalar Axios, simplemente escriba el siguiente comando:
yarn add axios
##O
npm i axios
Podemos usar yarn add axios
o npm i axios
, dependiendo de su administrador de paquetes que haya instalado.
Ahora, vamos a importarlo en nuestro componente Traductor.
import axios from 'axios';
También necesitamos los hooks useState
y useEffect
.
import React, { useState, useEffect } from 'react';
A continuación, cree un estado llamado inputText.
const [textoEntrante, setTextoEntrante] = useState('');
Y en el campo de área de texto de entrada, enlazarlo a un controlador de eventos onChange.
<Form.Field
control={TextArea}
placeholder='Escribe el texto a traducir..'
onChange={(e) => setTextoEntrante(e.target.value)}
/>
Si introducimos algún texto, se almacenará en el estado textoEntrante
.
Cómo llamar a la API de detección de idioma
Ahora, llamemos a la API de detección de idioma para detectar nuestro idioma de entrada.
Crea una función llamada obtenerFuenteDelIdioma()
como esta:
const obtenerFuenteDelIdioma = () => {
axios.post(`https://libretranslate.de/detect`, {
q: textoEntrante
})
.then((respuesta) => {
console.log(respuesta.data[0].language)
})
}
Aquí, estamos llamando a la API de detección, y estamos pasando nuestra entrada como el cuerpo del POST.
Estamos usando axios.post
para enviar el texto de entrada como cuerpo, y estamos usando q como parámetro de encabezado.
Además, querremos llamar a esta función al hacer clic en el botón Traducir, así que vincule esta función al botón Traducir de esta manera:
<Button
color="orange"
size="large"
onClick={obtenerFuenteDelIdioma}
>
<Icon name='traducir' />
Traducir</Button>
Escribe algo en el primer cuadro de entrada de texto y, a continuación, pulse el botón Traducir. Verá un objeto, con la clave de idioma detectada en la consola, que necesitamos.

Ahora, necesitamos almacenar esta clave de idioma en un estado. Por lo tanto, cree un estado llamado claveIdiomaDetectada
.
Luego, establezca el estado con la respuesta del llamado de la siguiente manera:
const obtenerFuenteDelIdioma = () => {
axios.post(`https://libretranslate.de/detect`, {
q: textoEntrante
})
.then((respuesta) => {
setClaveIdiomaDetectada(respuesta.data[0].language)
})
}
Estamos estableciendo el índice cero a partir de los datos de respuesta, porque ahí es donde comienzan nuestros datos.
Aquí está todo el código hasta este punto:
import React, { useState, useEffect } from 'react';
import {
Form,
TextArea,
Button,
Icon
} from 'semantic-ui-react';
import axios from 'axios';
export default function Traducir() {
const [textoEntrante, setTextoEntrante] = useState('');
const [claveIdiomaDetectada, setClaveIdiomaDetectada] = useState('')
const obtenerFuenteDelIdioma = () => {
axios.post(`https://libretranslate.de/detect`, {
q: textoEntrante
})
.then((respuesta) => {
setClaveIdiomaDetectada(respuesta.data[0].language)
})
}
return (
<div>
<div className="app-header">
<h2 className="header">Traductor de texto</h2>
</div>
<div className='app-body'>
<div>
<Form>
<Form.Field
control={TextArea}
placeholder='Escribe el texto a traducir..'
onChange={(e) => setTextoEntrante(e.target.value)}
/>
<select className="select-idioma">
<option>Por favor seleccione un idioma..</option>
</select>
<Form.Field
control={TextArea}
placeholder='El resultado de su traducción..'
/>
<Button
color="orange"
size="large"
onClick={obtenerFuenteDelIdioma}
>
<Icon name='traducir' />
Traducir</Button>
</Form>
</div>
</div>
</div>
)
}
Cómo llamar a la API de idiomas admitidos para el menú desplegable
Ahora, la segunda API obtiene los idiomas admitidos. Usaremos la lista en nuestro menú desplegable de selección.
Cree un hook useEffect
para llamar a nuestra API de idiomas compatibles. useEffect
es una función que se ejecutará cada vez que nuestro componente se renderice o cargue.
useEffect(() => {
axios.get(`https://libretranslate.de/languages`)
.then((respuesta) => {
console.log(respuesta.data)
})
}, [])
Aquí estamos llamando a la API para idiomas compatibles utilizando el método axios.get. Luego estamos imprimiendo la respuesta en la consola.
Abra la consola para comprobar la lista de idiomas. Deberías ver algo como esto:

Establezcamos estos datos en un estado. Por lo tanto, cree un estado llamado listadoIdiomas
. Será un arreglo vacío.
const [listadoIdiomas, setListadoIdiomas] = useState([])
useEffect(() => {
axios.get(`https://libretranslate.de/languages`)
.then((respuesta) => {
setListadoIdiomas(respuesta.data)
})
}, [])
Luego, en el hook useEffect
, debemos establecer la lista de idiomas usando setListadoIdiomas
.
Necesitamos mostrar esta lista de idiomas en la opción de selección. Por lo tanto, asignemos el menú desplegable de selección utilizando el estado listadoIdiomas
de la siguiente manera:
<select className="select-idioma">
<option>Por favor seleccione un idioma..</option>
{listadoIdiomas.map((idioma) => {
return (
<option value={idioma.code}>
{idioma.name}
</option>
)
})}
</select>

Ahora, podemos seleccionar nuestro idioma en el menú desplegable de selección.
Cómo obtener el código del idioma seleccionado
Ahora, si seleccionamos un idioma, por ejemplo, español, necesitamos obtener el código del idioma, ya que necesitamos ese código de idioma en nuestra API de traducción final.
Crea una función llamada claveIdioma()
como esta:
const claveIdioma = () => {
}
Y en la opción de selección (<select>), debemos unir esta función usando el evento onChange:
<select className="select-idioma" onChange={claveIdioma}>
<option>Por favor seleccione un idioma..</option>
{listadoIdiomas.map((idioma) => {
return (
<option value={idioma.code}>
{idioma.name}
</option>
)
})}
</select>
Además, necesitamos almacenar el código del idioma en un estado, así que vamos a crearlo.
Cree un estado llamado claveIdiomaSeleccionada
, que tendrá nuestra clave del idioma seleccionado de la entrada de selección.
const [claveIdiomaSeleccionada, setClaveIdiomaSeleccionada] = useState('')
Esta función claveIdioma
aceptará un parámetro denominado idiomaSeleccionado
. Y almacenaremos estos datos en el estado claveIdiomaSeleccionada
, que obtendremos de la entrada de selección.
const claveIdioma = (idiomaSeleccionado) => {
setClaveIdiomaSeleccionada(idiomaSeleccionado.target.value)
}
Ahora, si nos fijamos en la documentación de LibreTranslate, necesitamos tres entradas de datos:
- El texto a traducir.
- El código del idioma fuente. (source)
- El código del idioma de destino. (target)

No necesitamos la clave de la API (api_key) porque este servicio es gratuito.
Tenemos los tres inputs que necesitamos enviar en el cuerpo contenido en estos estados a continuación:
const [textoEntrante, setTextoEntrante] = useState('');
const [claveIdiomaDetectada, setClaveIdiomaDetectada] = useState('');
const [claveIdiomaSeleccionada, setClaveIdiomaSeleccionada] = useState('')
Ahora, llamemos a nuestra API final, que es /translate.
Cómo llamar a la API de traducción para traducir nuestro texto
Cree un estado final denominado textoResultante
. Este estado contendrá nuestro texto traducido de salida.
const [textoResultante, setTextoResultante] = useState('');
Cree una función que llame a la API de traducción:
const traducirTexto = () => {
obtenerFuenteDelIdioma();
let data = {
q : textoEntrante,
source: claveIdiomaDetectada,
target: claveIdiomaSeleccionada
}
axios.post(`https://libretranslate.de/translate`, data)
.then((respuesta) => {
setTextoResultante(respuesta.data.translatedText)
})
}
Como puedes ver, estamos configurando textoEntrante
en el estado textoResultante
, y estamos llamando a la función obtenerFuenteDelIdioma
dentro de la función traducirTexto
. Por lo tanto, cada vez que se ejecute esta función, obtenerFuenteDelIdioma
los activará automáticamente para obtener la fuente del idioma.
En otras palabras, al hacer clic (evento onClick) en el botón Traducir, la función traducirTexto()
establecerá la fuente del idioma a través de obtenerFuenteDelIdioma()
, y luego llamará a la API de traducción.
Entonces, en el botón Traducir, conecta esta función:
<Button
color="orange"
size="large"
onClick={traducirTexto}
>
<Icon name='traducir' />
Traducir</Button>
A continuación, vamos a crear un objeto llamado data. Enviaremos dentro de él toda la información que obtuvimos previamente, como textoEntrante
, claveIdiomaDetectada
, y la clave de claveIdiomaSeleccionada
como q, source, y target respectivamente.
let data = {
q : textoEntrante,
source: claveIdiomaDetectada,
target: claveIdiomaSeleccionada
}
Luego, llamamos a la API de traducción usando axios.post y enviamos el objeto data como un parámetro de cuerpo de la petición.
let data = {
q : textoEntrante,
source: claveIdiomaDetectada,
target: claveIdiomaSeleccionada
}
axios.post(`https://libretranslate.de/translate`, data)
Por último, establecemos la respuesta devuelta en el estado textoResultante
.
.then((respuesta) => {
setTextoResultante(respuesta.data.translatedText)
})
Por lo tanto, ahora escriba algo en el cuadro de entrada, seleccione el idioma y haga clic en Traducir. Obtendrá su texto traducido.
Aquí está todo el código hasta este punto, para su referencia:
import React, { useState, useEffect } from 'react';
import {
Form,
TextArea,
Button,
Icon
} from 'semantic-ui-react';
import axios from 'axios';
export default function Traductor() {
const [textoEntrante, setTextoEntrante] = useState('');
const [claveIdiomaDetectada, setClaveIdiomaDetectada] = useState('');
const [claveIdiomaSeleccionada, setClaveIdiomaSeleccionada] = useState('')
const [listadoIdiomas, setListadoIdiomas] = useState([])
const [textoResultante, setTextoResultante] = useState('');
const obtenerFuenteDelIdioma = () => {
axios.post(`https://libretranslate.de/detect`, {
q: textoEntrante
})
.then((respuesta) => {
setClaveIdiomaDetectada(respuesta.data[0].language)
})
}
useEffect(() => {
axios.get(`https://libretranslate.de/languages`)
.then((respuesta) => {
setListadoIdiomas(respuesta.data)
})
}, [])
const claveIdioma = (idiomaSeleccionado) => {
setClaveIdioma(idiomaSeleccionado.target.value)
}
const traducirTexto = () => {
obtenerFuenteDelIdioma();
let data = {
q : textoEntrante,
source: claveIdiomaDetectada,
target: claveIdiomaSeleccionada
}
axios.post(`https://libretranslate.de/translate`, data)
.then((respuesta) => {
setTextoResultante(respuesta.data.translatedText)
})
}
return (
<div>
<div className="app-header">
<h2 className="header">Traductor de texto</h2>
</div>
<div className='app-body'>
<div>
<Form>
<Form.Field
control={TextArea}
placeholder='Escribe el texto a traducir..'
onChange={(e) => setTextoEntrante(e.target.value)}
/>
<select className="select-idioma" onChange={claveIdioma}>
<option>Por favor seleccione un idioma..</option>
{listadoIdiomas.map((idioma) => {
return (
<option value={idioma.code}>
{idioma.name}
</option>
)
})}
</select>
<Form.Field
control={TextArea}
placeholder='El resultado de su traducción..'
value={textoResultante}
/>
<Button
color="orange"
size="large"
onClick={traducirTexto}
>
<Icon name='traducir' />
Traducir</Button>
</Form>
</div>
</div>
</div>
)
}
Ahora, el último paso. En el hook useEffect
, llama a la función obtenerFuenteDelIdioma()
, y establece textoEntrante
como el arreglo de dependencias del useEffect
. Esto significa que siempre y cuando nuestro textoEntrada
cambie su texto, o este estado se actualice, se ejecutará la función useEffect
, y llamará a la función obtenerFuenteDelIdioma()
cada vez que se ejecute.
useEffect(() => {
axios.get(`https://libretranslate.de/languages`)
.then((respuesta) => {
setListadoIdiomas(respuesta.data)
})
obtenerFuenteDelIdioma()
}, [textoEntrante])
Ahora, veamos nuestra salida:

Escriba algo de texto como entrada y seleccione el idioma. Presione Traducir y verá sus datos traducidos en el espacio de salida.
Conclusión
Ahora ya sabes cómo crear un traductor de texto con React. Puedes crear tu propia interfaz de usuario si lo deseas.
Así que adelante, construye y experimenta un poco con él. Hay toneladas de cosas que puedes hacer.
Buen aprendizaje!