aboutsummaryrefslogtreecommitdiff
path: root/internal/i18n/vocab_test.go
diff options
context:
space:
mode:
authorLukasz Kasprzak <lukas@labunix.xyz>2026-08-14 13:22:16 +0200
committerLukasz Kasprzak <lukas@labunix.xyz>2026-08-14 13:22:16 +0200
commit913974b10a993af251b25125d1a417c452ad785c (patch)
tree5dd82811c100de6daa995bebd115a12434296508 /internal/i18n/vocab_test.go
parentd7da4b09f7775276231d0241cfe2700d247728ee (diff)
parent3b32c002d3eddda5ece9422442717657b9fee63b (diff)
downloadlectio-913974b10a993af251b25125d1a417c452ad785c.tar.gz
lectio-913974b10a993af251b25125d1a417c452ad785c.zip
Merge branch 'polish-ui-and-calendar': the gomobile facade and the EF calendar fixes
Two bodies of work that shared a branch. The gomobile facade (2026-08-03..05): mobile.PartLabels, Days, and the observed rank on DayInfo, so dlectio stops hardcoding part IDs and rank strings; the 1962 part labels become i18n data; the documented gomobile bind command is corrected so it reproduces the shipped .aar. The EF calendar fixes (2026-08-12): seven defects found by differencing this engine against colitur, a second 1962 implementation built from the Missal's General Rubrics rather than from this codebase. RG 96 transfers were not skipping II-class days; a II-class privileged feria was not yielding to a feast; Sunday ranks, the two Rose Sundays and Holy Thursday's colour were wrong; and scripts/gen-sanctoral-ef inferred ranks, deduped and tagged classes wrongly, which put 15 III-class feasts into the shipped tridentine-calendar.ini as bare commemorations and dropped four entries outright. Holy Thursday was violet in both engines, which is how a shared lineage hides a defect: this project's ini is generated from missalemeum and colitur's data was bootstrapped from here, so an error inherited by both is invisible to a differential. It took the Missal itself to see it. The EF oracle test now asserts rank and colour, not season alone. One known gap is recorded in the source rather than fixed, as out of scope: RG 95 chained transfers (calendar.go).
Diffstat (limited to 'internal/i18n/vocab_test.go')
-rw-r--r--internal/i18n/vocab_test.go98
1 files changed, 98 insertions, 0 deletions
diff --git a/internal/i18n/vocab_test.go b/internal/i18n/vocab_test.go
new file mode 100644
index 0000000..d0fd603
--- /dev/null
+++ b/internal/i18n/vocab_test.go
@@ -0,0 +1,98 @@
+package i18n
+
+import (
+ "testing"
+
+ "github.com/lukaszkasprzak/lectio/internal/calendar"
+)
+
+// Every rank the calendar can emit must have a word in every shipped
+// language. This is the guard against adding a constant later and silently
+// rendering a raw key like "class-2" in the UI.
+func TestVocabularyCoversEveryConstant(t *testing.T) {
+ ranks := []calendar.Rank{
+ calendar.RankFerial, calendar.RankOptional, calendar.RankMemorial,
+ calendar.RankFeast, calendar.RankSolemnity, calendar.RankSunday,
+ calendar.RankClass1, calendar.RankClass2, calendar.RankClass3,
+ calendar.RankClass4, calendar.RankCommemoration,
+ }
+ for _, lang := range []string{"en", "pl"} {
+ ui := Get(lang)
+ for _, r := range ranks {
+ if ui.Rank[string(r)] == "" {
+ t.Errorf("%s: no rank word for %q", lang, r)
+ }
+ }
+ }
+}
+
+// The English rank words must not change: lectio's CLI has printed these since
+// before the table existed, and English users' output should be untouched.
+func TestEnglishRankWordingUnchanged(t *testing.T) {
+ want := map[string]string{
+ "solemnity": "solemnity", "feast": "feast", "memorial": "memorial",
+ "optional": "optional memorial", "ferial": "feria", "sunday": "Sunday",
+ "class-1": "I class", "class-2": "II class",
+ "class-3": "III class", "class-4": "IV class",
+ "commemoration": "commemoration",
+ }
+ ui := Get("en")
+ for k, v := range want {
+ if got := ui.Rank[k]; got != v {
+ t.Errorf("rank[%q] = %q, want %q", k, got, v)
+ }
+ }
+}
+
+// The Polish rank words must be exactly this spelling, diacritics included:
+// TestVocabularyCoversEveryConstant only checks non-emptiness, so a typo
+// (e.g. "uroczystosc" for "uroczystość", or a wrong diacritic) would pass
+// silently without this pin. Polish correctness is the whole point of this
+// project.
+func TestPolishRankWordingUnchanged(t *testing.T) {
+ want := map[string]string{
+ "solemnity": "uroczystość", "feast": "święto",
+ "memorial": "wspomnienie obowiązkowe", "optional": "wspomnienie dowolne",
+ "ferial": "dzień powszedni", "sunday": "niedziela",
+ "class-1": "I klasy", "class-2": "II klasy",
+ "class-3": "III klasy", "class-4": "IV klasy",
+ "commemoration": "komemoracja",
+ }
+ ui := Get("pl")
+ for k, v := range want {
+ if got := ui.Rank[k]; got != v {
+ t.Errorf("rank[%q] = %q, want %q", k, got, v)
+ }
+ }
+}
+
+// The Polish part labels must be exactly this spelling, diacritics included,
+// and no others. This asserts against plUI directly, NOT i18n.Get("pl"):
+// Get overlays the embedded English baseline first and then the Polish file
+// on top (lang.go's Get), so a label present in English and missing only
+// from plUI.PartLabel would resolve through Get("pl") to the identical
+// English word rather than "" -- invisible to
+// internal/readings/partids_test.go's TestEveryPartIDHasLabels, which only
+// checks Get(lang) for non-emptiness. plUI is the unmerged golden source
+// with no fallback, so a missing entry is genuinely absent there, which is
+// the only way to catch this. The exact key-count check guards against a
+// future addition to plUI.PartLabel slipping in unpinned.
+func TestPolishPartLabelWordingUnchanged(t *testing.T) {
+ want := map[string]string{
+ "pierwsze_czytanie": "1. czytanie",
+ "psalm": "Psalm",
+ "drugie_czytanie": "2. czytanie",
+ "aklamacja": "Aklamacja",
+ "ewangelia": "Ewangelia",
+ "epistola": "Lekcja",
+ "evangelium": "Ewangelia",
+ }
+ if len(plUI.PartLabel) != len(want) {
+ t.Fatalf("plUI.PartLabel has %d keys, want %d: %v", len(plUI.PartLabel), len(want), plUI.PartLabel)
+ }
+ for k, v := range want {
+ if got, ok := plUI.PartLabel[k]; !ok || got != v {
+ t.Errorf("plUI.PartLabel[%q] = %q (present=%v), want %q", k, got, ok, v)
+ }
+ }
+}