diff options
| -rw-r--r-- | lang/en.ini | 10 | ||||
| -rw-r--r-- | lang/la.ini | 30 | ||||
| -rw-r--r-- | lib/naming/lang.ml | 7 | ||||
| -rw-r--r-- | lib/naming/lang.mli | 6 | ||||
| -rw-r--r-- | lib/render/view.ml | 6 | ||||
| -rw-r--r-- | templates/ef/grid.html | 2 | ||||
| -rw-r--r-- | templates/ef/grid.ms | 2 | ||||
| -rw-r--r-- | templates/ef/ordo.adoc | 2 | ||||
| -rw-r--r-- | templates/ef/ordo.html | 2 | ||||
| -rw-r--r-- | templates/ef/ordo.md | 2 | ||||
| -rw-r--r-- | templates/ef/ordo.ms | 2 | ||||
| -rw-r--r-- | templates/ef/ordo.tex | 4 | ||||
| -rw-r--r-- | templates/ef/ordo.typ | 4 | ||||
| -rw-r--r-- | test/cli.t | 4 | ||||
| -rw-r--r-- | test/golden/grid-2027.html | 2 | ||||
| -rw-r--r-- | test/golden/grid-2027.ms | 2 | ||||
| -rw-r--r-- | test/golden/ordo-2027.adoc | 2 | ||||
| -rw-r--r-- | test/golden/ordo-2027.html | 2 | ||||
| -rw-r--r-- | test/golden/ordo-2027.md | 2 | ||||
| -rw-r--r-- | test/golden/ordo-2027.ms | 2 | ||||
| -rw-r--r-- | test/golden/ordo-2027.tex | 4 | ||||
| -rw-r--r-- | test/golden/ordo-2027.typ | 4 | ||||
| -rw-r--r-- | test/test_lang_coverage.ml | 13 | ||||
| -rw-r--r-- | test/test_view.ml | 9 |
24 files changed, 100 insertions, 25 deletions
diff --git a/lang/en.ini b/lang/en.ini index 25084d8..bfd7689 100644 --- a/lang/en.ini +++ b/lang/en.ini @@ -80,6 +80,16 @@ gospel = Gospel commemoration = Commemoration week = Week +[rite] +; See lang/la.ini's own [rite] section for the full sourcing (the Missal's +; own title page, docs/research/LT.txt:6/8/15, plus the 1962 dating this +; project uses throughout). This is that same phrase in English, not a +; second, independent translation decision: "Missale Romanum" -> "Roman +; Missal" and "editio typica" -> "typical edition" are the standard English +; renderings used for exactly this kind of front-matter (both terms of art +; in English-language liturgical publishing, not colitur's own coinage). +ef = Roman Missal, 1962 typical edition + [celebration] ; --- Temporal (394 slugs, 2020-2045 measured; three added Task 5, ; 2026-08-19, following ef-nativity-octave-day-5/6/7's own pattern -- see diff --git a/lang/la.ini b/lang/la.ini index e82650d..9cbb8fe 100644 --- a/lang/la.ini +++ b/lang/la.ini @@ -156,6 +156,36 @@ gospel = Evangelium commemoration = Commemoratio week = Hebdomada +[rite] +; Every rite id the engine can emit needs a reader-facing display name here +; (test_lang_coverage.ml's own "every rite id has a Latin name" case) -- +; the same discipline [celebration]/[season]/[rank]/[colour] already +; enforce, extended to the one new axis Defect 1 found uncovered: `rite` is +; a stable internal key (Temporal_ef.id = "ef"), never meant for a reader, +; exactly like a slug -- but unlike a slug there was no [rite] section at +; all before this one, so nothing degraded gracefully; the booklet printed +; the bare id "ef" outright. +; +; ef -- PATTERN, not a single verbatim heading: constructed from two +; distinct elements of the Missal's OWN title page, docs/research/LT.txt:6 +; ("MISSALE ROMANUM") and LT.txt:15 ("EDITIO TYPICA"), the standard formula +; a Missale Romanum typical edition has carried on its own cover since +; Trent (LT.txt:8, "SS. CONCILII TRIDENTINI RESTITUTUM" -- present +; unabridged in the full title but dropped here for a running header's +; sake, the same "shorter than the source" trade-off already accepted in +; [term]'s "contents = Index" above). The year is not a quote: 1960 is the +; motu proprio's own promulgation date (LT.txt:102-103, "Rubricarum +; instructum diei 23 iulii anno 1960"), but the RESULTING typical edition +; this project treats as its source of truth is dated 1962 throughout +; docs/research/rules-register.md ("the actual 1962 typical edition") and +; this project's own CLAUDE.md ("the 1962 Missale Romanum") -- both +; disclosed here rather than mechanically cited, since neither is an +; LT.txt line. No single phrase in either scan says "1962" against this +; book's own cover (the year is a publication fact, not a title-page +; word), so appending it is a deliberate, disclosed choice for a reader +; who needs to know WHICH typical edition this is, not an invented title. +ef = Missale Romanum, editio typica 1962 + [celebration] ; --------------------------------------------------------------------- ; TEMPORAL slugs only (^ef-). The SANCTORAL half (a fixed saint's day, not diff --git a/lib/naming/lang.ml b/lib/naming/lang.ml index 147a49b..92c8a9a 100644 --- a/lib/naming/lang.ml +++ b/lib/naming/lang.ml @@ -14,6 +14,7 @@ type t = { rank : table; colour : table; term : table; + rite : table; chain : t option; (** consulted when this table misses *) } @@ -32,6 +33,7 @@ let season t k = get t (fun x -> x.season) k let rank t k = get t (fun x -> x.rank) k let colour t k = get t (fun x -> x.colour) k let term t k = get t (fun x -> x.term) k +let rite t k = get t (fun x -> x.rite) k let weekday_key = [| "sunday"; "monday"; "tuesday"; "wednesday"; "thursday"; "friday"; "saturday" |] @@ -58,7 +60,7 @@ let fallback_code t = t.fallback_code let raw = { code = "raw"; fallback_code = None; celebration = empty_table; weekday = empty_table; month = empty_table; season = empty_table; rank = empty_table; colour = empty_table; - term = empty_table; chain = None } + term = empty_table; rite = empty_table; chain = None } let with_fallback t base = { t with chain = Some base } @@ -98,6 +100,7 @@ let of_string text = rank = find "rank"; colour = find "colour"; term = find "term"; + rite = find "rite"; chain = None }) let keys t = @@ -105,5 +108,5 @@ let keys t = List.concat [ qualify "celebration" t.celebration; qualify "weekday" t.weekday; qualify "month" t.month; qualify "season" t.season; qualify "rank" t.rank; - qualify "colour" t.colour; qualify "term" t.term ] + qualify "colour" t.colour; qualify "term" t.term; qualify "rite" t.rite ] |> List.sort compare diff --git a/lib/naming/lang.mli b/lib/naming/lang.mli index 36931d4..4d7f82f 100644 --- a/lib/naming/lang.mli +++ b/lib/naming/lang.mli @@ -49,6 +49,12 @@ val rank : t -> string -> string val colour : t -> string -> string val term : t -> string -> string +(** A rite id's reader-facing display name (e.g. ["ef"] -> + ["Missale Romanum, editio typica 1962"]). A miss returns the id itself, + same TOTAL-lookup contract as every other function here -- the same + degradation an unnamed slug already gets, not a special case. *) +val rite : t -> string -> string + (** [weekday t n], 0 = Sunday. Out-of-range [n] returns [string_of_int n]. *) val weekday : t -> int -> string diff --git a/lib/render/view.ml b/lib/render/view.ml index bbb8c7d..7bd5416 100644 --- a/lib/render/view.ml +++ b/lib/render/view.ml @@ -191,6 +191,12 @@ let of_days ~lang ~vocab ~rite ~year days = in T.Obj [ ("rite", str rite); + (* The reader-facing display name (lang/*.ini's own [rite] section, + Defect 1) -- [rite] itself stays the stable internal key, exactly + as [slug] is kept beside [name] on a day/commemoration. Every + template that used to print the bare id ("ef") now prints this + field instead. *) + ("rite_name", str (Lang.rite lang rite)); ("year", str (string_of_int year)); ("term", term_value lang); ("weekday_headings", weekday_headings lang); diff --git a/templates/ef/grid.html b/templates/ef/grid.html index e313f9d..b2d4a96 100644 --- a/templates/ef/grid.html +++ b/templates/ef/grid.html @@ -35,7 +35,7 @@ .violet{background:#eae} .rose{background:#fde} .black{background:#ddd} @media print{@page{size:landscape}body{margin:0}} </style></head><body> -<h1>Calendarium {{year}} · {{rite}}</h1> +<h1>Calendarium {{year}} · {{rite_name}}</h1> {{#months}} <table> <caption>{{name}}</caption> diff --git a/templates/ef/grid.ms b/templates/ef/grid.ms index 727143b..7ed483a 100644 --- a/templates/ef/grid.ms +++ b/templates/ef/grid.ms @@ -96,7 +96,7 @@ .nr LL 10.9i .ll \n[LL]u .TL -Calendarium {{year}} \(bu {{rite}} +Calendarium {{year}} \(bu {{rite_name}} .ll \n[LL]u .na {{#months}} diff --git a/templates/ef/ordo.adoc b/templates/ef/ordo.adoc index 3146f2e..3c7e69b 100644 --- a/templates/ef/ordo.adoc +++ b/templates/ef/ordo.adoc @@ -12,7 +12,7 @@ // (Ordo, Epistle, Gospel, Commemoration) comes from the view's term // vocabulary rather than being written into this file, so a translated // booklet needs no template edit. -= {{term.ordo}} {{year}} · {{rite}} += {{term.ordo}} {{year}} · {{rite_name}} :toc: {{#months}} diff --git a/templates/ef/ordo.html b/templates/ef/ordo.html index 3353000..c80a2a4 100644 --- a/templates/ef/ordo.html +++ b/templates/ef/ordo.html @@ -20,7 +20,7 @@ .rose{border-left:4px solid #e7a} .black{border-left:4px solid #000} @media print{body{margin:0}} </style></head><body> -<h1>{{term.ordo}} {{year}} · {{rite}}</h1> +<h1>{{term.ordo}} {{year}} · {{rite_name}}</h1> {{#months}}<h2>{{name}}</h2> {{#days}}<div class="day {{colour}}"> <span class="dom">{{dom}}</span>{{name}} diff --git a/templates/ef/ordo.md b/templates/ef/ordo.md index 805bf67..fde5bb2 100644 --- a/templates/ef/ordo.md +++ b/templates/ef/ordo.md @@ -11,7 +11,7 @@ (Ordo, Epistle, Gospel, Commemoration) comes from the view's term vocabulary rather than being written into this file, so a translated booklet needs no template edit. --> -# {{term.ordo}} {{year}} · {{rite}} +# {{term.ordo}} {{year}} · {{rite_name}} {{#months}} ## {{name}} diff --git a/templates/ef/ordo.ms b/templates/ef/ordo.ms index 88dcb6c..d578455 100644 --- a/templates/ef/ordo.ms +++ b/templates/ef/ordo.ms @@ -10,7 +10,7 @@ .\" vocabulary rather than being written into this file, so a translated .\" booklet needs no template edit. .TL -{{term.ordo}} {{year}} \(bu {{rite}} +{{term.ordo}} {{year}} \(bu {{rite_name}} {{#months}} .SH {{name}} diff --git a/templates/ef/ordo.tex b/templates/ef/ordo.tex index 6a298df..4b5bed9 100644 --- a/templates/ef/ordo.tex +++ b/templates/ef/ordo.tex @@ -61,7 +61,7 @@ % alone cannot outline a filled rule. \newcommand{\swatch}[1]{\tikz[baseline=-0.6ex]{\fill[draw=black,line width=0.4pt,fill=#1] (0,0) rectangle (2.4ex,2.4ex);}} \pagestyle{fancy}\fancyhf{} -\fancyhead[C]{\small {{term.ordo}} {{year}} \textperiodcentered\ {{rite}}} +\fancyhead[C]{\small {{term.ordo}} {{year}} \textperiodcentered\ {{rite_name}}} \fancyfoot[C]{\small\thepage} \renewcommand{\headrulewidth}{0.4pt} \setlength{\parindent}{0pt} @@ -69,7 +69,7 @@ \begin{center} \Large\bfseries {{term.ordo}} {{year}}\\[2pt] -\normalsize\mdseries {{rite}} +\normalsize\mdseries {{rite_name}} \end{center} \vspace{4mm} {\bfseries {{term.contents}}}\par\vspace{2mm} diff --git a/templates/ef/ordo.typ b/templates/ef/ordo.typ index 33bc802..162a485 100644 --- a/templates/ef/ordo.typ +++ b/templates/ef/ordo.typ @@ -61,7 +61,7 @@ paper: "a5", margin: (inside: 14mm, outside: 10mm, top: 12mm, bottom: 12mm), numbering: "1", - header: align(center)[#text(size: 8pt)[{{term.ordo}} {{year}} #sym.dot.c {{rite}}]], + header: align(center)[#text(size: 8pt)[{{term.ordo}} {{year}} #sym.dot.c {{rite_name}}]], ) #set text(size: 9pt) #set par(justify: false) @@ -82,7 +82,7 @@ #align(center)[ #text(size: 18pt, weight: "bold")[{{term.ordo}} {{year}}] \ - {{rite}} + {{rite_name}} ] #v(4mm) #text(weight: "bold")[{{term.contents}}] @@ -427,8 +427,8 @@ CSV emits a header and one row per day: JSON is one object, ICS one VCALENDAR: - $ colitur emit --format json --from 2027 --to 2027 | cut -c1-20 - {"rite":"ef","year": + $ colitur emit --format json --from 2027 --to 2027 | cut -c1-75 + {"rite":"ef","rite_name":"Missale Romanum, editio typica 1962","year":"2027 $ colitur emit --format ics --from 2027 --to 2027 | head -1 | cat -A | head -1 BEGIN:VCALENDAR^M$ diff --git a/test/golden/grid-2027.html b/test/golden/grid-2027.html index 2a85eca..f69b8f3 100644 --- a/test/golden/grid-2027.html +++ b/test/golden/grid-2027.html @@ -35,7 +35,7 @@ .violet{background:#eae} .rose{background:#fde} .black{background:#ddd} @media print{@page{size:landscape}body{margin:0}} </style></head><body> -<h1>Calendarium 2027 · ef</h1> +<h1>Calendarium 2027 · Roman Missal, 1962 typical edition</h1> <table> <caption>January</caption> diff --git a/test/golden/grid-2027.ms b/test/golden/grid-2027.ms index 98e9594..b7539ed 100644 --- a/test/golden/grid-2027.ms +++ b/test/golden/grid-2027.ms @@ -96,7 +96,7 @@ .nr LL 10.9i .ll \n[LL]u .TL -Calendarium 2027 \(bu ef +Calendarium 2027 \(bu Roman Missal, 1962 typical edition .ll \n[LL]u .na diff --git a/test/golden/ordo-2027.adoc b/test/golden/ordo-2027.adoc index f3d33cb..7eae94c 100644 --- a/test/golden/ordo-2027.adoc +++ b/test/golden/ordo-2027.adoc @@ -12,7 +12,7 @@ // (Ordo, Epistle, Gospel, Commemoration) comes from the view's term // vocabulary rather than being written into this file, so a translated // booklet needs no template edit. -= Ordo 2027 · ef += Ordo 2027 · Roman Missal, 1962 typical edition :toc: diff --git a/test/golden/ordo-2027.html b/test/golden/ordo-2027.html index 96ec943..ce7aa26 100644 --- a/test/golden/ordo-2027.html +++ b/test/golden/ordo-2027.html @@ -20,7 +20,7 @@ .rose{border-left:4px solid #e7a} .black{border-left:4px solid #000} @media print{body{margin:0}} </style></head><body> -<h1>Ordo 2027 · ef</h1> +<h1>Ordo 2027 · Roman Missal, 1962 typical edition</h1> <h2>January</h2> <div class="day white"> <span class="dom">1</span>The Octave Day of the Nativity diff --git a/test/golden/ordo-2027.md b/test/golden/ordo-2027.md index 4742dc2..ac3419f 100644 --- a/test/golden/ordo-2027.md +++ b/test/golden/ordo-2027.md @@ -11,7 +11,7 @@ (Ordo, Epistle, Gospel, Commemoration) comes from the view's term vocabulary rather than being written into this file, so a translated booklet needs no template edit. --> -# Ordo 2027 · ef +# Ordo 2027 · Roman Missal, 1962 typical edition ## January diff --git a/test/golden/ordo-2027.ms b/test/golden/ordo-2027.ms index 9e869dd..4594e43 100644 --- a/test/golden/ordo-2027.ms +++ b/test/golden/ordo-2027.ms @@ -10,7 +10,7 @@ .\" vocabulary rather than being written into this file, so a translated .\" booklet needs no template edit. .TL -Ordo 2027 \(bu ef +Ordo 2027 \(bu Roman Missal, 1962 typical edition .SH January diff --git a/test/golden/ordo-2027.tex b/test/golden/ordo-2027.tex index c447f99..21b711e 100644 --- a/test/golden/ordo-2027.tex +++ b/test/golden/ordo-2027.tex @@ -61,7 +61,7 @@ % alone cannot outline a filled rule. \newcommand{\swatch}[1]{\tikz[baseline=-0.6ex]{\fill[draw=black,line width=0.4pt,fill=#1] (0,0) rectangle (2.4ex,2.4ex);}} \pagestyle{fancy}\fancyhf{} -\fancyhead[C]{\small Ordo 2027 \textperiodcentered\ ef} +\fancyhead[C]{\small Ordo 2027 \textperiodcentered\ Roman Missal, 1962 typical edition} \fancyfoot[C]{\small\thepage} \renewcommand{\headrulewidth}{0.4pt} \setlength{\parindent}{0pt} @@ -69,7 +69,7 @@ \begin{center} \Large\bfseries Ordo 2027\\[2pt] -\normalsize\mdseries ef +\normalsize\mdseries Roman Missal, 1962 typical edition \end{center} \vspace{4mm} {\bfseries Contents}\par\vspace{2mm} diff --git a/test/golden/ordo-2027.typ b/test/golden/ordo-2027.typ index 8abad25..2f3cf92 100644 --- a/test/golden/ordo-2027.typ +++ b/test/golden/ordo-2027.typ @@ -61,7 +61,7 @@ paper: "a5", margin: (inside: 14mm, outside: 10mm, top: 12mm, bottom: 12mm), numbering: "1", - header: align(center)[#text(size: 8pt)[Ordo 2027 #sym.dot.c ef]], + header: align(center)[#text(size: 8pt)[Ordo 2027 #sym.dot.c Roman Missal, 1962 typical edition]], ) #set text(size: 9pt) #set par(justify: false) @@ -82,7 +82,7 @@ #align(center)[ #text(size: 18pt, weight: "bold")[Ordo 2027] \ - ef + Roman Missal, 1962 typical edition ] #v(4mm) #text(weight: "bold")[Contents] diff --git a/test/test_lang_coverage.ml b/test/test_lang_coverage.ml index 34758b2..9ed633c 100644 --- a/test/test_lang_coverage.ml +++ b/test/test_lang_coverage.ml @@ -80,6 +80,18 @@ let test_vocabularies_are_complete () = if L.month t n = string_of_int n then Alcotest.failf "no Latin month for %d" n done +(* Defect 1: the booklet used to print the bare rite id ("ef") because no + [rite] section existed in either language file. Walks every rite id the + engine can actually emit -- one today (Rite_ef.Temporal_ef.id, the same + id `Rite_ef.context` stamps onto every Rite.t.id -- see rite_ef.ml) -- so + this is cheap now and fails loudly the moment a second rite module (OF) + is wired in without a matching [rite] entry in la.ini. *) +let test_every_rite_has_a_latin_name () = + let t = la () in + List.iter + (fun id -> if L.rite t id = id then Alcotest.failf "no Latin display name for rite %S" id) + [ Rite_ef.Temporal_ef.id ] + (* lang/en.ini is DELIBERATELY partial (see its own header note): it declares [meta] fallback = la, so a slug it does not carry itself should still resolve through the chain to la.ini's name rather than degrade to the bare @@ -120,4 +132,5 @@ let suite = ( "Lang/coverage", [ Alcotest.test_case "every slug has a Latin name" `Slow test_every_slug_has_a_latin_name; Alcotest.test_case "vocabularies complete" `Quick test_vocabularies_are_complete; + Alcotest.test_case "every rite has a Latin name" `Quick test_every_rite_has_a_latin_name; Alcotest.test_case "en.ini falls back to Latin" `Quick test_en_falls_back_to_latin ] ) diff --git a/test/test_view.ml b/test/test_view.ml index b49b090..e8de6a0 100644 --- a/test/test_view.ml +++ b/test/test_view.ml @@ -66,6 +66,11 @@ let as_bool = function T.Bool b -> b | _ -> Alcotest.fail "expected a bool" let test_year_shape () = let v = view_of 2027 in Alcotest.(check string) "rite" "ef" (as_str (get [ "rite" ] v)); + (* Defect 1: [rite] stays the stable key ("ef"); [rite_name] is the + reader-facing display name a template prints instead. en.ini's own + [rite] section names it directly. *) + Alcotest.(check string) "rite_name" "Roman Missal, 1962 typical edition" + (as_str (get [ "rite_name" ] v)); Alcotest.(check string) "year" "2027" (as_str (get [ "year" ] v)); Alcotest.(check int) "twelve months" 12 (List.length (as_list (get [ "months" ] v))); Alcotest.(check int) "365 days" 365 (List.length (as_list (get [ "days" ] v))) @@ -193,7 +198,9 @@ let test_vocabularies_localise () = let d1 = List.hd (as_list (get [ "days" ] v)) in Alcotest.(check string) "weekday" "Feria VI" (as_str (get [ "weekday" ] d1)); Alcotest.(check string) "rank" "I classis" (as_str (get [ "rank_name" ] d1)); - Alcotest.(check string) "colour" "albus" (as_str (get [ "colour_name" ] d1)) + Alcotest.(check string) "colour" "albus" (as_str (get [ "colour_name" ] d1)); + Alcotest.(check string) "rite_name" "Missale Romanum, editio typica 1962" + (as_str (get [ "rite_name" ] v)) let suite = ( "View", |
