aboutsummaryrefslogtreecommitdiff
path: root/test/test_lang_coverage.ml
diff options
context:
space:
mode:
authorLukasz Kasprzak <lukas@labunix.xyz>2026-08-19 15:07:06 +0200
committerLukasz Kasprzak <lukas@labunix.xyz>2026-08-19 15:07:06 +0200
commit92559825f9ad3e0f751d2c2022ffe000f23358ef (patch)
treee1da646a10ca4e18b72db13d7b653c6b714cee17 /test/test_lang_coverage.ml
parent7f263a0ec9a91d1a036cfd22ed38354d06500b1d (diff)
downloadcolitur-92559825f9ad3e0f751d2c2022ffe000f23358ef.tar.gz
colitur-92559825f9ad3e0f751d2c2022ffe000f23358ef.zip
feat(lang): Latin sanctoral names, and English
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.
Diffstat (limited to 'test/test_lang_coverage.ml')
-rw-r--r--test/test_lang_coverage.ml71
1 files changed, 51 insertions, 20 deletions
diff --git a/test/test_lang_coverage.ml b/test/test_lang_coverage.ml
index d72484f..96a3383 100644
--- a/test/test_lang_coverage.ml
+++ b/test/test_lang_coverage.ml
@@ -11,19 +11,17 @@ let la () =
| Ok t -> t
| Error e -> Alcotest.failf "lang/la.ini: %s" e
-(* Every TEMPORAL slug the engine can emit must have a Latin name. THIS IS THE
- TEST THAT WOULD HAVE CAUGHT THE ORIGINAL DEFECT -- a booklet printed
- "ef-septuagesima-sunday-2" because nothing asserted coverage. It must fail
- loudly the moment a new slug appears without a name.
+(* Every slug the engine can emit -- temporal ("^ef-") AND sanctoral (a fixed
+ saint's day) alike -- must have a Latin name. THIS IS THE TEST THAT WOULD
+ HAVE CAUGHT THE ORIGINAL DEFECT -- a booklet printed "ef-septuagesima-
+ sunday-2" because nothing asserted coverage. It must fail loudly the
+ moment a new slug appears without a name.
- RESTRICTED TO "^ef-" SLUGS FOR NOW (Task 3's own scope: la.ini's
- [celebration] table currently carries the temporal half only). Task 4 adds
- the sanctoral names and REMOVES this filter -- see this file's own
- [is_temporal_slug] below, kept as one clearly-named, easy-to-find place to
- change, rather than an inline condition. *)
-let is_temporal_slug slug = String.length slug >= 3 && String.sub slug 0 3 = "ef-"
-
-let test_every_temporal_slug_has_a_latin_name () =
+ Task 3 restricted this to "^ef-" slugs only (la.ini's [celebration] table
+ carried the temporal half alone at the time); Task 4 added the sanctoral
+ half and REMOVED that filter -- every slug is now in scope, with no
+ exceptions. *)
+let test_every_slug_has_a_latin_name () =
let t = la () in
let layer = match Test_support.load_ef_layer () with Ok l -> l | Error e -> Alcotest.failf "%s" e in
let ctx = Test_support.ef_context () in
@@ -36,11 +34,8 @@ let test_every_temporal_slug_has_a_latin_name () =
d.Colitur_kernel.Liturgical_day.observed.Colitur_kernel.Celebration.slug
in
(* A miss returns the key itself, so name = slug means "no entry". *)
- if
- is_temporal_slug slug
- && L.celebration t slug = slug
- && not (List.mem slug !missing)
- then missing := slug :: !missing)
+ if L.celebration t slug = slug && not (List.mem slug !missing) then
+ missing := slug :: !missing)
(Colitur_kernel.Calendar.year ctx layer y)
done;
if !missing <> [] then
@@ -66,8 +61,44 @@ let test_vocabularies_are_complete () =
if L.month t n = string_of_int n then Alcotest.failf "no Latin month for %d" n
done
+(* 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
+ slug -- that is what makes an incomplete translation shippable from its
+ first line. This test proves the CHAIN MECHANISM itself, independent of
+ how complete lang/en.ini happens to be today: a from-scratch table with NO
+ [celebration] entries at all, chained to the real la.ini, must still
+ resolve a real la.ini key -- so the test cannot be defeated simply by
+ en.ini becoming more complete over time. It also sanity-checks the real
+ shipped file: that it parses, declares the right fallback code, and that
+ at least one of its own entries resolves directly (not merely through the
+ chain). *)
+let test_en_falls_back_to_latin () =
+ let en =
+ match L.of_string (read "../lang/en.ini") with
+ | Ok t -> t
+ | Error e -> Alcotest.failf "lang/en.ini: %s" e
+ in
+ Alcotest.(check string) "declares la fallback" "la"
+ (Option.value (L.fallback_code en) ~default:"NONE");
+ (* The real shipped file: at least one of its own entries resolves without
+ needing the chain at all. *)
+ Alcotest.(check bool) "en.ini names ef-epiphany directly" true
+ (L.celebration en "ef-epiphany" <> "ef-epiphany");
+ (* The mechanism, isolated from today's en.ini coverage: an EMPTY table
+ (no [celebration] section) chained to la.ini must still resolve a real
+ la.ini-only key through the fallback. *)
+ let empty =
+ match L.of_string "[meta]\nlang = en\nfallback = la\n" with
+ | Ok t -> t
+ | Error e -> Alcotest.failf "synthetic empty en table: %s" e
+ in
+ let chained = L.with_fallback empty (la ()) in
+ Alcotest.(check bool) "empty table falls back to la.ini for a real slug" true
+ (L.celebration chained "hilary" <> "hilary")
+
let suite =
( "Lang/coverage",
- [ Alcotest.test_case "every temporal slug has a Latin name" `Slow
- test_every_temporal_slug_has_a_latin_name;
- Alcotest.test_case "vocabularies complete" `Quick test_vocabularies_are_complete ] )
+ [ 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 "en.ini falls back to Latin" `Quick test_en_falls_back_to_latin ] )