Added translator WithLanguage + exported Accept Language header parsing

This commit is contained in:
Quentin Renard
2025-11-25 16:19:04 +00:00
parent f9600a19ce
commit 44d3647127
2 changed files with 49 additions and 7 deletions

View File

@@ -151,7 +151,7 @@ func (t *Translator) HTTPMiddleware(h http.Handler) http.Handler {
return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
// Store language in context
if l := r.Header.Get("Accept-Language"); l != "" {
*r = *r.WithContext(contextWithTranslatorLanguage(r.Context(), t.parseAcceptLanguage(l)))
*r = *r.WithContext(contextWithTranslatorLanguage(r.Context(), t.LanguageFromAcceptLanguageHeader(l)))
}
// Next handler
@@ -159,7 +159,7 @@ func (t *Translator) HTTPMiddleware(h http.Handler) http.Handler {
})
}
func (t *Translator) parseAcceptLanguage(h string) string {
func (t *Translator) LanguageFromAcceptLanguageHeader(h string) string {
// Split on comma
var qs []float64
ls := make(map[float64][]string)
@@ -203,7 +203,7 @@ func (t *Translator) parseAcceptLanguage(h string) string {
}
}
}
return ""
return t.defaultLanguage
}
const contextKeyTranslatorLanguage = contextKey("astikit.translator.language")
@@ -231,6 +231,10 @@ func (t *Translator) language(language string) string {
// LanguageCtx returns the translator language from the context, or the default language if not in the context
func (t *Translator) LanguageCtx(ctx context.Context) string {
return t.LanguageC(ctx)
}
func (t *Translator) LanguageC(ctx context.Context) string {
return t.language(translatorLanguageFromContext(ctx))
}
@@ -273,3 +277,23 @@ func (t *Translator) TranslateC(ctx context.Context, key string) string {
func (t *Translator) TranslateCf(ctx context.Context, key string, args ...any) string {
return t.Translatef(translatorLanguageFromContext(ctx), key, args...)
}
type translatorForLanguage struct {
language string
t *Translator
}
func (t *Translator) WithLanguage(language string) *translatorForLanguage {
return &translatorForLanguage{
language: language,
t: t,
}
}
func (t *translatorForLanguage) Translate(k string) string {
return t.t.Translate(t.language, k)
}
func (t *translatorForLanguage) Translatef(k string, args ...any) string {
return t.t.Translatef(t.language, k, args...)
}

View File

@@ -111,14 +111,32 @@ func TestTranslator(t *testing.T) {
t.Fatalf("expected %+v, got %+v", v.expected, o)
}
}
// With language
twl := tl.WithLanguage("en")
if e, g := "1", twl.Translate("1"); !reflect.DeepEqual(e, g) {
t.Fatalf("expected %+v, got %+v", e, g)
}
if e, g := "4", twl.Translate("4"); !reflect.DeepEqual(e, g) {
t.Fatalf("expected %+v, got %+v", e, g)
}
if e, g := "en.a", twl.Translate("a"); !reflect.DeepEqual(e, g) {
t.Fatalf("expected %+v, got %+v", e, g)
}
if e, g := "fvf", twl.Translatef("f", "v"); !reflect.DeepEqual(e, g) {
t.Fatalf("expected %+v, got %+v", e, g)
}
}
func TestTranslator_ParseAcceptLanguage(t *testing.T) {
tl := NewTranslator(TranslatorOptions{ValidLanguages: []string{"en", "fr"}})
if e, g := "", tl.parseAcceptLanguage(""); !reflect.DeepEqual(e, g) {
func TestTranslator_LanguageFromAcceptLanguageHeader(t *testing.T) {
tl := NewTranslator(TranslatorOptions{
DefaultLanguage: "en",
ValidLanguages: []string{"en", "fr"},
})
if e, g := "en", tl.LanguageFromAcceptLanguageHeader(""); !reflect.DeepEqual(e, g) {
t.Fatalf("expected %+v, got %+v", e, g)
}
if e, g := "fr", tl.parseAcceptLanguage(" fr-FR, fr ; q=0.9 ,en;q=0.7,en-US;q=0.8 "); !reflect.DeepEqual(e, g) {
if e, g := "fr", tl.LanguageFromAcceptLanguageHeader(" fr-FR, fr ; q=0.9 ,en;q=0.7,en-US;q=0.8 "); !reflect.DeepEqual(e, g) {
t.Fatalf("expected %+v, got %+v", e, g)
}
}