Integrando Azure Text Translation en una aplicación React con Next.js
Daniel J. Saldaña
Posted on March 10, 2024
En el mundo globalizado de hoy, proporcionar contenido en varios idiomas puede ser una enorme ventaja para tu aplicación web. Microsoft Azure ofrece un servicio de traducción de texto que se puede integrar fácilmente en cualquier aplicación web. En este tutorial, te mostraré cómo utilizar Azure Text Translation en una aplicación creada con React para el frontend y Next.js para el API de backend.
Paso 1: Configuración del Servicio en Azure
El primer paso es crear y configurar el servicio Azure Text Translation en la consola de Azure:
Iniciar sesión y crear un recurso : Ve a Azure Portal y haz clic en "Crear un recurso". Busca "Translator" y sigue las instrucciones para crearlo.
Configuración del servicio : Elige un nombre para tu servicio, selecciona el plan de precios y la región.
Obtener las claves de acceso : Una vez creado el servicio, ve a "Claves y punto de conexión" para obtener tu "Clave 1" y "Ubicación". Guarda estos valores, los necesitarás más adelante para tu API.
Paso 2: Configuración del Backend con Next.js
Ahora que hemos configurado nuestro servicio en Azure, es hora de crear el backend que manejará las solicitudes de traducción. Este backend se implementará usando Next.js, aprovechando su capacidad para crear API routes de manera sencilla y eficiente.
A continuación, te muestro un ejemplo de cómo configurar un endpoint de API en Next.js para realizar traducciones utilizando el servicio Azure Text Translation:
import axios from 'axios';
import { enableCors } from "@/src/middleware/enableCors";
import { methodValidator } from "@/src/utils/methodValidator";
require('dotenv').config();
// Función para eliminar el markdown del texto
function stripMarkdown(markdownText) {
// Aquí se eliminan diversos elementos de markdown para obtener solo el texto plano
return markdownText
.replace(/```
[\s\S]*?
```/g, '')
.replace(/\([^\)]*\)/g, '')
.replace(/(\*\*|__)(.*?)(\*\*|__)/g, '$2')
.replace(/\!\[(.*?)\]\((.*?)\)/g, '')
.replace(/\[(.*?)\]\((.*?)\)/g, '$1')
.replace(/(\*\*|__)/g, '')
.replace(/(\*|-)/g, '')
.replace(/(#{1,6}) /g, '')
.replace(/`(.+?)`/g, '')
.replace(/\n/g, ' ');
}
// Función para eliminar el HTML del texto
function stripHtml(htmlText) {
// Elimina las etiquetas HTML para obtener solo el texto
return htmlText.replace(/<[^>]*>/g, '');
}
// La función principal que maneja la solicitud de traducción
const translation = async (req, res) => {
await enableCors(req, res); // Habilita CORS para la solicitud
await methodValidator(req, res, 'POST'); // Valida que la solicitud sea de tipo POST
if (res.headersSent) {
console.log('La respuesta ya fue enviada.');
return;
}
// Extrae los datos necesarios de la solicitud
let { title, content, targetLanguage } = req.body;
if (!title || !content || !targetLanguage) {
console.log('Faltan datos en la solicitud:', { title, content, targetLanguage });
return res.status(400).json({ error: 'Faltan datos en la solicitud. Se requieren title, content y targetLanguage.' });
}
// Limpia el título y el contenido de markdown y HTML
title = stripMarkdown(stripHtml(title));
content = stripMarkdown(stripHtml(content));
// Configuración para la solicitud a la API de Azure Text Translation
const translatorConfig = {
headers: {
'Ocp-Apim-Subscription-Key': process.env.TRANSLATOR_SUBSCRIPTION_KEY,
'Ocp-Apim-Subscription-Region': process.env.TRANSLATOR_REGION,
'Content-Type': 'application/json'
},
params: {
'api-version': '3.0',
'to': targetLanguage
}
};
try {
// Realiza las solicitudes de traducción para el título y el contenido simultáneamente
const [titleResponse, contentResponse] = await Promise.all([
axios.post('https://api.cognitive.microsofttranslator.com/translate', [{ Text: title }], translatorConfig),
axios.post('https://api.cognitive.microsofttranslator.com/translate', [{ Text: content }], translatorConfig)
]);
// Extrae las traducciones del título y el contenido de las respuestas
const translatedTitle = titleResponse.data[0].translations[0].text;
const translatedContent = contentResponse.data[0].translations[0].text;
// Envía la respuesta con el título y contenido traducidos
return res.status(200).json({
translatedTitle,
translatedContent
});
} catch (error) {
console.error('Error durante la traducción:', error);
return res.status(500).json({
error: `Error durante la solicitud de traducción: ${error.message}`
});
}
};
export default enableCors(translation);
Cómo Funciona
Este backend realiza varios pasos importantes para procesar y responder a las solicitudes de traducción:
Habilitación de CORS : Utiliza un middleware
enableCors
para permitir solicitudes de origen cruzado, lo cual es crucial para APIs accesibles desde el frontend.Validación del Método de Solicitud : El
methodValidator
asegura que solo se acepten solicitudes POST, que es lo esperado para enviar datos de texto a traducir.Limpieza de Texto : Antes de enviar el texto a la API de Azure, se limpia de markdown y HTML para asegurarse de que la traducción sea sobre el texto puro.
Configuración de la Solicitud de Traducción : Establece los encabezados y parámetros necesarios, incluyendo la clave de suscripción y la región que obtuviste al configurar el servicio Azure.
Envío y Respuesta de la Traducción : Realiza solicitudes HTTP paralelas para traducir tanto el título como el contenido, y luego responde con el texto traducido.
Al implementar esta función en tu backend, proporcionas una forma robusta y segura de integrar traducciones automáticas en tu aplicación.
Entendido, vamos a actualizar el paso 3 del post con el ejemplo de código proporcionado para el componente del frontend y una explicación de cómo funciona:
Paso 3: Integración del Frontend con React
Una vez que el backend está en su lugar, es hora de conectar el frontend para que los usuarios puedan enviar texto para traducir y ver los resultados. Vamos a crear un componente React que maneje esta funcionalidad:
import { useState, useEffect, useMemo } from 'react';
import axios from 'axios';
import sanitizeHtml from 'sanitize-html';
import { marked } from 'marked';
import { SiMicrosofttranslator } from 'react-icons/si';
import { GiAllSeeingEye } from 'react-icons/gi';
import './TranslationController.scss';
const TranslationController = ({ content, title, image }) => {
// Estados para controlar la UI y almacenar los datos de traducción
const [isModalOpen, setIsModalOpen] = useState(false);
const [selectedLanguage, setSelectedLanguage] = useState('');
const [translatedTitle, setTranslatedTitle] = useState(title);
const [translatedContent, setTranslatedContent] = useState(content);
const [isTranslating, setIsTranslating] = useState(false);
const [tokens, setTokens] = useState(0);
const [dailyLimitInfo, setDailyLimitInfo] = useState({ dailyLimit: 0, tokensUsedToday: 0 });
const [errorMessage, setErrorMessage] = useState('');
// Efectos para cargar información necesaria al cargar el componente
useEffect(() => {
fetchDailyLimit();
fetchTokens();
}, []);
// Aquí se definen las funciones para manejar la lógica de negocios, como obtener los tokens y límites diarios,
// actualizar tokens y realizar la traducción.
const toggleModal = () => {
setIsModalOpen(!isModalOpen);
document.body.classList.toggle('no-scroll', !isModalOpen);
};
const handleLanguageChange = (e) => {
setSelectedLanguage(e.target.value);
};
// Funciones para manejar la conversión de Markdown a HTML y la limpieza de HTML
const translateContent = async () => {
// Lógica para iniciar la traducción y actualizar los estados basados en la respuesta
};
// Lógica para calcular los tokens disponibles basada en la información del límite diario
const tokensAvailableToday = useMemo(() => {
const { dailyLimit, tokensUsedToday } = dailyLimitInfo;
return Math.max(dailyLimit - tokensUsedToday, 0);
}, [dailyLimitInfo]);
// Renderiza el componente, mostrando el formulario de traducción, los resultados y cualquier mensaje de error.
return (
// JSX para la interfaz del controlador de traducción
);
};
export default TranslationController;
Cómo Funciona
Este componente de React TranslationController
maneja varias tareas importantes:
Estados y Efectos : Utiliza los hooks de React para manejar estados y efectos secundarios. Esto incluye abrir y cerrar el modal de traducción, almacenar el contenido traducido, y rastrear si se está realizando una traducción.
Manejo de Límites y Tokens : Hace solicitudes al backend para obtener y actualizar el número de tokens disponibles y el límite diario de uso. Esto es crucial para no sobrepasar los límites del servicio de traducción.
Selección de Idioma y Traducción : Permite al usuario seleccionar el idioma de destino y envía el contenido a traducir al backend. Muestra el contenido traducido una vez que esté disponible.
Renderización de Markdown y Sanitización de HTML : Convierte el contenido de Markdown a HTML y lo limpia antes de mostrarlo, asegurando que el contenido sea seguro y esté formateado correctamente.
UI Interactiva : Proporciona una interfaz de usuario interactiva y amigable, incluyendo un modal de traducción, selección de idioma y botones para realizar la traducción. También maneja la visualización de mensajes de error y la cantidad de tokens disponibles.
Este componente encapsula toda la lógica necesaria para interactuar con el servicio de traducción y proporcionar una experiencia de usuario fluida y funcional. Con este enfoque, los usuarios pueden traducir fácilmente el título y el contenido de sus publicaciones o documentos directamente desde la interfaz de la aplicación.
Posted on March 10, 2024
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.