aboutsummaryrefslogtreecommitdiff
path: root/internal
diff options
context:
space:
mode:
authorLukasz Kasprzak <lukas@labunix.xyz>2026-08-03 23:51:54 +0200
committerLukasz Kasprzak <lukas@labunix.xyz>2026-08-03 23:51:54 +0200
commite3d551ebb8f6ac2bf1a7027991a4222e83309a39 (patch)
tree9b45f9e86febe0d700c72ae5f074dfa062f178c7 /internal
parentf94ceaae997bce2168a5ab9e64a0c3afeafe0cf6 (diff)
downloadlectio-e3d551ebb8f6ac2bf1a7027991a4222e83309a39.tar.gz
lectio-e3d551ebb8f6ac2bf1a7027991a4222e83309a39.zip
readings: 1962 part labels become i18n data; export PartIDs
Diffstat (limited to 'internal')
-rw-r--r--internal/i18n/golden_test.go4
-rw-r--r--internal/i18n/lang/en.ini2
-rw-r--r--internal/i18n/lang/pl.ini2
-rw-r--r--internal/readings/offline.go50
-rw-r--r--internal/readings/partids_test.go45
5 files changed, 90 insertions, 13 deletions
diff --git a/internal/i18n/golden_test.go b/internal/i18n/golden_test.go
index d07d20a..b32a259 100644
--- a/internal/i18n/golden_test.go
+++ b/internal/i18n/golden_test.go
@@ -22,6 +22,8 @@ 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",
@@ -117,6 +119,8 @@ var plUI = UI{
"drugie_czytanie": "2. czytanie",
"aklamacja": "Aklamacja",
"ewangelia": "Ewangelia",
+ "epistola": "Lekcja",
+ "evangelium": "Ewangelia",
},
Rank: map[string]string{
"solemnity": "uroczystość", "feast": "święto",
diff --git a/internal/i18n/lang/en.ini b/internal/i18n/lang/en.ini
index a2b53f3..60a5f32 100644
--- a/internal/i18n/lang/en.ini
+++ b/internal/i18n/lang/en.ini
@@ -4,6 +4,8 @@ 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
diff --git a/internal/i18n/lang/pl.ini b/internal/i18n/lang/pl.ini
index d1817f9..5991938 100644
--- a/internal/i18n/lang/pl.ini
+++ b/internal/i18n/lang/pl.ini
@@ -4,6 +4,8 @@ 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
diff --git a/internal/readings/offline.go b/internal/readings/offline.go
index 59a03fa..c2c276b 100644
--- a/internal/readings/offline.go
+++ b/internal/readings/offline.go
@@ -8,6 +8,7 @@ import (
"github.com/lukaszkasprzak/lectio/internal/caldata"
"github.com/lukaszkasprzak/lectio/internal/calendar"
"github.com/lukaszkasprzak/lectio/internal/config"
+ "github.com/lukaszkasprzak/lectio/internal/i18n"
"github.com/lukaszkasprzak/lectio/internal/liturgy"
"github.com/lukaszkasprzak/lectio/internal/naming"
)
@@ -60,24 +61,47 @@ var ofPart = map[string]struct{ id, heading string }{
"gospel": {"ewangelia", "Ewangelia"},
}
-// efPartHeading gives the traditional (1962) section's heading per UI language;
-// the EF has only an epistle/lesson and a gospel. Unlike the OF headings these
-// are not translated downstream, so they are set in the target language here.
+// efPartHeading gives the traditional (1962) section's ID and heading per UI
+// language; the EF has only an epistle/lesson and a gospel. The label words are
+// i18n data, like the modern ones. Unlike the OF headings these are not
+// translated downstream (render.LocalizeHeading only handles modern IDs), so
+// they are resolved in the target language here.
func efPartHeading(part, lang string) (id, heading string) {
- pl := lang == "pl"
switch part {
case "first":
- if pl {
- return "epistola", "Lekcja"
- }
- return "epistola", "Lesson"
+ id = "epistola"
case "gospel":
- if pl {
- return "evangelium", "Ewangelia"
- }
- return "evangelium", "Gospel"
+ id = "evangelium"
+ default:
+ return "", ""
+ }
+ heading = i18n.Get(lang).PartLabel[id]
+ if heading == "" {
+ heading = id
+ }
+ return id, heading
+}
+
+// ofPartOrder and efPartOrder are the display orders of each lectionary's
+// sections. They are the single source of truth for which part IDs exist.
+var (
+ ofPartOrder = []string{"pierwsze_czytanie", "psalm", "drugie_czytanie", "aklamacja", "ewangelia"}
+ efPartOrder = []string{"epistola", "evangelium"}
+)
+
+// PartIDs returns the part IDs the given lectionary can emit, in display order.
+// lect takes config.Config.Lectionary's values: "new" or "traditional". An
+// unknown lectionary returns nil. Callers that build per-part UI (the dlectio
+// app's reading filters) must derive their list from this rather than
+// hardcoding IDs.
+func PartIDs(lect string) []string {
+ switch lect {
+ case "new":
+ return append([]string(nil), ofPartOrder...)
+ case "traditional":
+ return append([]string(nil), efPartOrder...)
}
- return "", ""
+ return nil
}
// sectionsFor turns computed readings into render-ready sections, tagging each
diff --git a/internal/readings/partids_test.go b/internal/readings/partids_test.go
index 68f5ec0..1ba9373 100644
--- a/internal/readings/partids_test.go
+++ b/internal/readings/partids_test.go
@@ -4,6 +4,7 @@ import (
"testing"
"github.com/lukaszkasprzak/lectio/internal/config"
+ "github.com/lukaszkasprzak/lectio/internal/i18n"
)
// The day header must carry the rank, not just name and colour: the app's
@@ -28,3 +29,47 @@ func TestDayInfoCarriesRank(t *testing.T) {
}
}
}
+
+// PartIDs must list exactly the IDs the engine can emit, in display order.
+// The app derives its "show readings" checkboxes from this; when it hardcoded
+// them instead, seven of the nine 1962 IDs were wrong and the epistle's
+// checkbox did nothing.
+func TestPartIDs(t *testing.T) {
+ wantNew := []string{"pierwsze_czytanie", "psalm", "drugie_czytanie", "aklamacja", "ewangelia"}
+ wantOld := []string{"epistola", "evangelium"}
+ if got := PartIDs("new"); !equalSlice(got, wantNew) {
+ t.Errorf("PartIDs(new) = %v, want %v", got, wantNew)
+ }
+ if got := PartIDs("traditional"); !equalSlice(got, wantOld) {
+ t.Errorf("PartIDs(traditional) = %v, want %v", got, wantOld)
+ }
+ if got := PartIDs("nonsense"); len(got) != 0 {
+ t.Errorf("PartIDs(nonsense) = %v, want empty", got)
+ }
+}
+
+// Every ID PartIDs lists must have a label in every shipped language,
+// otherwise a checkbox would render a raw ID like "epistola".
+func TestEveryPartIDHasLabels(t *testing.T) {
+ for _, lect := range []string{"new", "traditional"} {
+ for _, id := range PartIDs(lect) {
+ for _, lang := range []string{"en", "pl"} {
+ if i18n.Get(lang).PartLabel[id] == "" {
+ t.Errorf("%s/%s: no label for %q", lect, lang, id)
+ }
+ }
+ }
+ }
+}
+
+func equalSlice(a, b []string) bool {
+ if len(a) != len(b) {
+ return false
+ }
+ for i := range a {
+ if a[i] != b[i] {
+ return false
+ }
+ }
+ return true
+}