aboutsummaryrefslogtreecommitdiff
path: root/internal/i18n
diff options
context:
space:
mode:
Diffstat (limited to 'internal/i18n')
-rw-r--r--internal/i18n/golden_test.go19
-rw-r--r--internal/i18n/i18n.go14
-rw-r--r--internal/i18n/lang/en.ini13
-rw-r--r--internal/i18n/lang/pl.ini13
-rw-r--r--internal/i18n/vocab_test.go98
5 files changed, 155 insertions, 2 deletions
diff --git a/internal/i18n/golden_test.go b/internal/i18n/golden_test.go
index 5a29097..d06d63b 100644
--- a/internal/i18n/golden_test.go
+++ b/internal/i18n/golden_test.go
@@ -22,6 +22,15 @@ var enUI = UI{
"drugie_czytanie": "2nd reading",
"aklamacja": "Acclamation",
"ewangelia": "Gospel",
+ "epistola": "Lesson",
+ "evangelium": "Gospel",
+ },
+ Rank: 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",
},
FooterKeys: "tab/⇧tab version ←/→ day d date j/k scroll space/b page g/G top/bottom q quit",
Loading: "loading…",
@@ -110,6 +119,16 @@ var plUI = UI{
"drugie_czytanie": "2. czytanie",
"aklamacja": "Aklamacja",
"ewangelia": "Ewangelia",
+ "epistola": "Lekcja",
+ "evangelium": "Ewangelia",
+ },
+ Rank: 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",
},
FooterKeys: "tab/⇧tab wersja ←/→ dzień d data j/k przewiń spacja/b strona g/G góra/dół q wyjście",
Loading: "ładowanie…",
diff --git a/internal/i18n/i18n.go b/internal/i18n/i18n.go
index fece4a8..6785705 100644
--- a/internal/i18n/i18n.go
+++ b/internal/i18n/i18n.go
@@ -15,14 +15,24 @@ type UI struct {
// version code (wuj, vul, grb, drb).
Version map[string]string
- // PartLabel names each modern-lectionary section's heading label word,
- // keyed by liturgy.Section.PartID (pierwsze_czytanie, psalm,
+ // PartLabel names each lectionary section's heading label word, keyed by
+ // liturgy.Section.PartID -- the modern IDs (pierwsze_czytanie, psalm,
// drugie_czytanie, aklamacja, ewangelia). The pl entries are the exact
// prefixes niedziela.pl's scraped headings carry, used by
// render.LocalizeHeading to recognise and swap the label word while
// keeping the citation untouched.
PartLabel map[string]string
+ // Rank names each liturgical rank, keyed by the string form of
+ // calendar.Rank. Two vocabularies share the map: the Ordinary Form's
+ // ferial/optional/memorial/feast/solemnity and the 1962 form's
+ // class-1..class-4/commemoration. The English values are hand-synced to
+ // agree with internal/cli/liturgy.go's own rankLabel() switch, but the
+ // CLI does not read this map -- it renders rank independently, and the
+ // two are kept in sync by hand. The actual consumers of this map are the
+ // dlectio app's day banner and calendar rows.
+ Rank map[string]string
+
// TUI keybar and status messages. NoReadingsFor and ErrorPrefix each
// carry their own single trailing space (the TUI concatenates a date or
// error string directly onto them, no separator added at the call site).
diff --git a/internal/i18n/lang/en.ini b/internal/i18n/lang/en.ini
index 8444a4d..4abd5d1 100644
--- a/internal/i18n/lang/en.ini
+++ b/internal/i18n/lang/en.ini
@@ -4,9 +4,22 @@ version.vul = Vulgate (Latin)
version.wuj = Wujek (Polish)
part_label.aklamacja = Acclamation
part_label.drugie_czytanie = 2nd reading
+part_label.epistola = Lesson
+part_label.evangelium = Gospel
part_label.ewangelia = Gospel
part_label.pierwsze_czytanie = 1st reading
part_label.psalm = Psalm
+rank.class-1 = I class
+rank.class-2 = II class
+rank.class-3 = III class
+rank.class-4 = IV class
+rank.commemoration = commemoration
+rank.feast = feast
+rank.ferial = feria
+rank.memorial = memorial
+rank.optional = optional memorial
+rank.solemnity = solemnity
+rank.sunday = Sunday
footer_keys = tab/⇧tab version ←/→ day d date j/k scroll space/b page g/G top/bottom q quit
loading = loading…
no_readings_for = "no readings for "
diff --git a/internal/i18n/lang/pl.ini b/internal/i18n/lang/pl.ini
index 305c4c9..4ae4ebf 100644
--- a/internal/i18n/lang/pl.ini
+++ b/internal/i18n/lang/pl.ini
@@ -4,9 +4,22 @@ version.vul = Wulgata (lac.)
version.wuj = Wujek (pol.)
part_label.aklamacja = Aklamacja
part_label.drugie_czytanie = 2. czytanie
+part_label.epistola = Lekcja
+part_label.evangelium = Ewangelia
part_label.ewangelia = Ewangelia
part_label.pierwsze_czytanie = 1. czytanie
part_label.psalm = Psalm
+rank.class-1 = I klasy
+rank.class-2 = II klasy
+rank.class-3 = III klasy
+rank.class-4 = IV klasy
+rank.commemoration = komemoracja
+rank.feast = święto
+rank.ferial = dzień powszedni
+rank.memorial = wspomnienie obowiązkowe
+rank.optional = wspomnienie dowolne
+rank.solemnity = uroczystość
+rank.sunday = niedziela
footer_keys = tab/⇧tab wersja ←/→ dzień d data j/k przewiń spacja/b strona g/G góra/dół q wyjście
loading = ładowanie…
no_readings_for = "brak czytań na "
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)
+ }
+ }
+}