/* * spa-variants.js — one Spanish translation, two Spanish congregations. * * WHY ONLY ONE DIRECTION IS IMPLEMENTED, AND IT IS NOT THE ONE ASKED FOR. * * Converting Latin American Spanish INTO Peninsular (ustedes -> vosotros) was * specified, built on paper, and then measured against this church's own * archive of 5,954 English->Spanish pairs. It has to be abandoned, because the * information it needs is not in the input: * * - Spanish 3rd-person-plural is IDENTICAL for "ustedes" (you all) and * "ellos" (they). English resolves person but not NUMBER, and in 98.9% of * the sentences a gate would fire on, whether "you" was one person or a * room is simply undetermined. * - Spanish uses 3PL as its impersonal/passive, so the very condition that * triggers a conversion is what creates the false positives. Measured, real: * "You're not accepted on the basis of your religious works." * NLLB: "No te aceptan por tus obras religiosas." * after: "no te aceptáis" = "you don't accept yourself" * That inverts grace into works-salvation, fluently, in a synthesized voice, * for listeners who cannot detect it. * - "su" means his/her/its/their/your-formal. Of the sentences carrying it, * 25.2% provably could NOT mean "your" — the English has no "your" at all. * "Él te recibirá como su hijo" ("as HIS son") would become "as YOUR son". * - Provable wins 68, provable losses 46, on 22.6% of rows. Every uncounted * loss class pushes that under 1:1. * * THE INVERSE DIRECTION IS SAFE, and that asymmetry is the whole design. * vosotros, vuestro, os, -áis, -éis and the -ad/-ed/-id imperative can ONLY be * second-person-plural. There is nothing to disambiguate. So Peninsular forms * can be normalised OUT of Latin American output with no risk at all — and NLLB * does leak them: 27 rows in the archive, including "lavará vuestros pecados" * and "Hacéis esto". * * Result: Spain gets the same words in a Castilian voice (the thing a Spaniard * notices first), and Latin America gets Spanish that is consistently Latin * American instead of occasionally Peninsular. */ (function (root, factory) { if (typeof module === 'object' && module.exports) module.exports = factory(); else root.SpaVariants = factory(); }(typeof self !== 'undefined' ? self : this, function () { 'use strict'; /* Accent-aware boundaries. JS \b is [A-Za-z0-9_], so /\bvosotros\b/ is fine but /\bhabláis\b/ breaks at the á — the trap pt-variants.js documents. */ const W = '\\p{L}\\p{N}\\p{M}'; const RE = (body, flags) => new RegExp('(? 3rd-person-plural (the ustedes form). * * THREE FORMS ARE DELIBERATELY ABSENT. Matching is case-insensitive, so any * short form that is also an ordinary word is a landmine: * "sed" (ser, "be ye") is the noun THIRST — measured 5 times in this * church's archive, every one of them the noun, in a sermon about a * man dying of thirst in the desert. It turned "morir de sed" into * "morir de sean". Caught only by running the real corpus. * "id" (ir, "go ye") collides with the English "ID". * "dad" (dar, "give ye") collides with the English "dad". * All three are vanishingly rare in NLLB output and common as other words. * Do not add them back. */ const VERBS = { /* ser / estar / haber / ir */ 'sois': 'son', 'erais': 'eran', 'fuisteis': 'fueron', 'seréis': 'serán', 'seáis': 'sean', 'estáis': 'están', 'estabais': 'estaban', 'estuvisteis': 'estuvieron', 'estaréis': 'estarán', 'estéis': 'estén', 'habéis': 'han', 'habíais': 'habían', 'hubisteis': 'hubieron', 'habréis': 'habrán', 'hayáis': 'hayan', 'vais': 'van', 'ibais': 'iban', 'fuisteis2': 'fueron', 'iréis': 'irán', 'vayáis': 'vayan', /* high-frequency irregulars */ 'tenéis': 'tienen', 'teníais': 'tenían', 'tuvisteis': 'tuvieron', 'tendréis': 'tendrán', 'tengáis': 'tengan', 'tened': 'tengan', 'hacéis': 'hacen', 'hacíais': 'hacían', 'hicisteis': 'hicieron', 'haréis': 'harán', 'hagáis': 'hagan', 'haced': 'hagan', 'podéis': 'pueden', 'podíais': 'podían', 'pudisteis': 'pudieron', 'podréis': 'podrán', 'podáis': 'puedan', 'queréis': 'quieren', 'queríais': 'querían', 'quisisteis': 'quisieron', 'querréis': 'querrán', 'queráis': 'quieran', 'decís': 'dicen', 'decíais': 'decían', 'dijisteis': 'dijeron', 'diréis': 'dirán', 'digáis': 'digan', 'decid': 'digan', 'venís': 'vienen', 'veníais': 'venían', 'vinisteis': 'vinieron', 'vendréis': 'vendrán', 'vengáis': 'vengan', 'venid': 'vengan', 'sabéis': 'saben', 'sabíais': 'sabían', 'supisteis': 'supieron', 'sabréis': 'sabrán', 'sepáis': 'sepan', 'dais': 'dan', 'dabais': 'daban', 'disteis': 'dieron', 'daréis': 'darán', 'deis': 'den', 'veis': 'ven', 'veíais': 'veían', 'visteis': 'vieron', 'veréis': 'verán', 'veáis': 'vean', 'ved': 'vean', 'ponéis': 'ponen', 'pusisteis': 'pusieron', 'pondréis': 'pondrán', 'pongáis': 'pongan', 'poned': 'pongan', 'salís': 'salen', 'salisteis': 'salieron', 'saldréis': 'saldrán', 'salgáis': 'salgan', 'salid': 'salgan', 'oís': 'oyen', 'oísteis': 'oyeron', 'oiréis': 'oirán', 'oigáis': 'oigan', 'oíd': 'oigan', /* regular verbs a preacher actually uses */ 'habláis': 'hablan', 'hablabais': 'hablaban', 'hablasteis': 'hablaron', 'hablaréis': 'hablarán', 'habléis': 'hablen', 'hablad': 'hablen', 'miráis': 'miran', 'mirasteis': 'miraron', 'miréis': 'miren', 'mirad': 'miren', 'escucháis': 'escuchan', 'escuchasteis': 'escucharon', 'escuchéis': 'escuchen', 'escuchad': 'escuchen', 'oráis': 'oran', 'orasteis': 'oraron', 'oréis': 'oren', 'orad': 'oren', 'rezáis': 'oran', 'rezasteis': 'oraron', 'recéis': 'oren', 'rezad': 'oren', 'creéis': 'creen', 'creíais': 'creían', 'creísteis': 'creyeron', 'creáis': 'crean', 'creed': 'crean', 'vivís': 'viven', 'vivíais': 'vivían', 'vivisteis': 'vivieron', 'viváis': 'vivan', 'vivid': 'vivan', 'abrís': 'abren', 'abristeis': 'abrieron', 'abráis': 'abran', 'abrid': 'abran', 'recibís': 'reciben', 'recibisteis': 'recibieron', 'recibáis': 'reciban', 'recibid': 'reciban', 'entendéis': 'entienden', 'entendisteis': 'entendieron', 'entendáis': 'entiendan', 'buscáis': 'buscan', 'buscasteis': 'buscaron', 'busquéis': 'busquen', 'buscad': 'busquen', 'amáis': 'aman', 'amasteis': 'amaron', 'améis': 'amen', 'amad': 'amen', 'sentís': 'sienten', 'sentisteis': 'sintieron', 'sintáis': 'sientan', 'pedís': 'piden', 'pedisteis': 'pidieron', 'pidáis': 'pidan', 'pedid': 'pidan', 'volvéis': 'vuelven', 'volvisteis': 'volvieron', 'volváis': 'vuelvan', 'volved': 'vuelvan', 'llegáis': 'llegan', 'llegasteis': 'llegaron', 'lleguéis': 'lleguen', 'levantáis': 'levantan', 'levantad': 'levanten', 'levantaos': 'levántense', 'sentaos': 'siéntense', 'arrepentíos': 'arrepiéntanse', 'acercaos': 'acérquense', /* Reflexive imperatives change the stem and move the accent, so they are named rather than derived. These are the ones that actually occur in Peninsular scripture. */ 'despojaos': 'despójense', 'renovaos': 'renuévense', 'vestíos': 'vístanse', 'airaos': 'aírense', 'alegraos': 'alégrense', 'regocijaos': 'regocíjense', 'humillaos': 'humíllense', 'apartaos': 'apártense', 'acordaos': 'acuérdense', 'guardaos': 'guárdense', 'someteos': 'sométanse', 'revestíos': 'revístanse', 'volveos': 'vuélvanse', 'allegaos': 'acérquense', 'mirad': 'miren' }; delete VERBS['fuisteis2']; /* * Pronouns and possessives. This direction needs NO noun gender, which is * precisely what made the reverse direction impossible: "su" is invariant, * while "vuestro" must agree with the possessed noun in gender AND number. */ const GRAMMAR = [ [RE('vosotros|vosotras'), 'ustedes'], [RE('vuestros|vuestras'), 'sus'], [RE('vuestro|vuestra'), 'su'], /* The 2pl clitic. Anchored, because "os" is two letters and sits inside hundreds of words. */ [RE('os'), 'les'] ]; /* * Lexical Peninsular leakage, all observed in the archive. Deliberately tiny: * an unobserved entry is a guess, and a guess here is a silent error. */ const LEXICON = [ [RE('coches'), 'carros'], [RE('coche'), 'carro'], [RE('gafas'), 'lentes'], [RE('ordenadores'), 'computadoras'], [RE('ordenador'), 'computadora'], [RE('móviles'), 'celulares'], [RE('zumo'), 'jugo'], [RE('patatas'), 'papas'], [RE('patata'), 'papa'], [RE('piso'), 'departamento'], [RE('chavales'), 'muchachos'], [RE('chaval'), 'muchacho'] ]; /* * "vale" is a homograph and the archive contains both senses: * interjection "Vale, pensemos..." -> Peninsular, convert * the verb "No vale la pena." -> universal, MUST NOT convert * Only the sentence-initial interjection followed by a comma is touched. */ const VALE = /(^|[.!?¡¿]\s*)Vale,/g; /* * Regular paradigm, as ORDERED SUFFIX rules, applied after the explicit table * so irregulars (estáis->están, sois->son) always win. * * These endings are safe where a bare "-ís" or "-ad" is not: -áis, -éis, * -abais, -íais, -asteis, -isteis, -réis and -ríais occur in Spanish ONLY as * second-person-plural verb inflections. There is no noun or adjective with * any of them, so no homograph can be caught. * * ORDER MATTERS. The future is -réis and maps to -rán, not to -ren: without * the -réis rule first, "hablaréis" would become "hablaren" rather than * "hablarán". Longest and most specific first, throughout. */ const SUFFIX = [ [/(\w{2,})ríais\b/giu, '$1rían'], // conditional: hablaríais -> hablarían [/(\w{2,})réis\b/giu, '$1rán'], // future: hablaréis -> hablarán [/(\w{2,})abais\b/giu, '$1aban'], // imperfect -ar [/(\w{2,})íais\b/giu, '$1ían'], // imperfect -er/-ir [/(\w{2,})asteis\b/giu,'$1aron'], // preterite -ar [/(\w{2,})isteis\b/giu,'$1ieron'], // preterite -er/-ir [/(\w{2,})áis\b/giu, '$1an'], // present -ar / subjunctive -er,-ir [/(\w{2,})éis\b/giu, '$1en'] // present -er / subjunctive -ar ]; /* * DENOMINATIONAL REGISTER, and it applies to every Spanish variant — this is * not a regional question. * * RAE separates the two verbs: `orar` is "dirigirse mentalmente o de palabra * a una divinidad" — extempore prayer, the evangelical default. `rezar` is * from Latin recitare, "recitar la misa, una oracion", i.e. saying a SET * prayer, and is Catholic-coded. NLLB picks between them at random: measured * across this church's archive, 15 rows chose rezar and 14 chose orar, for * the same English word "pray". So a Protestant congregation hears * "Rezo para que..." — which reads as reciting a liturgical formula. * * Straight lexical substitution, no ambiguity in the verb forms. ONE guard: * "rezo" is also a NOUN (a recited prayer), and mapping the noun would say * "oro" = GOLD. Every occurrence in the archive is the verb, but the * determiner lookbehind makes the noun unreachable regardless. */ const PRAY = [ [RE('rezar'), 'orar'], [RE('rezando'), 'orando'], [RE('rezado'), 'orado'], [RE('rezamos'), 'oramos'], [RE('rezaban'), 'oraban'], [RE('rezaba'), 'oraba'], [RE('rezaron'), 'oraron'], [RE('rezan'), 'oran'], [RE('rezas'), 'oras'], [RE('recemos'), 'oremos'], [RE('recen'), 'oren'], [RE('reces'), 'ores'], [RE('rece'), 'ore'], [RE('reza'), 'ora'], /* the noun guard */ [/(? correct form, with zero * collateral. Real-but-wrong forms ("Bendijo" for "I bless") are NOT here: * they are words, and a table cannot know the person the speaker meant. * * bendíalo/bendíelo -> bendigámoslo (1pl hortative "let us bless him"), * deliberately not the fluent-but-wrong tú imperative bendícelo. * bendicié -> bendice is kept: "Bendice tu nombre" is grammatical praise * where the non-word was noise; flagged advisory in review. */ const CONJ = [ [RE('bendecemos|bendicemos|bendimos|bendicimos'), 'bendecimos'], [RE('bendico'), 'bendigo'], [RE('bendecen'), 'bendicen'], [RE('bendicié'), 'bendice'], [RE('bendíalo|bendíelo'), 'bendigámoslo'], [RE('bendiciré'), 'bendeciré'], [RE('benditaremos|bendiciremos'), 'bendeciremos'], [RE('maldiciré'), 'maldeciré'], [RE('pedamos'), 'pidamos'], [RE('ungas'), 'unjas'], [RE('undémonos'), 'úngenos'], [RE('redémonos'), 'redímenos'], [RE('dás'), 'das'] ]; /* Applied to EVERY Spanish variant, before any regional pass. */ function toChurchRegister(text) { let s = String(text == null ? '' : text); if (!s) return s; for (const [re, to] of PRAY.concat(SAFE, CONJ)) s = s.replace(re, (m) => /^[\p{Lu}]/u.test(m) ? to.charAt(0).toUpperCase() + to.slice(1) : to); return s; } function toLatinAmerican(text) { let s = String(text == null ? '' : text); if (!s) return s; /* Verbs first, longest form first, so "estabais" is not shadowed by a shorter overlapping entry. */ const forms = Object.keys(VERBS).sort((a, b) => b.length - a.length); for (const f of forms) s = s.replace(RE(f), (m) => { const to = VERBS[f]; /* Preserve the capital: sentence-initial imperatives are common. */ return /^[\p{Lu}]/u.test(m) ? to.charAt(0).toUpperCase() + to.slice(1) : to; }); /* Then the regular paradigm, for verbs the table does not name. */ for (const [re, to] of SUFFIX) s = s.replace(re, to); for (const [re, to] of GRAMMAR) s = s.replace(re, (m) => /^[\p{Lu}]/u.test(m) ? to.charAt(0).toUpperCase() + to.slice(1) : to); for (const [re, to] of LEXICON) s = s.replace(re, (m) => /^[\p{Lu}]/u.test(m) ? to.charAt(0).toUpperCase() + to.slice(1) : to); s = s.replace(VALE, '$1Bueno,'); return s; } /* * Spain keeps NLLB's words untouched and is distinguished by its VOICE. * Deliberately a no-op rather than an absent function, so the call site reads * symmetrically and the reason lives here rather than in a comment there. */ function toPeninsular(text) { return String(text == null ? '' : text); } return { toLatinAmerican, toPeninsular, toChurchRegister, VERBS, LEXICON, PRAY, CONJ }; }));