fix(quick-261029-d9j): pick the mail language from Accept-Language, add mail.fallback_locale, Polish subjects
- preferred_locale and the request locale are normalised (comma lists, q-weights, region subtags, case) to pl or en by NormalizeMailLocale, so a raw Accept-Language such as en-GB,en;q=0.9 selects the -en templates - new golem15.user.mail.fallback_locale (default pl) is used when neither names a supported language; ResolveMailLocaleFor applies it, and Boot rejects any value other than pl or en - activate, reactivate and restore Polish templates get Polish subjects - no template, route or payload changes; MailTemplate and ResolveMailLocale keep their signatures
This commit is contained in:
@@ -1,16 +1,187 @@
|
||||
package classes
|
||||
|
||||
import "testing"
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"git.golem15.com/golem15/sm-user-plugin/models"
|
||||
"git.golem15.com/golem15/summercms/modules/backpack"
|
||||
"git.golem15.com/golem15/summercms/modules/compass"
|
||||
"git.golem15.com/golem15/summercms/modules/towel"
|
||||
)
|
||||
|
||||
func TestMailTemplate(t *testing.T) {
|
||||
base := "golem15.user::mail.reactivate"
|
||||
if got := MailTemplate(base, "pl"); got != base {
|
||||
t.Fatalf("pl = %s", got)
|
||||
}
|
||||
if got := MailTemplate(base, ""); got != base {
|
||||
t.Fatalf("empty = %s", got)
|
||||
}
|
||||
if got := MailTemplate(base, "en"); got != base+"-en" {
|
||||
t.Fatalf("en = %s", got)
|
||||
for _, tc := range []struct {
|
||||
locale, want string
|
||||
}{
|
||||
{"pl", base},
|
||||
{"", base},
|
||||
{"en", base + "-en"},
|
||||
{"en-GB", base + "-en"},
|
||||
{"en-GB,en;q=0.9", base + "-en"},
|
||||
{"de", base},
|
||||
{"pl-PL,en;q=0.5", base},
|
||||
} {
|
||||
if got := MailTemplate(base, tc.locale); got != tc.want {
|
||||
t.Errorf("MailTemplate(%q) = %s, want %s", tc.locale, got, tc.want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestNormalizeMailLocale(t *testing.T) {
|
||||
for _, tc := range []struct {
|
||||
raw, want string
|
||||
}{
|
||||
{"en", "en"},
|
||||
{"pl", "pl"},
|
||||
{"EN", "en"},
|
||||
{"en-GB", "en"},
|
||||
{"en_US", "en"},
|
||||
{"pl-PL", "pl"},
|
||||
{" en-gb ; q=0.9 ", "en"},
|
||||
{"en-GB,en;q=0.9", "en"},
|
||||
{"pl-PL,pl;q=0.9,en-US;q=0.8,en;q=0.7", "pl"},
|
||||
{"de-DE,de;q=0.9,en;q=0.8", "en"},
|
||||
{"de-DE,en;q=0.5,pl;q=0.7", "pl"},
|
||||
{"en;q=0.5,pl;q=0.5", "en"},
|
||||
{"en;q=0,pl", "pl"},
|
||||
{"en;q=0", ""},
|
||||
{"en;q=abc,pl;q=0.1", "pl"},
|
||||
{"en;q=1.5", ""},
|
||||
{"english", ""},
|
||||
{"de", ""},
|
||||
{"*", ""},
|
||||
{"", ""},
|
||||
{" ", ""},
|
||||
} {
|
||||
if got := NormalizeMailLocale(tc.raw); got != tc.want {
|
||||
t.Errorf("NormalizeMailLocale(%q) = %q, want %q", tc.raw, got, tc.want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestResolveMailLocale(t *testing.T) {
|
||||
str := func(s string) *string { return &s }
|
||||
header := "en-GB,en;q=0.9"
|
||||
for _, tc := range []struct {
|
||||
name string
|
||||
saved *string
|
||||
nilUser bool
|
||||
request string
|
||||
want string
|
||||
}{
|
||||
{"saved region form wins", str("en-GB"), false, "pl", "en"},
|
||||
{"saved upper case", str("PL"), false, "", "pl"},
|
||||
{"unsupported saved falls through", str("de"), false, header, "en"},
|
||||
{"nil user, raw header", nil, true, header, "en"},
|
||||
{"nil user, no request locale", nil, true, "", ""},
|
||||
{"empty saved, unsupported request", str(""), false, "fr", ""},
|
||||
} {
|
||||
ctx := context.Background()
|
||||
if tc.request != "" {
|
||||
ctx = towel.WithLocale(ctx, tc.request)
|
||||
}
|
||||
var user *models.User
|
||||
if !tc.nilUser {
|
||||
user = &models.User{PreferredLocale: tc.saved}
|
||||
}
|
||||
if got := ResolveMailLocale(ctx, user); got != tc.want {
|
||||
t.Errorf("%s: got %q, want %q", tc.name, got, tc.want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func mailTestApp(t *testing.T, environ ...string) *backpack.App {
|
||||
t.Helper()
|
||||
cfg, err := compass.Open(compass.Options{Dir: t.TempDir(), Env: "development", Environ: append([]string{"SUMMER_ENV=development"}, environ...)})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
return backpack.New(cfg)
|
||||
}
|
||||
|
||||
func TestMailFallbackLocale(t *testing.T) {
|
||||
if got, err := MailFallbackLocale(nil); got != "pl" || err != nil {
|
||||
t.Errorf("nil app: %q %v", got, err)
|
||||
}
|
||||
if got, err := MailFallbackLocale(&backpack.App{}); got != "pl" || err != nil {
|
||||
t.Errorf("nil config: %q %v", got, err)
|
||||
}
|
||||
if got, err := MailFallbackLocale(mailTestApp(t)); got != "pl" || err != nil {
|
||||
t.Errorf("no key: %q %v", got, err)
|
||||
}
|
||||
for _, tc := range []struct {
|
||||
value, want string
|
||||
bad bool
|
||||
}{
|
||||
{"", "pl", false},
|
||||
{" ", "pl", false},
|
||||
{"en", "en", false},
|
||||
{"EN-gb", "en", false},
|
||||
{"pl", "pl", false},
|
||||
{"de", "pl", true},
|
||||
} {
|
||||
app := mailTestApp(t)
|
||||
if err := app.Config.Set("golem15.user.mail.fallback_locale", tc.value); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
got, err := MailFallbackLocale(app)
|
||||
if got != tc.want {
|
||||
t.Errorf("%q: got %q, want %q", tc.value, got, tc.want)
|
||||
}
|
||||
if tc.bad {
|
||||
if err == nil || !strings.Contains(err.Error(), "golem15.user.mail.fallback_locale") || !strings.Contains(err.Error(), `"de"`) {
|
||||
t.Errorf("%q: error %v", tc.value, err)
|
||||
}
|
||||
} else if err != nil {
|
||||
t.Errorf("%q: unexpected error %v", tc.value, err)
|
||||
}
|
||||
}
|
||||
app := mailTestApp(t, "SUMMER_GOLEM15__USER__MAIL__FALLBACK_LOCALE=en")
|
||||
if got, err := MailFallbackLocale(app); got != "en" || err != nil {
|
||||
t.Errorf("env override: %q %v", got, err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestResolveMailLocaleFor(t *testing.T) {
|
||||
const restore = "golem15.user::mail.restore"
|
||||
user := &models.User{}
|
||||
headerCtx := towel.WithLocale(context.Background(), "en-GB,en;q=0.9")
|
||||
|
||||
// The reported bug: raw Accept-Language, no preferred_locale, default config.
|
||||
if got := MailTemplate(restore, ResolveMailLocaleFor(headerCtx, mailTestApp(t), user)); got != restore+"-en" {
|
||||
t.Errorf("raw header: %s", got)
|
||||
}
|
||||
if got := MailTemplate(restore, ResolveMailLocaleFor(context.Background(), mailTestApp(t), user)); got != restore {
|
||||
t.Errorf("default fallback: %s", got)
|
||||
}
|
||||
if got := ResolveMailLocaleFor(context.Background(), nil, nil); got != "pl" {
|
||||
t.Errorf("nil app and user: %q", got)
|
||||
}
|
||||
|
||||
set := mailTestApp(t)
|
||||
if err := set.Config.Set("golem15.user.mail.fallback_locale", "en"); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if got := MailTemplate(restore, ResolveMailLocaleFor(context.Background(), set, user)); got != restore+"-en" {
|
||||
t.Errorf("fallback en via Set: %s", got)
|
||||
}
|
||||
env := mailTestApp(t, "SUMMER_GOLEM15__USER__MAIL__FALLBACK_LOCALE=en")
|
||||
if got := MailTemplate(restore, ResolveMailLocaleFor(context.Background(), env, user)); got != restore+"-en" {
|
||||
t.Errorf("fallback en via env: %s", got)
|
||||
}
|
||||
// The user and the request still come first.
|
||||
if got := ResolveMailLocaleFor(towel.WithLocale(context.Background(), "pl-PL,en;q=0.5"), set, user); got != "pl" {
|
||||
t.Errorf("Polish-first browser on an en fallback: %q", got)
|
||||
}
|
||||
|
||||
bad := mailTestApp(t)
|
||||
if err := bad.Config.Set("golem15.user.mail.fallback_locale", "de"); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if got := ResolveMailLocaleFor(context.Background(), bad, user); got != "pl" {
|
||||
t.Errorf("invalid fallback: %q", got)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user