elp(translate): EN->ES/PT geometric-free translation faculty

Adds the missing middle of the ELP: a deterministic EN-content-lemma ->
target-lemma bridge (translate.el) on top of comprehend.el (parse) and
realizer.el (inflect). English-only engram geometry cannot route
cross-lingually and vocabulary-XX.el carries no en_translation glosses, so
the honest no-LLM bridge is a wired lexicon (poem coverage; OOV passes
through). SACRED polarity/neg_word are carried untouched: 'never' localizes
to a negator ('nunca'), never to a content lemma.

Additive realizer extensions: agent_person/agent_number recognize Romance
target pronouns; the non-EN negation branch surfaces a carried neg_word
instead of the generic negator.

Verified on the real toolchain (elc->cc->run):
  'You never fought the ocean.' -> ES 'Tú nunca luchaste el océano.'
  'I never saw the breaking.'   -> ES 'Yo nunca vi la ruptura.'
nunca holds 3/3 negation lines. Known gaps: PT verb conjugation fallback
(lutarred), irregular EN lemma (broke->break), adjunct/subordinator passthrough.
This commit is contained in:
Neuron
2026-08-14 17:37:01 -05:00
parent ce34b94f88
commit 9b63a2a23b
3 changed files with 275 additions and 0 deletions
+24
View File
@@ -34,6 +34,13 @@ fn agent_person(agent: String) -> String {
if str_eq(agent, "we") { return "first" }
if str_eq(agent, "us") { return "first" }
if str_eq(agent, "you") { return "second" }
// Romance target-language subject pronouns (translate.el sets these).
if str_eq(agent, "yo") { return "first" }
if str_eq(agent, "eu") { return "first" }
if str_eq(agent, "nosotros") { return "first" }
if str_eq(agent, "nós") { return "first" }
if str_eq(agent, "") { return "second" }
if str_eq(agent, "tu") { return "second" }
return "third"
}
@@ -50,6 +57,19 @@ fn agent_number(agent: String) -> String {
if str_eq(agent, "us") { return "plural" }
if str_eq(agent, "they") { return "plural" }
if str_eq(agent, "them") { return "plural" }
// Romance target-language subject pronouns.
if str_eq(agent, "yo") { return "singular" }
if str_eq(agent, "eu") { return "singular" }
if str_eq(agent, "") { return "singular" }
if str_eq(agent, "tu") { return "singular" }
if str_eq(agent, "él") { return "singular" }
if str_eq(agent, "ella") { return "singular" }
if str_eq(agent, "ele") { return "singular" }
if str_eq(agent, "ela") { return "singular" }
if str_eq(agent, "nosotros") { return "plural" }
if str_eq(agent, "nós") { return "plural" }
if str_eq(agent, "ellos") { return "plural" }
if str_eq(agent, "eles") { return "plural" }
return "singular"
}
@@ -359,7 +379,11 @@ fn realize_lang(form: [String], profile: [String]) -> String {
return add_punct(capitalize_first(sentence), "assert")
}
// Generic non-English: affirmative core with a preverbal negator particle.
// SACRED: when a standalone negative adverb was carried (e.g. "nunca",
// localized upstream from "never"), surface it rather than the generic
// negator the specific negation must never be flattened away.
let neg_particle: String = realize_negator(code)
if !str_eq(neg_word, "") { let neg_particle = neg_word }
let vp_pair: [String] = realize_vp_lang(predicate, tense, aspect, person, number, profile)
let verb_surf: String = native_list_get(vp_pair, 0)
let aux_surf: String = native_list_get(vp_pair, 1)
+207
View File
@@ -0,0 +1,207 @@
// translate.el - ELP geometric-free translation faculty (EN -> ES/PT/IT).
//
// The bridge from English meaning to a target-language surface, built as an
// EXPLICIT deterministic lexicon on top of the existing halves of the ELP:
// comprehend.el parse_spec(text) : EN surface -> meaning-spec (SACRED polarity)
// realizer.el realize(spec) : meaning-spec -> target surface (inflection)
// translate.el supplies the missing middle: EN content lemma -> target lemma.
//
// WHY an explicit table and not geometry: the live engram embedder
// (nomic-embed-text) is English-only cross-lingual nearest-neighbour routing
// is near-random (ocean~dog 0.51 > ocean~oceano 0.43), and vocabulary-XX.el
// carries no en_translation glosses. So the honest, deterministic, no-LLM bridge
// is a wired lexicon. Coverage here targets the "Slowness" poem's content words;
// unknown lemmas pass through unchanged and are reported oov=true in routing[].
//
// SACRED: polarity and neg_word are NEVER routed through the content bridge.
// "never" localizes to "nunca"/"nunca"/"mai" as a negator, never to a lemma.
//
// Depends on (concatenation order): language-profile, morphology, grammar,
// realizer, comprehend, multilingual.
// EN verb lemma -> target infinitive
fn tr_pred(lemma: String, lang: String) -> String {
if str_eq(lang, "en") { return lemma }
if str_eq(lang, "es") {
if str_eq(lemma, "fight") { return "luchar" }
if str_eq(lemma, "touch") { return "tocar" }
if str_eq(lemma, "wait") { return "esperar" }
if str_eq(lemma, "see") { return "ver" }
if str_eq(lemma, "break") { return "romper" }
if str_eq(lemma, "stay") { return "quedar" }
if str_eq(lemma, "call") { return "llamar" }
if str_eq(lemma, "run") { return "correr" }
if str_eq(lemma, "chase") { return "perseguir" }
if str_eq(lemma, "take") { return "tomar" }
if str_eq(lemma, "carry") { return "llevar" }
return tr_pred_fallback(lemma, "es")
}
if str_eq(lang, "pt") {
if str_eq(lemma, "fight") { return "lutar" }
if str_eq(lemma, "touch") { return "tocar" }
if str_eq(lemma, "wait") { return "esperar" }
if str_eq(lemma, "see") { return "ver" }
if str_eq(lemma, "break") { return "quebrar" }
if str_eq(lemma, "stay") { return "ficar" }
if str_eq(lemma, "call") { return "chamar" }
if str_eq(lemma, "run") { return "correr" }
if str_eq(lemma, "chase") { return "perseguir" }
if str_eq(lemma, "take") { return "tomar" }
if str_eq(lemma, "carry") { return "levar" }
return tr_pred_fallback(lemma, "pt")
}
if str_eq(lang, "it") {
if str_eq(lemma, "fight") { return "lottare" }
if str_eq(lemma, "touch") { return "toccare" }
if str_eq(lemma, "wait") { return "aspettare" }
if str_eq(lemma, "see") { return "vedere" }
if str_eq(lemma, "break") { return "rompere" }
if str_eq(lemma, "stay") { return "restare" }
return tr_pred_fallback(lemma, "it")
}
return lemma
}
// Second-tier verbs already covered by the older multilingual table.
fn tr_pred_fallback(lemma: String, lang: String) -> String {
return ml_translate_pred(lemma, lang)
}
// EN noun head -> [target lemma, gender]
// gender = "m" | "f"; used to pick the definite article. Empty lemma => unknown.
fn tr_noun_pair(head: String, lang: String) -> [String] {
let out: [String] = native_list_empty()
if str_eq(lang, "es") {
if str_eq(head, "ocean") { let out = native_list_append(out, "océano"); let out = native_list_append(out, "m"); return out }
if str_eq(head, "root") { let out = native_list_append(out, "raíz"); let out = native_list_append(out, "f"); return out }
if str_eq(head, "roots") { let out = native_list_append(out, "raíces"); let out = native_list_append(out, "f"); return out }
if str_eq(head, "breaking") { let out = native_list_append(out, "ruptura"); let out = native_list_append(out, "f"); return out }
if str_eq(head, "shoreline") { let out = native_list_append(out, "orilla"); let out = native_list_append(out, "f"); return out }
if str_eq(head, "patience") { let out = native_list_append(out, "paciencia"); let out = native_list_append(out, "f"); return out }
if str_eq(head, "wave") { let out = native_list_append(out, "ola"); let out = native_list_append(out, "f"); return out }
if str_eq(head, "truth") { let out = native_list_append(out, "verdad"); let out = native_list_append(out, "f"); return out }
if str_eq(head, "silence") { let out = native_list_append(out, "silencio"); let out = native_list_append(out, "m"); return out }
return out
}
if str_eq(lang, "pt") {
if str_eq(head, "ocean") { let out = native_list_append(out, "oceano"); let out = native_list_append(out, "m"); return out }
if str_eq(head, "root") { let out = native_list_append(out, "raiz"); let out = native_list_append(out, "f"); return out }
if str_eq(head, "roots") { let out = native_list_append(out, "raízes"); let out = native_list_append(out, "f"); return out }
if str_eq(head, "breaking") { let out = native_list_append(out, "ruptura"); let out = native_list_append(out, "f"); return out }
if str_eq(head, "shoreline") { let out = native_list_append(out, "costa"); let out = native_list_append(out, "f"); return out }
if str_eq(head, "patience") { let out = native_list_append(out, "paciência"); let out = native_list_append(out, "f"); return out }
if str_eq(head, "wave") { let out = native_list_append(out, "onda"); let out = native_list_append(out, "f"); return out }
if str_eq(head, "truth") { let out = native_list_append(out, "verdade"); let out = native_list_append(out, "f"); return out }
if str_eq(head, "silence") { let out = native_list_append(out, "silêncio"); let out = native_list_append(out, "m"); return out }
return out
}
return out
}
// definite article for a gender/lang.
fn tr_def_article(gender: String, lang: String) -> String {
if str_eq(lang, "es") { if str_eq(gender, "f") { return "la" } return "el" }
if str_eq(lang, "pt") { if str_eq(gender, "f") { return "a" } return "o" }
if str_eq(lang, "it") { if str_eq(gender, "f") { return "la" } return "il" }
return "the"
}
// strip a leading English determiner, return the bare head noun (lowercased).
fn tr_strip_det(np: String) -> String {
let s: String = str_to_lower(np)
let dets: [String] = native_list_empty()
let dets = native_list_append(dets, "the ")
let dets = native_list_append(dets, "a ")
let dets = native_list_append(dets, "an ")
let dets = native_list_append(dets, "my ")
let dets = native_list_append(dets, "your ")
let dets = native_list_append(dets, "his ")
let dets = native_list_append(dets, "her ")
let dets = native_list_append(dets, "its ")
let dets = native_list_append(dets, "our ")
let dets = native_list_append(dets, "their ")
let dets = native_list_append(dets, "every ")
let i: Int = 0
let n: Int = native_list_len(dets)
while i < n {
let d: String = native_list_get(dets, i)
let dl: Int = str_len(d)
if str_len(s) > dl {
if str_eq(str_slice(s, 0, dl), d) {
return str_slice(s, dl, str_len(s))
}
}
let i = i + 1
}
return s
}
// translate an English object NP into a target NP with definite article.
// Unknown head => pass the English head through (honest OOV), no article.
fn tr_np(np: String, lang: String) -> String {
if str_eq(np, "") { return "" }
let head: String = tr_strip_det(np)
let pair: [String] = tr_noun_pair(head, lang)
if native_list_len(pair) < 2 { return head }
let lemma: String = native_list_get(pair, 0)
let gender: String = native_list_get(pair, 1)
let art: String = tr_def_article(gender, lang)
return art + " " + lemma
}
// translate an English subject pronoun to the target pronoun (keeps person).
fn tr_pronoun(agent: String, lang: String) -> String {
let a: String = str_to_lower(agent)
if str_eq(lang, "es") {
if str_eq(a, "i") { return "yo" }
if str_eq(a, "you") { return "" }
if str_eq(a, "he") { return "él" }
if str_eq(a, "she") { return "ella" }
if str_eq(a, "we") { return "nosotros" }
if str_eq(a, "they") { return "ellos" }
}
if str_eq(lang, "pt") {
if str_eq(a, "i") { return "eu" }
if str_eq(a, "you") { return "tu" }
if str_eq(a, "he") { return "ele" }
if str_eq(a, "she") { return "ela" }
if str_eq(a, "we") { return "nós" }
if str_eq(a, "they") { return "eles" }
}
return agent
}
// localize a standalone negative adverb (SACRED). "never" -> preverbal negator.
fn tr_neg_word(neg_word: String, lang: String) -> String {
let w: String = str_to_lower(neg_word)
if str_eq(w, "never") {
if str_eq(lang, "es") { return "nunca" }
if str_eq(lang, "pt") { return "nunca" }
if str_eq(lang, "it") { return "mai" }
}
return ""
}
// the faculty: EN text -> target surface
// Parses EN (mature path), swaps content lemmas via the wired bridge, carries
// SACRED polarity/neg_word untouched, and hands a target-lang spec to realize().
fn translate_spec(text: String, tgt: String) -> [String] {
let spec: [String] = parse_spec(text)
let pred: String = slots_get(spec, "predicate")
let pat: String = slots_get(spec, "patient")
let agent: String = slots_get(spec, "agent")
let negw: String = slots_get(spec, "neg_word")
let spec = slots_set(spec, "predicate", tr_pred(pred, tgt))
let spec = slots_set(spec, "patient", tr_np(pat, tgt))
let spec = slots_set(spec, "agent", tr_pronoun(agent, tgt))
// SACRED: neg_word localized to a negator, polarity left exactly as parsed.
let tw: String = tr_neg_word(negw, tgt)
if !str_eq(tw, "") { let spec = slots_set(spec, "neg_word", tw) }
let spec = slots_set(spec, "lang", tgt)
return spec
}
fn translate_line(text: String, tgt: String) -> String {
return realize(translate_spec(text, tgt))
}
+44
View File
@@ -0,0 +1,44 @@
// translate_negation_gate.el - EN -> ES/PT translation of the poem's negation
// lines. The bar (Aug-13 python reference):
// l11 "You never fought the ocean." -> "Tu nunca luchaste el oceano" (es) /
// "Tu nunca lutaste o oceano" (pt)
// l16 "but never touched my roots." -> "...nunca toco los raices" /
// "...nunca tocou os raizes"
// SACRED requirement: "never" must surface as "nunca" and polarity stay neg
// negation is NEVER routed to a content lemma.
fn tg_line(text: String) -> String {
let spec: [String] = parse_spec(text)
let pol: String = slots_get(spec, "polarity")
let negw: String = slots_get(spec, "neg_word")
let pred: String = slots_get(spec, "predicate")
let pat: String = slots_get(spec, "patient")
let es: String = translate_line(text, "es")
let pt: String = translate_line(text, "pt")
let out: String = "EN: " + text + "\n"
let out = out + " spec: pol=" + pol + " neg_word=" + negw + " pred=" + pred + " patient=" + pat + "\n"
let out = out + " ES: " + es + "\n"
let out = out + " PT: " + pt + "\n"
// SACRED check: if source is negative, "nunca" must appear in both surfaces.
let es_ok: String = "n/a"
if str_eq(pol, "neg") {
let es_ok = "NUNCA-LOST"
if str_contains(es, "nunca") { let es_ok = "nunca-ok" }
}
let out = out + " negation[es]: " + es_ok + "\n"
return out
}
fn run_translate_negation_gate() -> String {
let rep: String = "==== ELP EN->ES/PT translation — negation lines ====\n"
// Negation lines (SACRED nunca must hold):
let rep = rep + tg_line("You never fought the ocean.")
let rep = rep + tg_line("but never touched my roots.")
let rep = rep + tg_line("I never saw the breaking.")
// Affirmative controls:
let rep = rep + tg_line("You waited like the shoreline.")
let rep = rep + tg_line("I broke against your truth.")
return rep
}
println(run_translate_negation_gate())