aboutsummaryrefslogtreecommitdiff
path: root/lang
Commit message (Collapse)AuthorAgeFilesLines
* feat(lang): traditions.ini, and its install ruleLukasz Kasprzak2026-08-202-1/+23
| | | | | | | | | | | | | | | | Which book a reference denotes does not vary by language, so it lives in its own file rather than in la.ini beside [weekday]. Six mappings, not four: Osee/Jonas are the same question as 3 Kings in transliteration form. The install rule is added in the same commit deliberately -- lang/ once shipped without one, so the feature worked from the source tree and was broken once installed. bin/dune gains colitur_citation as a linked library, needed for the new loader; lang_list's directory scan now excludes traditions.ini, which is not a language file and does not parse as one.
* feat(render): Roman week numbers and date spans, as dataLukasz Kasprzak2026-08-202-0/+36
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | The ordo booklet's week header repeated the month name on every week even though the heading above already established it -- pure noise. Replace it with a Roman week number plus the span of dates the week covers, e.g. "Hebdomada I (Ian 1-2)", following the project's own rule that a presentation choice is data, not code. lang/{la,en}.ini gain a [month_abbr] section (three-letter month abbreviations); Lang.month_abbr follows Lang.month's exact shape, including the out-of-range and miss-returns-the-key contracts. The coverage test now fails loudly if an abbreviation goes missing, the same as [month] already does. Every week object in the view gains num_roman (Roman numeral, num stays as the arabic original -- Roman is a presentation choice, not an engine change), first_dom/last_dom (the day-of-month of the week's first and last IN-MONTH days, padding excluded), month_abbr (resolved through Lang.month_abbr), and single_day (true when the week holds exactly one in-month day). single_day is a flag, not a preformatted span string: the engine is logic-less and cannot itself decide between "Ian 1" and "Ian 1-2", so a template makes that call from the flag instead -- the same "shape the data, not the template" discipline in_month and last already follow. Weeks are built per month with padding only at the two ends, so a week's in-month days never cross a month boundary -- verified, not assumed: every week always has at least one real day since no month is shorter than a single week. Covered by three new View tests, including a real single-day-week witness (January 2027's own trailing week is a lone Sunday, the 31st).
* fix(naming): the rite prints its display name, not the internal id efLukasz Kasprzak2026-08-202-0/+40
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | The booklet's title page and running header read "Ordo 2027 . ef" -- an internal identifier reaching a reader, the same defect class the sanctoral/temporal slugs were already fixed for. lang/la.ini and lang/en.ini each gain a [rite] section mapping the rite id to a reader-facing name, sourced from the Missal's own title page (docs/research/LT.txt:6 "MISSALE ROMANUM", :15 "EDITIO TYPICA") plus the 1962 dating this project uses throughout (rules-register.md, CLAUDE.md) -- both cited in the ini comments, marked PATTERN since the phrase combines two title-page elements rather than quoting one verbatim heading. Lang.t gains a rite table/lookup (same total, miss-echoes-the-key contract as every other lookup here); View.of_days exposes rite_name alongside the existing rite field, which stays the stable key exactly as slug is kept beside name. Every shipped template that printed {{rite}} now prints {{rite_name}} instead. test_lang_coverage.ml gains a coverage assertion over every rite id the engine can emit -- one today -- so a second rite module (OF) landing without a matching [rite] entry fails loudly instead of printing its own bare id. Goldens regenerated through the Test_view.view_of path test_render_golden.ml itself uses (English with a Latin fallback), not the CLI (whose --lang default is plain Latin and would have pinned output the tests never produce). test/cli.t's own JSON prefix assertion updated to match: rite_name is a real new key in that generic view dump, sitting right after rite.
* fix(install): ship lang/ so installed colitur resolves namesLukasz Kasprzak2026-08-191-0/+17
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | la.ini and en.ini (725 Latin/English liturgical names -- the entire point of the naming-and-config work just merged) had no dune install rule, so make install / dune install never copied them to <prefix>/share/colitur/lang/. bin/main.ml's lang_dir() probes exactly that installed path first, falling back to a build-tree layout that also does not exist for an installed binary -- so every installed user silently got raw slugs (ef-circumcision) and untranslated terms (epistle/gospel) instead of resolved names, with no error at all. The defect existed because nobody had run the installed binary from a directory with no colitur source tree above it: dune exec and dune test always resolve lang/ via the build tree, materialized as a side effect of test/dune's cram deps, so every in-tree check stayed green while the installed artifact was broken. Add lang/dune, following schema/dune's exact pattern: an install stanza placing la.ini and en.ini at <prefix>/share/colitur/lang/, matching where bin/main.ml's lang_dir() already looked. No code change was needed there -- only the missing install rule. Update Makefile's install target help text and summary echo to mention lang alongside ef/templates/schema. Verified end to end: uninstalled, removed lang/dune, rebuilt and reinstalled to reproduce the bug from an outside directory (~/tmp, colitur table showed ef-circumcision/epistle); restored lang/dune, reinstalled, and confirmed the same command now shows the resolved Latin name and rubric terms, that ~/.local/share/colitur/lang/ contains both files, and that colitur emit --format csv shows a real name in the name column. lang/la.ini and lang/en.ini are untouched. Full suite: dune test --force, 495 tests, 0 failures.
* feat(lang): walk commemorations and transfers, name every slug they surfaceLukasz Kasprzak2026-08-192-17/+571
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | test_lang_coverage.ml's own coverage test used to walk only the OBSERVED day of each date (one Celebration.t per Liturgical_day.t). A liturgical day also carries a second stream of slugs -- commemorations (kept when the observed day does not fully displace a losing candidate, RG 108-111) and transfers (an impeded I/II-class feast moved to a later date, RG 96-98) -- and nothing here ever looked at them. The test asserted coverage of what it happened to WALK, not of what the engine can EMIT, so it passed green while the ordo booklet printed raw slugs ("Commemoratio canute-martyr", "Commemoratio maur-abbot", "Commemoratio peter"). test_lang_coverage.ml now walks observed, every entry in commemorations, transferred_in, and every entry in transferred_out. That extension turned up 120 slugs with no Latin name across 2020-2045, now added to lang/la.ini: 112 are data/ef/sanctoral.sexp companions the temporal-only walk never reached; 5 (barbara, commemoration-of-st-peter, commemoration-of-the-seven-sorrows, major-litanies, rogation-wednesday) are data/ef/adjustments.sexp's own hand-authored Add directives; 3 (ef-nativity-octave-day-2/3/4) are temporal days with no calendarium heading to transcribe, built by the same pattern days 5-7 already use. Seven of the sanctoral names are cited to docs/research/scan1.txt rather than LT.txt: the 2006 web-capture transcription silently drops several real commemorations that both photographic scans carry (donatus, romanus, eusebius-confessor, naboris-et-felicis, sts-gervasius-and-protasius, sts-felix-and-adauctus, and praxedis-virginis -- the last for a spurious ligature LT.txt introduces, "Praxedis" confirmed correct against both scans). The same 120 names, extracted verbatim from sanctoral.sexp's and adjustments.sexp's own English fields rather than retyped, are added to lang/en.ini. make check-citations: 400 LT.txt citations checked, 0 wrong, 0 malformed, 0 cannot verify. Teeth proved by deleting canute-martyr's own name (a Commemoration_only slug that can never be the observed day, only ever a commemoration) and confirming the coverage test fails naming exactly that slug, then restoring it.
* docs(lang): clean lang/la.ini against the hardened citation checkerLukasz Kasprzak2026-08-191-51/+93
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Ran the round-2 hardened check_citations.py against lang/la.ini and fixed every WRONG and MALFORMED finding. Baseline before this task: 12 WRONG, 42 CANNOT VERIFY (round-1 tool). After the round-2 tool alone (data unchanged): 9 WRONG, 10 MALFORMED, 1 CANNOT VERIFY -- the rarity rule cleared 41 of the 42 CANNOT VERIFY entries by itself, as expected. After this cleanup: 0 WRONG, 0 MALFORMED, 0 CANNOT VERIFY, 292 citations checked (up from 272 -- several wide ranges became more granular, individually verified citations). What changed, all in comments, no `key = value` entry touched: - Three genuine wrong citations found and corrected: advent's own citation was pointing at christmastide's real heading (LT.txt:8631, "Tempus Nativitatis") 22 lines off from its own (LT.txt:8609) -- christmastide had never had a working citation of its own at all, the right line sitting unused inside advent's corrective note. Restructured so each entry cites its own real line, including giving time-after-epiphany its own citation (LT.txt:8668) for the first time. - Ten MALFORMED wide ranges (introduced by round 1's own tolerance removal, never capped until round 2) replaced with precise per-entry citations -- mostly comma lists of exact bare line numbers, since each TOC section lists one heading per line; two are legitimate multi-line wraps kept as capped explicit ranges (a 2-line Nativity-octave heading split by an unrelated saint's day; Christ the King's own in-body heading split across a page-number line). - Six citation-shaped substrings that were never genuine provenance claims lost their "LT.txt:" prefix (now read "line NNNN"), each with an inline note explaining why: two were corrective prose quoting a historical WRONG value ("previously cited LT.txt:8631/12459, which is..."), three were contextual pointers to a NEARBY but different heading used for explanation, and one discloses an unmodelled alternate wording. None of these ever claimed to be this entry's own heading; writing them as "LT.txt:N" only let the checker mistake documentation for a claim. - Two genuinely correct citations left permanently unable to pass an automated word-overlap check, for reasons orthogonal to correctness (disclosed in check_citations.py's own docstring as an accepted trade-off) also lost their "LT.txt:" prefix, each verified by hand and noted as corroborating rather than primary: class-1..4's "classis" (the only distinctive word in "I classis" etc., 500+ occurrences across LT.txt -- RG 8 is the primary source); Corpus Christi's and Holy Name's own TOC lines, both abbreviated ("Ss.mi"/"Ss.mae") where every entry below spells the same title out in full, and neither has a spelled-out occurrence anywhere else in this partial 2006 web-capture transcription to cite instead (Holy Name also has a stronger primary source already: temporal_ef.ml's own scan-verified string). No rule was weakened to reach zero: every de-prefixed reference was verified by hand against the transcription first, and none of them was ever wrong -- each was either documentation, context, or evidence the checker's own disclosed word-overlap/rarity design cannot confirm. Claude-Session: https://claude.ai/code/session_017ZBxCCRM2ojnBupp3SBxV9
* feat(lang): Latin sanctoral names, and EnglishLukasz Kasprzak2026-08-192-4/+1249
| | | | | | | | | | | | | | | Sanctoral names are transcribed from the Missal's own calendarium and kept in the GENITIVE, as the Missal prints them -- noted in the file so nobody corrects them to the nominative. English reuses the 327 names already in data/ef/sanctoral.sexp rather than retyping them, and declares fallback = la, so an untranslated day in an English booklet shows Latin rather than a slug. The test asserts the FALLBACK works rather than that en.ini is exhaustive: that is what makes a partial translation shippable from its first line. Coverage now demands a name for every slug the engine can emit across 2020-2045, temporal and sanctoral alike.
* fix(lang): correct two wrong citation lines, add check-citationsLukasz Kasprzak2026-08-191-16/+30
| | | | | | | | | | | | | | | | | | | | | | | | | | | | Two of la.ini's LT.txt:<n> citations pointed at the wrong line -- the Latin itself was right, only the pinned line was wrong: - advent cited LT.txt:8631 ("Tempus Nativitatis"); the real "Tempus Adventus" heading is at 8609. - ef-christ-the-king and [rank]'s own citation both pointed near "Dominica ultima Octobris" (12459) when the text they actually quote, "D.NI NOSTRI JESU CHRISTI REGIS" and "I classis", sits two and three lines further down, at 12461 and 12462. ef-christmas-sunday-0 was marked PATTERN but LT.txt:8644 is the identical string verbatim -- relabelled as a direct citation, not constructed. Added tools/check_citations.py and `make check-citations`: for every LT.txt:<n> citation outside a PATTERN block, confirms a +-2-line window around line n actually contains the Latin text the citation claims, rather than trusting each of the 38 citations by hand. Follows check-schema/check-templates' own precedent -- docs/ is gitignored, so the target prints SKIPPED loudly and exits 0 when docs/research/LT.txt is absent, never a silent pass. The checker's own teeth are proven three ways: replayed against the pre-fix file it independently re-derives both corrections above; a fresh mutation (redirecting one citation to an unrelated line) is caught and reverted; the fixed file passes clean, 147 citations checked, 0 wrong.
* feat(lang): Latin temporal names from the MissalLukasz Kasprzak2026-08-191-0/+717
Every entry is transcribed from the 1962 Missal's own propers headings in docs/research/LT.txt and cites where it came from; names constructed by following a neighbouring pattern are marked as such, so a reader can tell transcription from inference. The coverage test is the point of this commit. It walks every day of 2020-2045 and fails naming any slug with no Latin name -- the test that would have caught the original defect, where a printed booklet said ef-septuagesima-sunday-2 because nothing asserted that names exist. The three Triduum names reuse the exact strings temporal_ef.ml already carries, so the engine and the language file cannot disagree.