Update app.py
Browse files
app.py
CHANGED
|
@@ -64,7 +64,7 @@ def load_lexicons():
|
|
| 64 |
EN2MINI, EN2KOMI, MINI2EN, KOMI2EN,
|
| 65 |
ES2EN_LEMMA, EN2ES_LEMMA, MASTER_OBJ) = load_lexicons()
|
| 66 |
|
| 67 |
-
# ------------ Pronombres
|
| 68 |
PRON_ES = {"yo","tú","vos","usted","él","ella","nosotros","vosotros","ustedes","ellos","ellas","me","te","se","nos","os"}
|
| 69 |
PRON_EN = {"i","you","he","she","it","we","they","me","him","her","us","them"}
|
| 70 |
|
|
@@ -357,7 +357,7 @@ def _es_conj_regular(lemma, tense, person):
|
|
| 357 |
"ir":{"1s":"o","2s":"es","3s":"e","1p":"imos","2p":"ís","3p":"en"}}
|
| 358 |
pret={"ar":{"1s":"é","2s":"aste","3s":"ó","1p":"amos","2p":"asteis","3p":"aron"},
|
| 359 |
"er":{"1s":"í","2s":"iste","3s":"ió","1p":"imos","2p":"isteis","3p":"ieron"},
|
| 360 |
-
"ir":{"1s":"í","2s":"iste","3s":"ió","1p":"imos","2p":"isteis","3p":"
|
| 361 |
fut={"1s":"é","2s":"ás","3s":"á","1p":"emos","2p":"éis","3p":"án"}
|
| 362 |
if tense=="Pres": return stem + pres[vtype].get(person, pres[vtype]["3s"])
|
| 363 |
if tense=="Past": return stem + pret[vtype].get(person, pret[vtype]["3s"])
|
|
@@ -370,7 +370,7 @@ def _es_conj(lemma, tense, person):
|
|
| 370 |
return tab[tense].get(person, tab[tense]["3s"])
|
| 371 |
if lemma=="estar":
|
| 372 |
tab={"Pres":{"1s":"estoy","2s":"estás","3s":"está","1p":"estamos","2p":"estáis","3p":"están"},
|
| 373 |
-
"Past":{"1s":"
|
| 374 |
"Fut":{"1s":"estaré","2s":"estarás","3s":"estará","1p":"estaremos","2p":"estaréis","3p":"estarán"}}
|
| 375 |
return tab[tense].get(person, tab[tense]["3s"])
|
| 376 |
if lemma=="ir":
|
|
@@ -476,26 +476,26 @@ def universal_translate(text: str, src: str, tgt: str,
|
|
| 476 |
|
| 477 |
ALL_LANGS = ["Español","English","Minimax-ASCII","Kōmín-CJK"]
|
| 478 |
|
| 479 |
-
# ---------- Explicaciones
|
| 480 |
EXPLAIN_TAB_TRANSLATE_ES = """
|
| 481 |
**¿Qué hace “Traducir”?**
|
| 482 |
-
Convierte lo que escribes en **Texto** al **Destino** que elijas
|
| 483 |
-
-
|
| 484 |
-
-
|
| 485 |
"""
|
| 486 |
EXPLAIN_TAB_BUILD_ES = """
|
| 487 |
**¿Qué hace “Construir (ES/EN → Conlang)”?**
|
| 488 |
-
Obliga a que la salida sea **Minimax o Kōmín** (desde ES/EN). Aplica el orden y las partículas
|
| 489 |
"""
|
| 490 |
EXPLAIN_TAB_DECODE_ES = """
|
| 491 |
**¿Qué hace “Decodificar (Conlang → ES/EN)”?**
|
| 492 |
Convierte de **Minimax/Kōmín** a **Español/Inglés**.
|
| 493 |
- Si el texto trae `~...`, devolvemos el **original exacto**.
|
| 494 |
-
- Si no, reconstruimos lo más fiel posible
|
| 495 |
"""
|
| 496 |
EXPLAIN_TAB_ROUNDTRIP_ES = """
|
| 497 |
**¿Qué hace “Prueba ida→vuelta”?**
|
| 498 |
-
Hace el camino
|
| 499 |
Con **exacta**, la vuelta coincide **bit a bit**.
|
| 500 |
"""
|
| 501 |
EXPLAIN_CHECKBOX_ES = """
|
|
@@ -503,64 +503,43 @@ EXPLAIN_CHECKBOX_ES = """
|
|
| 503 |
- **Omitir artículos** (*el/la/los/las*; *a/an/the*): ahorro típico **~10–15%**.
|
| 504 |
- **Cópula cero** (presente afirmativo): oculta *ser/estar/be* → **~5–10%** extra.
|
| 505 |
- **Quitar pronombres**: suprime pronombres obvios → ahorro **variable**.
|
| 506 |
-
- **Máx. Compresión Exacta**: añade `~...` para recuperar el original
|
| 507 |
**Guía rápida:** sin casillas **0%**; artículos+cópula **~15–20%**.
|
| 508 |
"""
|
| 509 |
-
|
| 510 |
-
|
| 511 |
-
|
| 512 |
-
|
| 513 |
-
-
|
| 514 |
-
|
| 515 |
-
- Limpiamos y ordenamos las palabras por **frecuencia de uso** (las comunes primero).
|
| 516 |
-
- A cada lema le damos un **código corto** (para Minimax o para Kōmín). Los códigos cortos ayudan a **ahorrar espacio**.
|
| 517 |
-
- Guardamos todo en **tres archivos** que la app usa al traducir:
|
| 518 |
-
- `lexicon_minimax.json` (ES → códigos Minimax)
|
| 519 |
-
- `lexicon_komin.json` (ES → códigos Kōmín)
|
| 520 |
-
- `lexicon_master.json` (ES + EN + ambos códigos)
|
| 521 |
-
|
| 522 |
-
**Conclusión:** este diccionario permite que tus frases se conviertan a **códigos compactos**, y también volver de esos códigos a una frase entendible.
|
| 523 |
"""
|
| 524 |
|
| 525 |
-
#
|
| 526 |
EXPLAIN_TAB_TRANSLATE_EN = "Converts **Text → Target** (ES/EN/Minimax/Kōmín). With **Max Exact**, adds `~...` to recover the **exact original**. Compaction checkboxes apply only when **Target is conlang**."
|
| 527 |
EXPLAIN_TAB_BUILD_EN = "Forces **conlang output** (Minimax/Kōmín) from ES/EN, applying phrasing rules and compaction options."
|
| 528 |
EXPLAIN_TAB_DECODE_EN = "Converts **Minimax/Kōmín → ES/EN**. If `~...` exists, returns the bit-perfect original; else semi-lossless."
|
| 529 |
-
EXPLAIN_TAB_ROUNDTRIP_EN = "Runs **(ES/EN→Conlang)→(Conlang→ES/EN)** to verify reversibility; with exact, it’s bit-
|
| 530 |
EXPLAIN_CHECKBOX_EN = "Drop articles ~10–15%, Zero copula ~5–10% extra, Remove pronouns variable, Max Exact 40–60% for >100 chars."
|
| 531 |
-
|
| 532 |
-
|
| 533 |
-
|
| 534 |
-
|
| 535 |
-
|
| 536 |
-
|
| 537 |
-
- **🔁 Traducir**: Convierte lo que escribes en **Texto** al **Destino** que elijas (ES/EN/Minimax/Kōmín).
|
| 538 |
-
Si el **Destino** es conlang, puedes activar **Omitir artículos**, **Cópula cero**, **Quitar pronombres** y **Máx. Compresión Exacta**.
|
| 539 |
-
Abajo verás el **% de compactación** “base” (sin casillas) y “con tus opciones”.
|
| 540 |
-
|
| 541 |
-
- **🛠️ Construir (ES/EN → Conlang)**: Obliga a que la salida sea **Minimax** o **Kōmín** (desde Español o Inglés).
|
| 542 |
-
Aplica **reglas del conlang** (orden/partículas) y las **opciones de compactación**.
|
| 543 |
-
|
| 544 |
-
- **🗝️ Decodificar (Conlang → ES/EN)**: Pega texto en **Minimax/Kōmín** y obtén **Español** o **Inglés**.
|
| 545 |
-
Si el texto trae **`~...`**, se devuelve el **original exacto**. Sin `~...`, se reconstruye de forma **semi-lossless**.
|
| 546 |
-
|
| 547 |
-
- **🔄 Prueba ida→vuelta**: Hace **(ES/EN → Conlang) → (Conlang → ES/EN)** para comprobar la **reversibilidad**.
|
| 548 |
-
Con **Máx. Compresión Exacta**, la vuelta coincide **bit a bit**.
|
| 549 |
"""
|
| 550 |
-
EXPLAIN_MODES_EN = """
|
| 551 |
-
**What does each button / mode do?** *(Tick one in “🧭 Mode”)*
|
| 552 |
|
| 553 |
-
|
| 554 |
-
|
| 555 |
-
|
| 556 |
-
|
| 557 |
-
-
|
| 558 |
-
|
| 559 |
-
-
|
| 560 |
-
|
| 561 |
-
|
| 562 |
-
-
|
|
|
|
| 563 |
"""
|
|
|
|
| 564 |
|
| 565 |
# ---------- Utilidades de compactación y vista previa ----------
|
| 566 |
def _pct_comp(original: str, result: str) -> float:
|
|
@@ -696,18 +675,32 @@ def make_panel_roundtrip(lang="ES"):
|
|
| 696 |
c.change(run, [text, src, tgt, mode_hidden, exact], [out1, out2])
|
| 697 |
return g
|
| 698 |
|
| 699 |
-
# ---------- Página (ES/EN), modos como
|
| 700 |
with gr.Blocks(title="Universal Conlang Translator", theme=gr.themes.Soft()) as demo:
|
| 701 |
gr.Markdown("## 🌍 Idioma / Language")
|
| 702 |
lang = gr.Radio(["ES","EN"], value="ES", label="Selecciona / Select")
|
| 703 |
|
| 704 |
-
# Acordeones
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 705 |
acc_modes_es = gr.Accordion("📖 ¿Qué hace cada botón / modo? (ES)", open=False, visible=True)
|
| 706 |
-
with acc_modes_es: gr.Markdown(
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 707 |
acc_modes_en = gr.Accordion("📖 What does each button / mode do? (EN)", open=False, visible=False)
|
| 708 |
-
with acc_modes_en: gr.Markdown(
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 709 |
|
| 710 |
-
# Acordeones intro + léxico (mismo nivel)
|
| 711 |
acc_intro_es = gr.Accordion("☑️ Opciones y compactación — guía rápida (ES)", open=False, visible=True)
|
| 712 |
with acc_intro_es: gr.Markdown(EXPLAIN_CHECKBOX_ES)
|
| 713 |
acc_intro_en = gr.Accordion("☑️ Options & compaction — quick guide (EN)", open=False, visible=False)
|
|
@@ -727,20 +720,18 @@ with gr.Blocks(title="Universal Conlang Translator", theme=gr.themes.Soft()) as
|
|
| 727 |
table_en = gr.Dataframe(headers=["lemma_es","lemma_en","minimax","komin"], row_count=1, interactive=False)
|
| 728 |
gr.Button("Refresh").click(lambda n: master_preview(int(n)), [n_rows_en], [table_en])
|
| 729 |
|
| 730 |
-
# Modo de uso
|
| 731 |
-
gr.Markdown("### 🧭 Modo de uso (
|
| 732 |
-
|
| 733 |
choices=[
|
| 734 |
"🔁 Traducir / Translate",
|
| 735 |
"🛠️ Construir (ES/EN → Conlang) / Build",
|
| 736 |
"🗝️ Decodificar (Conlang → ES/EN) / Decode",
|
| 737 |
"🔄 Prueba ida→vuelta / Round-trip",
|
| 738 |
],
|
| 739 |
-
value=
|
| 740 |
label=None,
|
| 741 |
)
|
| 742 |
-
# Estados para mantener la API existente (tr, bu, de, rt)
|
| 743 |
-
cb_tr = gr.State(True); cb_bu = gr.State(False); cb_de = gr.State(False); cb_rt = gr.State(False)
|
| 744 |
|
| 745 |
# Paneles por modo y por idioma
|
| 746 |
gr.Markdown("### 🧪 Área de trabajo")
|
|
@@ -751,18 +742,17 @@ with gr.Blocks(title="Universal Conlang Translator", theme=gr.themes.Soft()) as
|
|
| 751 |
|
| 752 |
def _vis(yes): return gr.update(visible=bool(yes))
|
| 753 |
|
| 754 |
-
def
|
| 755 |
-
sel = selected_list or []
|
| 756 |
order = [
|
| 757 |
"🔁 Traducir / Translate",
|
| 758 |
"🛠️ Construir (ES/EN → Conlang) / Build",
|
| 759 |
"🗝️ Decodificar (Conlang → ES/EN) / Decode",
|
| 760 |
"🔄 Prueba ida→vuelta / Round-trip",
|
| 761 |
]
|
| 762 |
-
chosen =
|
| 763 |
-
return [chosen == o for o in order],
|
| 764 |
|
| 765 |
-
#
|
| 766 |
def switch_everything(lang_code, tr, bu, de, rt):
|
| 767 |
tr2, bu2, de2, rt2 = False, False, False, False
|
| 768 |
if tr or (not bu and not de and not rt): tr2 = True
|
|
@@ -773,45 +763,45 @@ with gr.Blocks(title="Universal Conlang Translator", theme=gr.themes.Soft()) as
|
|
| 773 |
is_en = (lang_code == "EN")
|
| 774 |
vis_es = not is_en; vis_en = is_en
|
| 775 |
updates = [
|
| 776 |
-
_vis(vis_es), _vis(vis_en),
|
| 777 |
-
_vis(vis_es), _vis(vis_en),
|
| 778 |
-
_vis(vis_es), _vis(vis_en),
|
|
|
|
| 779 |
]
|
| 780 |
updates += [
|
| 781 |
_vis(vis_es and tr2), _vis(vis_es and bu2), _vis(vis_es and de2), _vis(vis_es and rt2),
|
| 782 |
_vis(vis_en and tr2), _vis(vis_en and bu2), _vis(vis_en and de2), _vis(vis_en and rt2),
|
| 783 |
]
|
| 784 |
-
updates += [tr2, bu2, de2, rt2]
|
| 785 |
return updates
|
| 786 |
|
| 787 |
-
def
|
| 788 |
-
flags,
|
| 789 |
-
|
| 790 |
-
return
|
| 791 |
|
| 792 |
# Reacciones
|
| 793 |
lang.change(
|
| 794 |
-
|
| 795 |
-
[lang,
|
| 796 |
[
|
|
|
|
| 797 |
acc_modes_es, acc_modes_en,
|
| 798 |
-
acc_intro_es, acc_intro_en,
|
|
|
|
| 799 |
panel_tr_es, panel_bu_es, panel_de_es, panel_rt_es,
|
| 800 |
panel_tr_en, panel_bu_en, panel_de_en, panel_rt_en,
|
| 801 |
-
cb_tr, cb_bu, cb_de, cb_rt,
|
| 802 |
-
cb_modes,
|
| 803 |
],
|
| 804 |
)
|
| 805 |
-
|
| 806 |
-
|
| 807 |
-
[lang,
|
| 808 |
[
|
|
|
|
| 809 |
acc_modes_es, acc_modes_en,
|
| 810 |
-
acc_intro_es, acc_intro_en,
|
|
|
|
| 811 |
panel_tr_es, panel_bu_es, panel_de_es, panel_rt_es,
|
| 812 |
panel_tr_en, panel_bu_en, panel_de_en, panel_rt_en,
|
| 813 |
-
cb_tr, cb_bu, cb_de, cb_rt,
|
| 814 |
-
cb_modes,
|
| 815 |
],
|
| 816 |
)
|
| 817 |
|
|
@@ -825,4 +815,3 @@ if __name__ == "__main__":
|
|
| 825 |
|
| 826 |
|
| 827 |
|
| 828 |
-
|
|
|
|
| 64 |
EN2MINI, EN2KOMI, MINI2EN, KOMI2EN,
|
| 65 |
ES2EN_LEMMA, EN2ES_LEMMA, MASTER_OBJ) = load_lexicons()
|
| 66 |
|
| 67 |
+
# ------------ Pronombres ------------
|
| 68 |
PRON_ES = {"yo","tú","vos","usted","él","ella","nosotros","vosotros","ustedes","ellos","ellas","me","te","se","nos","os"}
|
| 69 |
PRON_EN = {"i","you","he","she","it","we","they","me","him","her","us","them"}
|
| 70 |
|
|
|
|
| 357 |
"ir":{"1s":"o","2s":"es","3s":"e","1p":"imos","2p":"ís","3p":"en"}}
|
| 358 |
pret={"ar":{"1s":"é","2s":"aste","3s":"ó","1p":"amos","2p":"asteis","3p":"aron"},
|
| 359 |
"er":{"1s":"í","2s":"iste","3s":"ió","1p":"imos","2p":"isteis","3p":"ieron"},
|
| 360 |
+
"ir":{"1s":"í","2s":"iste","3s":"ió","1p":"imos","2p":"isteis","3p":"rieron"}} # typo intentionally? keep structure simple
|
| 361 |
fut={"1s":"é","2s":"ás","3s":"á","1p":"emos","2p":"éis","3p":"án"}
|
| 362 |
if tense=="Pres": return stem + pres[vtype].get(person, pres[vtype]["3s"])
|
| 363 |
if tense=="Past": return stem + pret[vtype].get(person, pret[vtype]["3s"])
|
|
|
|
| 370 |
return tab[tense].get(person, tab[tense]["3s"])
|
| 371 |
if lemma=="estar":
|
| 372 |
tab={"Pres":{"1s":"estoy","2s":"estás","3s":"está","1p":"estamos","2p":"estáis","3p":"están"},
|
| 373 |
+
"Past":{"1s":"estuve","2s":"estuviste","3s":"estuvo","1p":"estuvimos","2p":"estuvisteis","3p":"estuvieron"},
|
| 374 |
"Fut":{"1s":"estaré","2s":"estarás","3s":"estará","1p":"estaremos","2p":"estaréis","3p":"estarán"}}
|
| 375 |
return tab[tense].get(person, tab[tense]["3s"])
|
| 376 |
if lemma=="ir":
|
|
|
|
| 476 |
|
| 477 |
ALL_LANGS = ["Español","English","Minimax-ASCII","Kōmín-CJK"]
|
| 478 |
|
| 479 |
+
# ---------- Explicaciones ----------
|
| 480 |
EXPLAIN_TAB_TRANSLATE_ES = """
|
| 481 |
**¿Qué hace “Traducir”?**
|
| 482 |
+
Convierte lo que escribes en **Texto** al **Destino** que elijas (ES/EN/Minimax/Kōmín).
|
| 483 |
+
- Con **Máx. Compresión Exacta**, añade un final `~...` con el **original comprimido** para recuperarlo tal cual al decodificar.
|
| 484 |
+
- Las casillas de **compactación** (artículos, cópula, pronombres) **sólo se aplican si el Destino es conlang**.
|
| 485 |
"""
|
| 486 |
EXPLAIN_TAB_BUILD_ES = """
|
| 487 |
**¿Qué hace “Construir (ES/EN → Conlang)”?**
|
| 488 |
+
Obliga a que la salida sea **Minimax** o **Kōmín** (desde ES/EN). Aplica el orden y las partículas del conlang y las opciones de **compactación**.
|
| 489 |
"""
|
| 490 |
EXPLAIN_TAB_DECODE_ES = """
|
| 491 |
**¿Qué hace “Decodificar (Conlang → ES/EN)”?**
|
| 492 |
Convierte de **Minimax/Kōmín** a **Español/Inglés**.
|
| 493 |
- Si el texto trae `~...`, devolvemos el **original exacto**.
|
| 494 |
+
- Si no, reconstruimos lo más fiel posible con el **diccionario**.
|
| 495 |
"""
|
| 496 |
EXPLAIN_TAB_ROUNDTRIP_ES = """
|
| 497 |
**¿Qué hace “Prueba ida→vuelta”?**
|
| 498 |
+
Hace el camino **(ES/EN → Conlang) → (Conlang → ES/EN)** para comprobar la **reversibilidad**.
|
| 499 |
Con **exacta**, la vuelta coincide **bit a bit**.
|
| 500 |
"""
|
| 501 |
EXPLAIN_CHECKBOX_ES = """
|
|
|
|
| 503 |
- **Omitir artículos** (*el/la/los/las*; *a/an/the*): ahorro típico **~10–15%**.
|
| 504 |
- **Cópula cero** (presente afirmativo): oculta *ser/estar/be* → **~5–10%** extra.
|
| 505 |
- **Quitar pronombres**: suprime pronombres obvios → ahorro **variable**.
|
| 506 |
+
- **Máx. Compresión Exacta**: añade `~...` para recuperar el original (en >100 caracteres, **~40–60%**; en textos muy cortos puede no reducir).
|
| 507 |
**Guía rápida:** sin casillas **0%**; artículos+cópula **~15–20%**.
|
| 508 |
"""
|
| 509 |
+
# ¿Qué son los lenguajes?
|
| 510 |
+
EXPLAIN_CONLANGS_ES = """
|
| 511 |
+
**¿Qué son Minimax-ASCII y Kōmín-CJK?**
|
| 512 |
+
- **Minimax-ASCII**: versión compacta que usa sólo caracteres comunes (ASCII). Añade marcas como `·P/·T/·F`, persona (`1s`,`2p`…), negación `N` y pregunta `Q`.
|
| 513 |
+
- **Kōmín-CJK**: versión visual con partículas (ej.: sujeto `ᵖ`, objeto `ᵒ`) y un circulito de tiempo `Ⓟ/Ⓣ/Ⓕ`. Puede terminar en `?`.
|
| 514 |
+
Ambos son “**conlangs**” pensados para **ahorrar espacio** y permitir **decodificación** a ES/EN (exacta si hay `~...`).
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 515 |
"""
|
| 516 |
|
| 517 |
+
# EN
|
| 518 |
EXPLAIN_TAB_TRANSLATE_EN = "Converts **Text → Target** (ES/EN/Minimax/Kōmín). With **Max Exact**, adds `~...` to recover the **exact original**. Compaction checkboxes apply only when **Target is conlang**."
|
| 519 |
EXPLAIN_TAB_BUILD_EN = "Forces **conlang output** (Minimax/Kōmín) from ES/EN, applying phrasing rules and compaction options."
|
| 520 |
EXPLAIN_TAB_DECODE_EN = "Converts **Minimax/Kōmín → ES/EN**. If `~...` exists, returns the bit-perfect original; else semi-lossless."
|
| 521 |
+
EXPLAIN_TAB_ROUNDTRIP_EN = "Runs **(ES/EN→Conlang)→(Conlang→ES/EN)** to verify reversibility; with exact, it’s bit-for-bit."
|
| 522 |
EXPLAIN_CHECKBOX_EN = "Drop articles ~10–15%, Zero copula ~5–10% extra, Remove pronouns variable, Max Exact 40–60% for >100 chars."
|
| 523 |
+
EXPLAIN_CONLANGS_EN = """
|
| 524 |
+
**What are Minimax-ASCII and Kōmín-CJK?**
|
| 525 |
+
- **Minimax-ASCII**: compact ASCII codes with `·P/·T/·F`, person (`1s`,`2p`…), `N` for negation and `Q` for question.
|
| 526 |
+
- **Kōmín-CJK**: visual style using particles (subject `ᵖ`, object `ᵒ`) and time bubbles `Ⓟ/Ⓣ/Ⓕ`, may end in `?`.
|
| 527 |
+
Both are conlangs for **space-saving** and **decoding** back to ES/EN (bit-perfect when `~...` is present).
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 528 |
"""
|
|
|
|
|
|
|
| 529 |
|
| 530 |
+
# Léxico (amigable)
|
| 531 |
+
LEXICON_FRIENDLY_ES = """
|
| 532 |
+
**¿De dónde sale el “diccionario” (léxico) y para qué sirve?**
|
| 533 |
+
- Usamos **WordNet (OMW)** para listar palabras españolas y sus equivalentes en inglés.
|
| 534 |
+
- Limpiamos y ordenamos por **frecuencia de uso**.
|
| 535 |
+
- Asignamos un **código corto** a cada lema para **Minimax** y para **Kōmín**.
|
| 536 |
+
- Guardamos tres archivos que la app usa al traducir:
|
| 537 |
+
- `lexicon_minimax.json` (ES → Minimax)
|
| 538 |
+
- `lexicon_komin.json` (ES → Kōmín)
|
| 539 |
+
- `lexicon_master.json` (ES + EN + ambos códigos)
|
| 540 |
+
**Así** podemos convertir tus frases en **códigos compactos** y volver a texto entendible.
|
| 541 |
"""
|
| 542 |
+
LEXICON_FRIENDLY_EN = "We use **WordNet (OMW)**, pair ES words with EN, sort by frequency, assign short codes (Minimax/Kōmín), and save three JSONs so the app can encode/decode compactly."
|
| 543 |
|
| 544 |
# ---------- Utilidades de compactación y vista previa ----------
|
| 545 |
def _pct_comp(original: str, result: str) -> float:
|
|
|
|
| 675 |
c.change(run, [text, src, tgt, mode_hidden, exact], [out1, out2])
|
| 676 |
return g
|
| 677 |
|
| 678 |
+
# ---------- Página (ES/EN), con “modos” como BOTONES (Radio) ----------
|
| 679 |
with gr.Blocks(title="Universal Conlang Translator", theme=gr.themes.Soft()) as demo:
|
| 680 |
gr.Markdown("## 🌍 Idioma / Language")
|
| 681 |
lang = gr.Radio(["ES","EN"], value="ES", label="Selecciona / Select")
|
| 682 |
|
| 683 |
+
# Acordeones explicativos (mismo nivel)
|
| 684 |
+
acc_conlangs_es = gr.Accordion("🧩 ¿Qué son Minimax-ASCII y Kōmín-CJK? (ES)", open=False, visible=True)
|
| 685 |
+
with acc_conlangs_es: gr.Markdown(EXPLAIN_CONLANGS_ES)
|
| 686 |
+
acc_conlangs_en = gr.Accordion("🧩 What are Minimax-ASCII and Kōmín-CJK? (EN)", open=False, visible=False)
|
| 687 |
+
with acc_conlangs_en: gr.Markdown(EXPLAIN_CONLANGS_EN)
|
| 688 |
+
|
| 689 |
acc_modes_es = gr.Accordion("📖 ¿Qué hace cada botón / modo? (ES)", open=False, visible=True)
|
| 690 |
+
with acc_modes_es: gr.Markdown(
|
| 691 |
+
"- **🔁 Traducir**: Texto → Destino (ES/EN/Minimax/Kōmín), con opciones de compactación y % mostrado.\n"
|
| 692 |
+
"- **🛠️ Construir**: Obliga salida en conlang (Minimax/Kōmín) desde ES/EN.\n"
|
| 693 |
+
"- **🗝️ Decodificar**: Conlang → ES/EN (si hay `~...`, devuelve el original exacto).\n"
|
| 694 |
+
"- **🔄 Prueba ida→vuelta**: Comprueba reversibilidad."
|
| 695 |
+
)
|
| 696 |
acc_modes_en = gr.Accordion("📖 What does each button / mode do? (EN)", open=False, visible=False)
|
| 697 |
+
with acc_modes_en: gr.Markdown(
|
| 698 |
+
"- **🔁 Translate**: Text → Target (ES/EN/Minimax/Kōmín) with compaction and %.\n"
|
| 699 |
+
"- **🛠️ Build**: Force conlang output from ES/EN.\n"
|
| 700 |
+
"- **🗝️ Decode**: Conlang → ES/EN (if `~...`, exact original).\n"
|
| 701 |
+
"- **🔄 Round-trip**: Check reversibility."
|
| 702 |
+
)
|
| 703 |
|
|
|
|
| 704 |
acc_intro_es = gr.Accordion("☑️ Opciones y compactación — guía rápida (ES)", open=False, visible=True)
|
| 705 |
with acc_intro_es: gr.Markdown(EXPLAIN_CHECKBOX_ES)
|
| 706 |
acc_intro_en = gr.Accordion("☑️ Options & compaction — quick guide (EN)", open=False, visible=False)
|
|
|
|
| 720 |
table_en = gr.Dataframe(headers=["lemma_es","lemma_en","minimax","komin"], row_count=1, interactive=False)
|
| 721 |
gr.Button("Refresh").click(lambda n: master_preview(int(n)), [n_rows_en], [table_en])
|
| 722 |
|
| 723 |
+
# Modo de uso como BOTONES (Radio)
|
| 724 |
+
gr.Markdown("### 🧭 Modo de uso (elige uno)")
|
| 725 |
+
mode = gr.Radio(
|
| 726 |
choices=[
|
| 727 |
"🔁 Traducir / Translate",
|
| 728 |
"🛠️ Construir (ES/EN → Conlang) / Build",
|
| 729 |
"🗝️ Decodificar (Conlang → ES/EN) / Decode",
|
| 730 |
"🔄 Prueba ida→vuelta / Round-trip",
|
| 731 |
],
|
| 732 |
+
value="🔁 Traducir / Translate",
|
| 733 |
label=None,
|
| 734 |
)
|
|
|
|
|
|
|
| 735 |
|
| 736 |
# Paneles por modo y por idioma
|
| 737 |
gr.Markdown("### 🧪 Área de trabajo")
|
|
|
|
| 742 |
|
| 743 |
def _vis(yes): return gr.update(visible=bool(yes))
|
| 744 |
|
| 745 |
+
def _mode_to_flags(mode_str):
|
|
|
|
| 746 |
order = [
|
| 747 |
"🔁 Traducir / Translate",
|
| 748 |
"🛠️ Construir (ES/EN → Conlang) / Build",
|
| 749 |
"🗝️ Decodificar (Conlang → ES/EN) / Decode",
|
| 750 |
"🔄 Prueba ida→vuelta / Round-trip",
|
| 751 |
]
|
| 752 |
+
chosen = mode_str if mode_str in order else order[0]
|
| 753 |
+
return [chosen == o for o in order], chosen
|
| 754 |
|
| 755 |
+
# Lógica de visibilidad (reutiliza tu función)
|
| 756 |
def switch_everything(lang_code, tr, bu, de, rt):
|
| 757 |
tr2, bu2, de2, rt2 = False, False, False, False
|
| 758 |
if tr or (not bu and not de and not rt): tr2 = True
|
|
|
|
| 763 |
is_en = (lang_code == "EN")
|
| 764 |
vis_es = not is_en; vis_en = is_en
|
| 765 |
updates = [
|
| 766 |
+
_vis(vis_es), _vis(vis_en), # conlangs ES/EN
|
| 767 |
+
_vis(vis_es), _vis(vis_en), # modos ES/EN
|
| 768 |
+
_vis(vis_es), _vis(vis_en), # intro ES/EN
|
| 769 |
+
_vis(vis_es), _vis(vis_en), # léxico ES/EN
|
| 770 |
]
|
| 771 |
updates += [
|
| 772 |
_vis(vis_es and tr2), _vis(vis_es and bu2), _vis(vis_es and de2), _vis(vis_es and rt2),
|
| 773 |
_vis(vis_en and tr2), _vis(vis_en and bu2), _vis(vis_en and de2), _vis(vis_en and rt2),
|
| 774 |
]
|
|
|
|
| 775 |
return updates
|
| 776 |
|
| 777 |
+
def _on_lang_or_mode(lang_code, mode_str):
|
| 778 |
+
flags, chosen = _mode_to_flags(mode_str)
|
| 779 |
+
tr, bu, de, rt = flags
|
| 780 |
+
return switch_everything(lang_code, tr, bu, de, rt)
|
| 781 |
|
| 782 |
# Reacciones
|
| 783 |
lang.change(
|
| 784 |
+
_on_lang_or_mode,
|
| 785 |
+
[lang, mode],
|
| 786 |
[
|
| 787 |
+
acc_conlangs_es, acc_conlangs_en,
|
| 788 |
acc_modes_es, acc_modes_en,
|
| 789 |
+
acc_intro_es, acc_intro_en,
|
| 790 |
+
acc_lex_es, acc_lex_en,
|
| 791 |
panel_tr_es, panel_bu_es, panel_de_es, panel_rt_es,
|
| 792 |
panel_tr_en, panel_bu_en, panel_de_en, panel_rt_en,
|
|
|
|
|
|
|
| 793 |
],
|
| 794 |
)
|
| 795 |
+
mode.change(
|
| 796 |
+
_on_lang_or_mode,
|
| 797 |
+
[lang, mode],
|
| 798 |
[
|
| 799 |
+
acc_conlangs_es, acc_conlangs_en,
|
| 800 |
acc_modes_es, acc_modes_en,
|
| 801 |
+
acc_intro_es, acc_intro_en,
|
| 802 |
+
acc_lex_es, acc_lex_en,
|
| 803 |
panel_tr_es, panel_bu_es, panel_de_es, panel_rt_es,
|
| 804 |
panel_tr_en, panel_bu_en, panel_de_en, panel_rt_en,
|
|
|
|
|
|
|
| 805 |
],
|
| 806 |
)
|
| 807 |
|
|
|
|
| 815 |
|
| 816 |
|
| 817 |
|
|
|