|
import gradio as gr |
|
from mtranslate import translate |
|
from bs4 import BeautifulSoup, NavigableString |
|
import re |
|
import uuid |
|
import time |
|
|
|
|
|
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') |
|
|
|
|
|
for node in soup.find_all(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) |
|
|
|
|
|
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(' '): |
|
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] |
|
|
|
|
|
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 |
|
|
|
|
|
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") |
|
|
|
|
|
status = gr.Textbox(label="Estado", interactive=False, visible=False) |
|
|
|
|
|
translate_btn.click(main, [Texto, source_lang, target_lang], output, show_progress=True) |
|
clear_btn.click(lambda: "", [], Texto) |
|
|
|
|
|
demo.queue().launch(debug=True) |
|
|