| 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) |
|
|