diff --git a/install.sh b/install.sh
index e1d8a2f..3780bc3 100755
--- a/install.sh
+++ b/install.sh
@@ -244,6 +244,9 @@ smtp:
imap:
host: "${IMAP_HOST}"
port: ${IMAP_PORT}
+locale:
+ language: "en"
+ timezone: "UTC"
session:
secret: "${SESSION_KEY}"
expiry_minutes: 60
diff --git a/src/core/admin/templates/global.templ b/src/core/admin/templates/global.templ
index 6e82842..b3143a3 100644
--- a/src/core/admin/templates/global.templ
+++ b/src/core/admin/templates/global.templ
@@ -1,6 +1,6 @@
package templates
-templ GlobalSettings(smtpHost, smtpPort, smtpUser, smtpPass, imapHost, imapPort, nextwksURL, authURL, msg string) {
+templ GlobalSettings(smtpHost, smtpPort, smtpUser, smtpPass, imapHost, imapPort, nextwksURL, authURL, lang, tz, msg string) {
@Layout("global") {
Global Settings
if msg != "" {
@@ -55,6 +55,29 @@ templ GlobalSettings(smtpHost, smtpPort, smtpUser, smtpPass, imapHost, imapPort,
+
+
}
diff --git a/src/core/admin/templates/global_templ.go b/src/core/admin/templates/global_templ.go
index 0c676bc..8258867 100644
--- a/src/core/admin/templates/global_templ.go
+++ b/src/core/admin/templates/global_templ.go
@@ -8,7 +8,7 @@ package templates
import "github.com/a-h/templ"
import templruntime "github.com/a-h/templ/runtime"
-func GlobalSettings(smtpHost, smtpPort, smtpUser, smtpPass, imapHost, imapPort, nextwksURL, authURL, msg string) templ.Component {
+func GlobalSettings(smtpHost, smtpPort, smtpUser, smtpPass, imapHost, imapPort, nextwksURL, authURL, lang, tz, msg string) templ.Component {
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
@@ -168,7 +168,77 @@ func GlobalSettings(smtpHost, smtpPort, smtpUser, smtpPass, imapHost, imapPort,
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 12, "\">")
+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 12, "\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
diff --git a/src/core/admin/ui.go b/src/core/admin/ui.go
index 20104bc..2f08a99 100644
--- a/src/core/admin/ui.go
+++ b/src/core/admin/ui.go
@@ -48,7 +48,8 @@ func (h *Handler) adminGlobal(w http.ResponseWriter, r *http.Request) {
cfg := readConfigRaw(h.configPath)
component := templates.GlobalSettings(
cfg["smtp_host"], cfg["smtp_port"], cfg["smtp_user"], cfg["smtp_pass"],
- cfg["imap_host"], cfg["imap_port"], cfg["nextwks_url"], cfg["auth_url"], "",
+ cfg["imap_host"], cfg["imap_port"], cfg["nextwks_url"], cfg["auth_url"],
+ cfg["lang"], cfg["tz"], "",
)
component.Render(r.Context(), w)
}
@@ -61,7 +62,8 @@ func (h *Handler) adminGlobalSave(w http.ResponseWriter, r *http.Request) {
cfg := readConfigRaw(h.configPath)
component := templates.GlobalSettings(
cfg["smtp_host"], cfg["smtp_port"], cfg["smtp_user"], cfg["smtp_pass"],
- cfg["imap_host"], cfg["imap_port"], cfg["nextwks_url"], cfg["auth_url"], msg,
+ cfg["imap_host"], cfg["imap_port"], cfg["nextwks_url"], cfg["auth_url"],
+ cfg["lang"], cfg["tz"], msg,
)
component.Render(r.Context(), w)
}
@@ -88,6 +90,8 @@ func readConfigRaw(path string) rawConfig {
cfg["nextwks_url"] = trimSuffix(cfg["nextwks_url"], "/auth/callback")
}
cfg["auth_url"] = getNested(m, "oidc", "issuer_url")
+ cfg["lang"] = getNested(m, "locale", "language")
+ cfg["tz"] = getNested(m, "locale", "timezone")
return cfg
}
@@ -105,6 +109,8 @@ func writeConfigRaw(path string, r *http.Request) string {
setNested(m, r.FormValue("smtp_pass"), "smtp", "password")
setNested(m, r.FormValue("imap_host"), "imap", "host")
setNested(m, r.FormValue("imap_port"), "imap", "port")
+ setNested(m, r.FormValue("lang"), "locale", "language")
+ setNested(m, r.FormValue("tz"), "locale", "timezone")
nextwks := r.FormValue("nextwks_url")
if nextwks != "" {
setNested(m, nextwks+"/auth/callback", "oidc", "redirect_url")
diff --git a/src/core/config/config.go b/src/core/config/config.go
index ecdff42..08cda95 100644
--- a/src/core/config/config.go
+++ b/src/core/config/config.go
@@ -16,6 +16,7 @@ type Config struct {
OIDC OIDCConfig `yaml:"oidc"`
SMTP SMTPConfig `yaml:"smtp"`
IMAP IMAPConfig `yaml:"imap"`
+ Locale LocaleConfig `yaml:"locale"`
Session SessionConfig `yaml:"session"`
}
@@ -61,6 +62,11 @@ type IMAPConfig struct {
Port int `yaml:"port"`
}
+type LocaleConfig struct {
+ Language string `yaml:"language"`
+ Timezone string `yaml:"timezone"`
+}
+
type SessionConfig struct {
Secret string `yaml:"secret"`
ExpiryMinutes int `yaml:"expiry_minutes"`
diff --git a/src/core/ui/handler.go b/src/core/ui/handler.go
index 8f447af..04682e8 100644
--- a/src/core/ui/handler.go
+++ b/src/core/ui/handler.go
@@ -17,11 +17,12 @@ type PageCtx struct {
}
type Handler struct {
- appDir string
+ appDir string
+ defaultLang string
}
-func NewHandler(appDir string) *Handler {
- return &Handler{appDir: appDir}
+func NewHandler(appDir string, defaultLang string) *Handler {
+ return &Handler{appDir: appDir, defaultLang: defaultLang}
}
func (h *Handler) RegisterRoutes(mux *http.ServeMux, authGate func(http.Handler) http.Handler) {
@@ -36,21 +37,24 @@ func (h *Handler) launcherPage(w http.ResponseWriter, r *http.Request) {
return
}
- ctx := getContext(r)
+ ctx := h.getContext(r)
apps := DefaultApps(ctx.Role)
component := LauncherPage(ctx, apps)
component.Render(r.Context(), w)
}
-func getContext(r *http.Request) PageCtx {
+func (h *Handler) getContext(r *http.Request) PageCtx {
userID, _ := auth.GetUserID(r)
role, _ := r.Context().Value(auth.ContextRole).(string)
if role == "" {
role = "user"
}
- // Detect language: cookie > header > default
- lang := "en"
+ // Detect language: cookie > header > config default
+ lang := h.defaultLang
+ if lang == "" {
+ lang = "en"
+ }
if cookie, err := r.Cookie("lang"); err == nil {
lang = cookie.Value
} else if al := r.Header.Get("Accept-Language"); al != "" {
diff --git a/src/main.go b/src/main.go
index 2fa7466..6156ac3 100644
--- a/src/main.go
+++ b/src/main.go
@@ -98,7 +98,7 @@ func main() {
if appDir == "." {
appDir = "./"
}
- uiHandler := ui.NewHandler(appDir)
+ uiHandler := ui.NewHandler(appDir, cfg.Locale.Language)
// Setup HTTP router
mux := http.NewServeMux()