From e2e56ac5af290b60ea01037e58e8bc00545c021c Mon Sep 17 00:00:00 2001 From: Lukasz Kasprzak Date: Thu, 20 Aug 2026 11:32:24 +0200 Subject: feat(render): Roman week numbers and date spans, as data 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). --- lib/naming/lang.ml | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) (limited to 'lib/naming/lang.ml') diff --git a/lib/naming/lang.ml b/lib/naming/lang.ml index 92c8a9a..2301513 100644 --- a/lib/naming/lang.ml +++ b/lib/naming/lang.ml @@ -10,6 +10,7 @@ type t = { celebration : table; weekday : table; month : table; + month_abbr : table; season : table; rank : table; colour : table; @@ -54,13 +55,17 @@ let month t n = if n < 1 || n > 12 then string_of_int n else match lookup t (fun x -> x.month) (string_of_int n) with Some v -> v | None -> string_of_int n +let month_abbr t n = + if n < 1 || n > 12 then string_of_int n + else match lookup t (fun x -> x.month_abbr) (string_of_int n) with Some v -> v | None -> string_of_int n + let code t = t.code 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; rite = empty_table; chain = None } + month = empty_table; month_abbr = empty_table; season = empty_table; rank = empty_table; + colour = empty_table; term = empty_table; rite = empty_table; chain = None } let with_fallback t base = { t with chain = Some base } @@ -96,6 +101,7 @@ let of_string text = celebration = find "celebration"; weekday = find "weekday"; month = find "month"; + month_abbr = find "month_abbr"; season = find "season"; rank = find "rank"; colour = find "colour"; @@ -107,6 +113,6 @@ let keys t = let qualify prefix m = SM.bindings m |> List.map (fun (k, v) -> (prefix ^ "." ^ k, v)) in 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 "rite" t.rite ] + qualify "month" t.month; qualify "month_abbr" t.month_abbr; qualify "season" t.season; + qualify "rank" t.rank; qualify "colour" t.colour; qualify "term" t.term; qualify "rite" t.rite ] |> List.sort compare -- cgit v1.3