aboutsummaryrefslogtreecommitdiff
path: root/internal/config
diff options
context:
space:
mode:
authorLukasz Kasprzak <lukas@labunix.xyz>2026-07-28 18:15:29 +0200
committerLukasz Kasprzak <lukas@labunix.xyz>2026-07-28 18:15:29 +0200
commit539a7c71b60115144959f712ef5966f48c63f9f0 (patch)
tree0f07fe348a3a6c99d5a8713e39dd99640aa6efd9 /internal/config
parent5e1664b8008675177a551aff1de371f54d4e20e4 (diff)
downloadlectio-539a7c71b60115144959f712ef5966f48c63f9f0.tar.gz
lectio-539a7c71b60115144959f712ef5966f48c63f9f0.zip
naming: localise liturgical day names in any language
Add internal/naming, which renders temporal day names and celebration display names from the calendar engine's slugs in any language. English is the built-in baseline; a language is data -- an embedded lang/<code>.ini (pl shipped) and/or a user file at <config dir>/names/<code>.ini that overrides it key by key. Names compose from a small vocabulary plus per-language format templates, so word order and grammatical case can differ (e.g. Polish genitive "3. Niedziela Okresu Zwykłego"); any string a language omits falls back to English. - Move day-name generation out of calendar (calendar.HumanizeSlug removed, calendar stays a pure engine) into naming.DayName; the English golden cases carry over verbatim. - naming.CelebrationName unifies the three duplicated resolvers (cli/readings/calfeed): name.<lang> -> English -> Latin -> humanized slug. Saint names stay in the calendar data (name.<lang>), overridable via calendar layers. - config: ui_language now accepts any code (lower-cased, not clamped to en/pl) so names/<code>.ini applies; UI chrome still resolves en/pl and falls back to English. Add NamesDir(); wire naming.SetUserDir (and the previously unwired bible.SetUserCorporaDir) in the TUI and web mains too, so external corpora and name files work across all three binaries.
Diffstat (limited to 'internal/config')
-rw-r--r--internal/config/config.go36
-rw-r--r--internal/config/config_test.go11
2 files changed, 28 insertions, 19 deletions
diff --git a/internal/config/config.go b/internal/config/config.go
index 299c942..c9a00f2 100644
--- a/internal/config/config.go
+++ b/internal/config/config.go
@@ -37,7 +37,7 @@ const configHeader = `# lectio configuration (INI). Full-line comments only (# o
# width integer; 0 = detect terminal width
# all true | false (all readings, or just the gospel)
# offline true | false (never fetch; cache/sigla only)
-# ui_language en | pl (interface chrome; readings stay source-language)
+# ui_language any code (en, pl, ...) (chrome is en/pl, else English; day/saint names from names/<code>.ini)
# reading_lang language for offline reading text (e.g. en, pl); blank follows ui_language
# reading_version force a specific bible corpus code (e.g. drb, wuj); blank = auto-resolve
# sigla_style auto | polish | english | latin (citation dialect; auto follows ui_language)
@@ -131,21 +131,14 @@ func NormalizeDisplay(display string) string {
return d
}
-// validUILanguages are the two UI chrome languages lectio understands.
-var validUILanguages = map[string]bool{
- "en": true,
- "pl": true,
-}
-
-// NormalizeUILanguage lower-cases lang and falls back to "en" when it is not
-// one of validUILanguages -- the same lenient style as NormalizeDisplay (no
-// error, just a safe default).
+// NormalizeUILanguage lower-cases and trims a ui_language code. Any code is
+// accepted: it selects day- and saint-name localisation (names/<code>.ini, via
+// internal/naming) and, for the UI chrome, resolves through i18n.Get, which
+// falls back to English for anything other than the built-in "en"/"pl". So a
+// user can set ui_language = fr, ship a names/fr.ini, and get French day names
+// with English chrome -- no rebuild.
func NormalizeUILanguage(lang string) string {
- l := strings.ToLower(lang)
- if !validUILanguages[l] {
- return "en"
- }
- return l
+ return strings.ToLower(strings.TrimSpace(lang))
}
// NormalizeSiglaStyle maps a sigla_style setting to one of "auto", "polish",
@@ -354,6 +347,19 @@ func CorporaDir() (string, error) {
return filepath.Join(filepath.Dir(p), "corpora"), nil
}
+// NamesDir is the user directory for drop-in day-name language files
+// (<code>.ini), alongside calendars/ and corpora/ under the lectio config dir.
+// A file here overrides the built-in day names for its language key by key;
+// combined with ui_language = <code>, it localises the daily view to any
+// language without a rebuild. Mirrors CalendarsDir/CorporaDir.
+func NamesDir() (string, error) {
+ p, _, err := configPath()
+ if err != nil {
+ return "", err
+ }
+ return filepath.Join(filepath.Dir(p), "names"), nil
+}
+
// BooksPath returns the path to the optional user books.ini (in the same
// directory as the config file). There is no embedded seed on disk -- absence
// means "use the built-in defaults".
diff --git a/internal/config/config_test.go b/internal/config/config_test.go
index 1035426..dd75808 100644
--- a/internal/config/config_test.go
+++ b/internal/config/config_test.go
@@ -169,18 +169,21 @@ func TestUILanguageLoadsPL(t *testing.T) {
}
}
-func TestUILanguageNormalizesUnknown(t *testing.T) {
+func TestUILanguagePreservesAnyCode(t *testing.T) {
+ // Any ui_language code is kept (lower-cased): it drives day/saint-name
+ // localisation via names/<code>.ini. The UI chrome, resolved through
+ // i18n.Get, still falls back to English for a code it has no table for.
dir := t.TempDir()
t.Setenv("XDG_CONFIG_HOME", dir)
os.MkdirAll(filepath.Join(dir, "lectio"), 0o755)
os.WriteFile(filepath.Join(dir, "lectio", "config.toml"),
- []byte("ui_language = \"bogus\"\n"), 0o644)
+ []byte("ui_language = \"FR\"\n"), 0o644)
cfg, err := Load()
if err != nil {
t.Fatal(err)
}
- if cfg.UILanguage != "en" {
- t.Errorf("UILanguage = %q, want %q (normalized from bogus)", cfg.UILanguage, "en")
+ if cfg.UILanguage != "fr" {
+ t.Errorf("UILanguage = %q, want %q (lower-cased, not clamped)", cfg.UILanguage, "fr")
}
}