Lang Negotiation Middleware
Create a request translator from query, cookie, and Accept-Language
middleware/lang is the HTTP language negotiation middleware. It does not load message catalogs; lang.Provider() does that. The middleware only reads request language preferences and stores the current request *lang.Translator in ctx.Context().
Install
go get github.com/duxweb/runa/lang
go get github.com/duxweb/runa/middleware/lang
Connect to an application
package main
import (
"context"
"github.com/duxweb/runa"
"github.com/duxweb/runa/lang"
langmw "github.com/duxweb/runa/middleware/lang"
"github.com/duxweb/runa/route"
)
func main() {
app := runa.New()
app.Install(
route.Provider(route.Addr(":8080")),
lang.Provider(),
)
route.Default().Use(langmw.New(
langmw.Query("lang"),
langmw.Cookie("lang"),
langmw.Header("Accept-Language"),
))
route.Default().Get("/", func(ctx *route.Context) error {
tr := lang.From(ctx.Context())
return ctx.Text(tr.T("user_welcome", "Name", "Runa"))
})
if err := app.Run(context.Background()); err != nil {
panic(err)
}
}
Default sources
When no sources are passed, langmw.New() uses:
langmw.Query("lang")
langmw.Cookie("lang")
langmw.Header("Accept-Language")
So ?lang=zh-CN wins first, then cookie, then browser Accept-Language.
Relationship with route.Context
The middleware does two things:
ctx.SetContext(lang.WithTranslator(ctx.Context(), translator))ctx.SetLang(translator.Locale())
Application code can then use:
tr := lang.From(ctx.Context())
current := ctx.Lang()
Use lang.From(ctx.Context()) for translation and ctx.Lang() when you only need the current locale string.
Use with template t
When lang/view.Provider() is installed, {{ t "key" }} automatically uses the translator stored in request context by this middleware:
app.Install(
lang.Provider(),
view.Provider(),
langview.Provider(),
)
route.Default().Use(langmw.New())
Template:
<h1>{{ t "user_welcome" "Name" .Name }}</h1>
Common mistakes
Mounting middleware without lang.Provider
The middleware needs lang.Default() to create request translators. Install lang.Provider() first.
Using the wrong header name
Browser language preferences are usually in Accept-Language, not Language.
Negotiating language inside handlers
Language negotiation is cross-cutting HTTP behavior. Put it in global or group middleware, then read lang.From(ctx.Context()) in handlers.
API quick reference
langmw.New(sources...)creates language negotiation middleware.langmw.Query(name)reads language from query.langmw.Cookie(name)reads language from cookie.langmw.Header(name)reads language from header.lang.From(ctx.Context())reads the current request translator.