diff --git a/anubis.go b/anubis.go index 6b219ca..ae674b4 100644 --- a/anubis.go +++ b/anubis.go @@ -32,3 +32,7 @@ const APIPrefix = "/.within.website/x/cmd/anubis/api/" // DefaultDifficulty is the default "difficulty" (number of leading zeroes) // that must be met by the client in order to pass the challenge. const DefaultDifficulty = 4 + +// ForcedLanguage is the language being used instead of the one of the request's Accept-Language header +// if being set. +var ForcedLanguage = "" diff --git a/cmd/anubis/main.go b/cmd/anubis/main.go index beae534..57ab4a1 100644 --- a/cmd/anubis/main.go +++ b/cmd/anubis/main.go @@ -50,6 +50,7 @@ var ( cookieExpiration = flag.Duration("cookie-expiration-time", anubis.CookieDefaultExpirationTime, "The amount of time the authorization cookie is valid for") cookiePrefix = flag.String("cookie-prefix", "techaro.lol-anubis", "prefix for browser cookies created by Anubis") cookiePartitioned = flag.Bool("cookie-partitioned", false, "if true, sets the partitioned flag on Anubis cookies, enabling CHIPS support") + forcedLanguage = flag.String("forced-language", "", "if set, this language is being used instead of the one from the request's Accept-Language header") hs512Secret = flag.String("hs512-secret", "", "secret used to sign JWTs, uses ed25519 if not set") cookieSecure = flag.Bool("cookie-secure", true, "if true, sets the secure flag on Anubis cookies") ed25519PrivateKeyHex = flag.String("ed25519-private-key-hex", "", "private key used to sign JWTs, if not set a random one will be assigned") @@ -378,6 +379,7 @@ func main() { anubis.CookieName = *cookiePrefix + "-auth" anubis.TestCookieName = *cookiePrefix + "-cookie-verification" + anubis.ForcedLanguage = *forcedLanguage // If OpenGraph configuration values are not set in the config file, use the // values from flags / envvars. diff --git a/docs/docs/CHANGELOG.md b/docs/docs/CHANGELOG.md index b77ae99..e19e106 100644 --- a/docs/docs/CHANGELOG.md +++ b/docs/docs/CHANGELOG.md @@ -13,13 +13,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Add `COOKIE_SECURE` option to set the cookie [Secure flag](https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/Cookies#block_access_to_your_cookies) - Sets cookie defaults to use [SameSite: None](https://web.dev/articles/samesite-cookies-explained) - - Determine the `BIND_NETWORK`/`--bind-network` value from the bind address ([#677](https://github.com/TecharoHQ/anubis/issues/677)). - Implement localization system. Find locale files in lib/localization/locales/. - Implement a [development container](https://containers.dev/) manifest to make contributions easier. -- Fix dynamic cookie domains functionality ([#731](https://github.com/TecharoHQ/anubis/pull/731)). -- Add option for custom cookie prefix ([#732](https://github.com/TecharoHQ/anubis/pull/732)). +- Fix dynamic cookie domains functionality ([#731](https://github.com/TecharoHQ/anubis/pull/731)) +- Add option for custom cookie prefix ([#732](https://github.com/TecharoHQ/anubis/pull/732)) - Remove the "Success" interstitial after a proof of work challenge is concluded. +- Add option for forcing a specific language ([#742](https://github.com/TecharoHQ/anubis/pull/742)) ## v1.20.0: Thancred Waters diff --git a/lib/localization/localization.go b/lib/localization/localization.go index d8af92c..e268f0e 100644 --- a/lib/localization/localization.go +++ b/lib/localization/localization.go @@ -3,6 +3,7 @@ package localization import ( "embed" "encoding/json" + "github.com/TecharoHQ/anubis" "net/http" "strings" "sync" @@ -57,14 +58,14 @@ func NewLocalizationService() *LocalizationService { globalService = &LocalizationService{bundle: bundle} }) - + // Safety check - if globalService is still nil, create a minimal one if globalService == nil { bundle := i18n.NewBundle(language.English) bundle.RegisterUnmarshalFunc("json", json.Unmarshal) globalService = &LocalizationService{bundle: bundle} } - + return globalService } @@ -93,8 +94,13 @@ func (sl *SimpleLocalizer) T(messageID string) string { return sl.Localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: messageID}) } -// GetLocalizer creates a localizer based on the request's Accept-Language header +// GetLocalizer creates a localizer based on the request's Accept-Language header or forcedLanguage option func GetLocalizer(r *http.Request) *SimpleLocalizer { - localizer := NewLocalizationService().GetLocalizerFromRequest(r) + var localizer *i18n.Localizer + if anubis.ForcedLanguage == "" { + localizer = NewLocalizationService().GetLocalizerFromRequest(r) + } else { + localizer = NewLocalizationService().GetLocalizer(anubis.ForcedLanguage) + } return &SimpleLocalizer{Localizer: localizer} }