Traduceme / app.py
tx3bas's picture
Update app.py
a6ce0c1 verified
raw
history blame
4.11 kB
import gradio as gr
from mtranslate import translate
from bs4 import BeautifulSoup, NavigableString
import re
import uuid
import time # Simulación de carga
# Diccionario de idiomas
lang_dict = {
'Auto': 'auto',
'Español': 'es',
'English': 'en',
}
lang_list = [k for k in lang_dict.keys() if k != 'Auto']
source_lang_list = ['Auto'] + lang_list
def split_text(text, limit=4000):
sentences = re.split(r'([;.])', text)
chunks = []
chunk = ''
for i in range(0, len(sentences), 2):
sentence = sentences[i] + (sentences[i+1] if i+1 < len(sentences) else '')
if len(chunk) + len(sentence) > limit:
chunks.append(chunk)
chunk = sentence
else:
chunk += sentence
if chunk:
chunks.append(chunk)
return chunks
def translate_html_content(text, source_lang, target_lang):
soup = BeautifulSoup(text, 'html.parser')
# Traducir nodos de texto
for node in soup.find_all(string=True): # Cambiado de text=True a string=True
if isinstance(node, NavigableString) and node.strip():
original_text = node.strip()
chunks = split_text(original_text)
translated_chunks = [translate(chunk, target_lang, source_lang) for chunk in chunks]
translated_text = ''.join(translated_chunks)
# Verificar espacios antes y después del nodo
if node.previous_sibling and isinstance(node.previous_sibling, NavigableString):
translated_text = ' ' + translated_text
if node.next_sibling and isinstance(node.next_sibling, NavigableString):
if not node.next_sibling.startswith(' '): # Verificación adicional
translated_text += ' '
node.replace_with(translated_text)
return str(soup)
def main(Texto, source_lang, target_lang):
source_code = lang_dict[source_lang]
target_code = lang_dict[target_lang]
# Simulación de tiempo de procesamiento para UX mejorada
time.sleep(2)
translated_text = translate_html_content(Texto, source_code, target_code)
element_id = f"text-{uuid.uuid4()}"
html_output = f"""
<div style="position: relative; min-height: 100px; padding: 10px; border: 1px solid #ddd; border-radius: 5px;">
<div id="translated-content" style="font-family: Arial, sans-serif; font-size: 16px;">{translated_text}</div>
<textarea id="{element_id}" style="display: none;">{translated_text}</textarea>
<button onclick="navigator.clipboard.writeText(document.getElementById('{element_id}').value).then(() => alert('Texto copiado'))"
style="margin-top: 10px; padding: 5px 10px; background: #007bff; color: white; border: none; border-radius: 4px; cursor: pointer;">
📋 Copiar Traducción
</button>
</div>
"""
return html_output
# --- INTERFAZ MEJORADA ---
title = """<h1 align="center">🌍 Traductor Inteligente de HTML 🌍</h1>"""
description = """<h3 align="center">💬 Traduce contenido HTML sin perder el formato. 🚀</h3>"""
with gr.Blocks(theme=gr.themes.Soft(primary_hue="blue")) as demo:
gr.HTML(title)
gr.HTML(description)
with gr.Row():
with gr.Column():
Texto = gr.Textbox(label="Introduce tu HTML aquí", placeholder="Escribe o pega un texto con HTML...", lines=10)
with gr.Column():
output = gr.HTML(label="Texto traducido")
with gr.Row():
source_lang = gr.Dropdown(source_lang_list, value="Auto", label="Idioma de origen")
target_lang = gr.Dropdown(lang_list, value="Español", label="Idioma de destino")
with gr.Row():
translate_btn = gr.Button("🌎 Traducir")
clear_btn = gr.Button("🧹 Limpiar")
# Indicador de carga
status = gr.Textbox(label="Estado", interactive=False, visible=False)
# Conectar eventos
translate_btn.click(main, [Texto, source_lang, target_lang], output, show_progress=True)
clear_btn.click(lambda: "", [], Texto)
# Activa el modo streaming para mejor experiencia
demo.queue().launch(debug=True)