From 9758b60a59b724de0b8214daee63daf8a3f9a2fb Mon Sep 17 00:00:00 2001 From: Evan Goode Date: Sun, 13 Jul 2025 22:12:11 -0400 Subject: [PATCH] fix tests --- common.go | 18 +++++++++--------- front.go | 32 ++++++++++++++++++-------------- main.go | 22 ++++++++++++++-------- model.go | 15 +++++++++++---- 4 files changed, 52 insertions(+), 35 deletions(-) diff --git a/common.go b/common.go index 446888d..d10c081 100644 --- a/common.go +++ b/common.go @@ -79,18 +79,15 @@ type OIDCProvider struct { } type UserError struct { - Code mo.Option[int] - Message string - MessagePlural mo.Option[string] - N mo.Option[int] - Params []interface{} + Code mo.Option[int] + Message string + Plural mo.Option[Plural] + Params []interface{} } func (e *UserError) Error() string { - if n, ok := e.N.Get(); ok { - if plural, ok := e.MessagePlural.Get(); ok && n > 1 { - return fmt.Sprintf(plural, e.Params...) - } + if plural, ok := e.Plural.Get(); ok && plural.N > 1 { + return fmt.Sprintf(plural.Message, e.Params...) } return fmt.Sprintf(e.Message, e.Params...) } @@ -107,6 +104,9 @@ func (e *UserError) TranslatedError(l *gotext.Locale) string { } } + if plural, ok := e.Plural.Get(); ok { + return l.GetN(e.Message, plural.Message, plural.N, translatedParams...) + } return l.Get(e.Message, translatedParams...) } diff --git a/front.go b/front.go index b1d732e..8f5011a 100644 --- a/front.go +++ b/front.go @@ -194,7 +194,7 @@ type baseContext struct { } func (app *App) NewBaseContext(c *echo.Context) baseContext { - l := getLocale(c) + l := app.getLocale(c) T := l.Get TN := l.GetN return baseContext{ @@ -209,8 +209,12 @@ func (app *App) NewBaseContext(c *echo.Context) baseContext { } } -func getLocale(c *echo.Context) *gotext.Locale { - return (*c).Get(CONTEXT_KEY_LOCALE).(*gotext.Locale) +func (app *App) getLocale(c *echo.Context) *gotext.Locale { + if l := (*c).Get(CONTEXT_KEY_LOCALE); l != nil { + return (*c).Get(CONTEXT_KEY_LOCALE).(*gotext.Locale) + } else { + return app.DefaultLocale + } } type errorContext struct { @@ -222,7 +226,7 @@ type errorContext struct { // Set error message and redirect func (app *App) HandleWebError(err error, c *echo.Context) error { - l := getLocale(c) + l := app.getLocale(c) var webError *WebError var userError *UserError @@ -608,7 +612,7 @@ func FrontCompleteRegistration(app *App) func(c echo.Context) error { func (app *App) FrontOIDCUnlink() func(c echo.Context) error { return withBrowserAuthentication(app, true, func(c echo.Context, user *User) error { - l := getLocale(&c) + l := app.getLocale(&c) returnURL := getReturnURL(app, &c) targetUUID := c.FormValue("userUuid") @@ -644,7 +648,7 @@ func makeOIDCAuthURL(c *echo.Context, provider *OIDCProvider, stateBase64 string } func (app *App) oidcLink(c echo.Context, oidcProvider *OIDCProvider, tokens *oidc.Tokens[*oidc.IDTokenClaims], state oidcState, user *User) error { - l := getLocale(&c) + l := app.getLocale(&c) returnURL := state.ReturnURL @@ -871,7 +875,7 @@ func FrontDeleteInvite(app *App) func(c echo.Context) error { // POST /web/admin/update-users func FrontUpdateUsers(app *App) func(c echo.Context) error { return withBrowserAdmin(app, func(c echo.Context, user *User) error { - l := getLocale(&c) + l := app.getLocale(&c) returnURL := getReturnURL(app, &c) @@ -1142,7 +1146,7 @@ func getFormValue(c *echo.Context, key string) mo.Option[string] { // POST /update-user func FrontUpdateUser(app *App) func(c echo.Context) error { return withBrowserAuthentication(app, true, func(c echo.Context, user *User) error { - l := getLocale(&c) + l := app.getLocale(&c) returnURL := getReturnURL(app, &c) targetUUID := nilIfEmpty(c.FormValue("uuid")) @@ -1209,7 +1213,7 @@ func FrontUpdateUser(app *App) func(c echo.Context) error { // POST /web/update-player func FrontUpdatePlayer(app *App) func(c echo.Context) error { return withBrowserAuthentication(app, true, func(c echo.Context, user *User) error { - l := getLocale(&c) + l := app.getLocale(&c) returnURL := getReturnURL(app, &c) playerUUID := c.FormValue("uuid") @@ -1413,7 +1417,7 @@ func frontChallenge(app *App, action string) func(c echo.Context) error { // POST /web/create-player func FrontCreatePlayer(app *App) func(c echo.Context) error { return withBrowserAuthentication(app, true, func(c echo.Context, caller *User) error { - l := getLocale(&c) + l := app.getLocale(&c) userUUID := c.FormValue("userUuid") @@ -1460,7 +1464,7 @@ func FrontCreatePlayer(app *App) func(c echo.Context) error { func FrontRegister(app *App) func(c echo.Context) error { returnURL := Unwrap(url.JoinPath(app.FrontEndURL, "web/user")) return func(c echo.Context) error { - l := getLocale(&c) + l := app.getLocale(&c) useIDToken := c.FormValue("useIdToken") == "on" honeypot := c.FormValue("email") @@ -1595,7 +1599,7 @@ func addDestination(url_ string, destination string) (string, error) { // POST /web/oidc-migrate func (app *App) FrontOIDCMigrate() func(c echo.Context) error { return func(c echo.Context) error { - l := getLocale(&c) + l := app.getLocale(&c) failureURL := getReturnURL(app, &c) username := c.FormValue("username") @@ -1695,7 +1699,7 @@ func FrontLogin(app *App) func(c echo.Context) error { // POST /web/delete-user func FrontDeleteUser(app *App) func(c echo.Context) error { return withBrowserAuthentication(app, true, func(c echo.Context, user *User) error { - l := getLocale(&c) + l := app.getLocale(&c) returnURL := getReturnURL(app, &c) var targetUser *User @@ -1733,7 +1737,7 @@ func FrontDeleteUser(app *App) func(c echo.Context) error { // POST /web/delete-player func FrontDeletePlayer(app *App) func(c echo.Context) error { return withBrowserAuthentication(app, true, func(c echo.Context, user *User) error { - l := getLocale(&c) + l := app.getLocale(&c) returnURL := getReturnURL(app, &c) playerUUID := c.FormValue("uuid") diff --git a/main.go b/main.go index 1b81fea..9efc258 100644 --- a/main.go +++ b/main.go @@ -75,6 +75,7 @@ type App struct { OIDCProvidersByIssuer map[string]*OIDCProvider FallbackAPIServers []FallbackAPIServer Locales map[language.Tag]*gotext.Locale + DefaultLocale *gotext.Locale LocaleTags []language.Tag } @@ -195,17 +196,16 @@ func (app *App) MakeServer() *echo.Echo { })) } + e.Use(app.GetLanguageMiddleware()) + // Front if app.Config.EnableWebFrontEnd { t := NewTemplate(app) e.Renderer = t frontUser := FrontUser(app) - getLanguage := app.GetLanguageMiddleware() - - e.GET("/", FrontRoot(app), getLanguage) + e.GET("/", FrontRoot(app)) g := e.Group("/web") - g.Use(getLanguage) g.GET("/admin", FrontAdmin(app)) g.GET("/complete-registration", FrontCompleteRegistration(app)) g.GET("/create-player-challenge", FrontCreatePlayerChallenge(app)) @@ -438,18 +438,23 @@ func setup(config *Config) *App { // Locales locales := map[language.Tag]*gotext.Locale{} localeTags := make([]language.Tag, 0) - locales_path := path.Join(config.DataDirectory, "locales") - lang_paths, err := filepath.Glob(path.Join(locales_path, "*")) - for _, lang_path := range lang_paths { + localesPath := path.Join(config.DataDirectory, "locales") + langPaths, err := filepath.Glob(path.Join(localesPath, "*")) + defaultLang := "en-US" // TODO config option? + var defaultLocale *gotext.Locale + for _, lang_path := range langPaths { lang := filepath.Base(lang_path) tag, err := language.Parse(lang) if err != nil { log.Fatalf("Unrecognized language tag: %s", lang) } - l := gotext.NewLocale(locales_path, lang) + l := gotext.NewLocale(localesPath, lang) l.AddDomain("default") localeTags = append(localeTags, tag) locales[tag] = l + if lang == defaultLang { + defaultLocale = l + } } // Crypto @@ -603,6 +608,7 @@ func setup(config *Config) *App { OIDCProvidersByIssuer: oidcProvidersByIssuer, FallbackAPIServers: fallbackAPIServers, Locales: locales, + DefaultLocale: defaultLocale, LocaleTags: localeTags, } diff --git a/model.go b/model.go index d17775e..a05f313 100644 --- a/model.go +++ b/model.go @@ -106,6 +106,11 @@ func ParseUUID(idOrUUID string) (string, error) { return "", errors.New("invalid ID or UUID") } +type Plural struct { + Message string + N int +} + func (app *App) ValidatePlayerName(playerName string) error { if app.TransientLoginEligible(playerName) { return &UserError{Message: "name is reserved for transient login"} @@ -116,10 +121,12 @@ func (app *App) ValidatePlayerName(playerName string) error { } if len(playerName) > maxLength { return &UserError{ - Message: "can't be longer than %d character", - MessagePlural: mo.Some("can't be longer than %d characters"), - N: mo.Some(maxLength), - Params: []interface{}{maxLength}, + Message: "can't be longer than %d character", + Plural: mo.Some(Plural{ + Message: "can't be longer than %d characters", + N: maxLength, + }), + Params: []interface{}{maxLength}, } }