summaryrefslogtreecommitdiff
path: root/internal/tui
diff options
context:
space:
mode:
authorLukasz Kasprzak <lukas@labunix.xyz>2026-07-23 21:51:40 +0200
committerLukasz Kasprzak <lukas@labunix.xyz>2026-07-23 21:51:40 +0200
commit4c776396115c8120c3e1cb8fda993449fcdcd326 (patch)
tree0144fb325663dde063057a5ec568c59d4cbe79da /internal/tui
parentbfa8df7b36ccbd44703e0705d51a2ed553a23164 (diff)
downloadlectio-4c776396115c8120c3e1cb8fda993449fcdcd326.tar.gz
lectio-4c776396115c8120c3e1cb8fda993449fcdcd326.zip
i18n: ui_language config (default en) for UI chrome across cli/tui/web; version labels localised
Diffstat (limited to 'internal/tui')
-rw-r--r--internal/tui/tui.go22
-rw-r--r--internal/tui/tui_test.go54
2 files changed, 66 insertions, 10 deletions
diff --git a/internal/tui/tui.go b/internal/tui/tui.go
index 1e3b948..bcfb3c1 100644
--- a/internal/tui/tui.go
+++ b/internal/tui/tui.go
@@ -13,6 +13,7 @@ import (
tea "github.com/charmbracelet/bubbletea"
"github.com/lukaszkasprzak/lectio/internal/config"
+ "github.com/lukaszkasprzak/lectio/internal/i18n"
"github.com/lukaszkasprzak/lectio/internal/liturgy"
"github.com/lukaszkasprzak/lectio/internal/readings"
"github.com/lukaszkasprzak/lectio/internal/render"
@@ -42,8 +43,6 @@ type errMsg struct {
err error
}
-const footerKeys = "tab/⇧tab wersja ←/→ dzień j/k przewiń spacja/b strona g/G góra/dół r odśwież q wyjście"
-
// New builds the initial model: cfg.Offline drops "pl" from the version
// list (render.OfflineVersions), the active version starts at
// cfg.DefaultVersion (falling back to the first version if not found, or
@@ -256,7 +255,7 @@ func (m Model) View() string {
}
header := headerStyle.Width(w).Render(m.headerText())
- footer := footerStyle.Width(w).Render(footerKeys)
+ footer := footerStyle.Width(w).Render(i18n.Get(m.cfg.UILanguage).FooterKeys)
bodyLines := m.bodyLines(innerW)
@@ -276,7 +275,7 @@ func (m Model) View() string {
func (m Model) headerText() string {
label := m.version()
if len(m.sections) > 0 {
- if l, _ := render.GatherVersion(m.version(), m.sections[0], m.cfg.Lectionary); l != "" {
+ if l, _ := render.GatherVersion(m.version(), m.sections[0], m.cfg.Lectionary, m.cfg.UILanguage); l != "" {
label = l
}
}
@@ -287,17 +286,19 @@ func (m Model) headerText() string {
// through: a loading/error/empty notice, or each section's heading +
// render.GatherVersion blocks for the active version.
func (m Model) bodyLines(w int) []string {
+ ui := i18n.Get(m.cfg.UILanguage)
+
switch {
case m.err != nil:
return []string{
- errStyle.Render("błąd: " + m.err.Error()),
+ errStyle.Render(ui.ErrorPrefix + m.err.Error()),
"",
- citationStyle.Render("zmień datę (←/→) lub odśwież (r)"),
+ citationStyle.Render(ui.ErrorHint),
}
case m.loading:
- return []string{citationStyle.Render("ładowanie…")}
+ return []string{citationStyle.Render(ui.Loading)}
case len(m.sections) == 0:
- return []string{citationStyle.Render("brak czytań na " + m.date)}
+ return []string{citationStyle.Render(ui.NoReadingsFor + m.date)}
}
ver := m.version()
@@ -306,13 +307,14 @@ func (m Model) bodyLines(w int) []string {
if i > 0 {
lines = append(lines, "")
}
- lines = append(lines, headingStyle.Render(sec.Heading))
+ heading := render.LocalizeHeading(sec.Heading, sec.PartID, m.cfg.UILanguage)
+ lines = append(lines, headingStyle.Render(heading))
if sec.Subtitle != "" {
lines = append(lines, citationStyle.Render(sec.Subtitle))
}
lines = append(lines, "")
- _, blocks := render.GatherVersion(ver, sec, m.cfg.Lectionary)
+ _, blocks := render.GatherVersion(ver, sec, m.cfg.Lectionary, m.cfg.UILanguage)
isPsalm := sec.PartID == "psalm"
for bi, b := range blocks {
refrain := isPsalm && bi == 0
diff --git a/internal/tui/tui_test.go b/internal/tui/tui_test.go
index 2aa7b84..baa5c05 100644
--- a/internal/tui/tui_test.go
+++ b/internal/tui/tui_test.go
@@ -1,9 +1,11 @@
package tui
import (
+ "strings"
"testing"
"github.com/lukaszkasprzak/lectio/internal/config"
+ "github.com/lukaszkasprzak/lectio/internal/liturgy"
)
func TestVersionCycle(t *testing.T) {
@@ -29,3 +31,55 @@ func TestOfflineDropsPL(t *testing.T) {
}
}
}
+
+// TestBodyLinesLocalisesMessages checks that the loading/no-readings/error
+// messages follow cfg.UILanguage.
+func TestBodyLinesLocalisesMessages(t *testing.T) {
+ en := Model{cfg: config.Config{UILanguage: "en"}, loading: true}
+ if lines := en.bodyLines(80); len(lines) == 0 || !strings.Contains(lines[0], "loading") {
+ t.Errorf("en loading bodyLines = %v, want it to contain %q", lines, "loading")
+ }
+
+ pl := Model{cfg: config.Config{UILanguage: "pl"}, loading: true}
+ if lines := pl.bodyLines(80); len(lines) == 0 || !strings.Contains(lines[0], "ładowanie") {
+ t.Errorf("pl loading bodyLines = %v, want it to contain %q", lines, "ładowanie")
+ }
+
+ enEmpty := Model{cfg: config.Config{UILanguage: "en"}, date: "2026-07-22"}
+ if lines := enEmpty.bodyLines(80); len(lines) == 0 || !strings.Contains(lines[0], "no readings for") {
+ t.Errorf("en no-readings bodyLines = %v, want it to contain %q", lines, "no readings for")
+ }
+}
+
+// TestBodyLinesLocalisesHeading checks that a modern-lectionary section
+// heading's label word follows cfg.UILanguage while the citation stays
+// exactly as scraped (render.LocalizeHeading, brief §3b).
+func TestBodyLinesLocalisesHeading(t *testing.T) {
+ sec := liturgy.Section{Heading: "Ewangelia (J 20, 1. 11-18)", PartID: "ewangelia"}
+
+ en := Model{cfg: config.Config{UILanguage: "en", Lectionary: "new"}, sections: []liturgy.Section{sec}}
+ body := strings.Join(en.bodyLines(80), "\n")
+ if !strings.Contains(body, "Gospel (J 20, 1. 11-18)") {
+ t.Errorf("en bodyLines missing localised heading: %q", body)
+ }
+
+ pl := Model{cfg: config.Config{UILanguage: "pl", Lectionary: "new"}, sections: []liturgy.Section{sec}}
+ body = strings.Join(pl.bodyLines(80), "\n")
+ if !strings.Contains(body, "Ewangelia (J 20, 1. 11-18)") {
+ t.Errorf("pl bodyLines missing unchanged heading: %q", body)
+ }
+}
+
+// TestFooterKeysLocalised checks the footer keybar text follows
+// cfg.UILanguage.
+func TestFooterKeysLocalised(t *testing.T) {
+ en := Model{cfg: config.Config{UILanguage: "en"}, date: "2026-07-22"}
+ if out := en.View(); !strings.Contains(out, "q quit") {
+ t.Errorf("en View() footer missing %q: %q", "q quit", out)
+ }
+
+ pl := Model{cfg: config.Config{UILanguage: "pl"}, date: "2026-07-22"}
+ if out := pl.View(); !strings.Contains(out, "q wyjście") {
+ t.Errorf("pl View() footer missing %q: %q", "q wyjście", out)
+ }
+}