Skip to content

Latest commit

 

History

History
115 lines (82 loc) · 3.24 KB

File metadata and controls

115 lines (82 loc) · 3.24 KB

i18n

In v2, i18n is an opt-in module, not loaded by default. When you need it, attach it to the App with WithI18n and pass the template function i.Funcs() to the template engine. Locale matching uses the stdlib golang.org/x/text (BCP-47).

The message store is the simplest form locale → key → text (no singular/plural); this module does not do date/number/currency/timezone formatting.

Overview

Capability Entry point
locale detection app.Use(AcceptLanguage("en", "zh", ...)) middleware
read locale in a Handler c.Locale()
translate in a Handler c.Translate(locale, key, args...)
message store I18n (NewI18n / Add / Set / LoadJSON)
translate in a template T (injected by i.Funcs())

1. Accept-Language middleware

app := httpsrv.New()
app.Use(httpsrv.AcceptLanguage("en", "zh", "ja")) // first is the default/fallback
  • Parses the Accept-Language header and matches a supported locale by BCP-47 (e.g. en-USen, zh-Hanszh).
  • Falls back to the first argument (the default) when nothing matches.
  • The result is stored in the request context; read it with c.Locale().

2. Message store I18n (flat key → text)

i := httpsrv.NewI18n("en") // default language

// batch
i.Add("zh", map[string]string{"welcome": "欢迎", "hi": "你好 %s"})
i.Add("en", map[string]string{"welcome": "Welcome", "hi": "Hi %s"})

// single
i.Set("en", "bye", "Bye")

// load from JSON (flat {"key": "text"})
i.LoadJSON("en", []byte(`{"welcome": "Welcome", "hi": "Hi %s"}`))

Translate:

i.Translate("en", "welcome")      // "Welcome"
i.Translate("zh", "missing")      // fall back to default → then the key: "missing"
i.Translate("zh", "hi", "Alice")  // "你好 Alice" (args via fmt.Sprintf)
  • Lookup chain: requested locale → default locale → the key itself.
  • Locales are case-insensitive.

3. Attach to the App (use in a Handler)

app := httpsrv.New(httpsrv.WithI18n(i))

app.Get("/", func(c httpsrv.Ctx) error {
    return c.SendString(c.Translate(c.Locale(), "welcome"))
})
  • Without WithI18n: c.Translate(...) returns the key unchanged (i18n module not loaded).
  • Without the AcceptLanguage middleware: c.Locale() falls back to the i18n default, then the empty string.

4. Use in a template (T)

Pass i.Funcs() as extra template functions to the template engine:

r, _ := httpsrv.TemplatesFS(views, i.Funcs())
app := httpsrv.New(httpsrv.WithViews(r), httpsrv.WithI18n(i))

Template: <h1>{{T .Lang "welcome"}}</h1>

Full example

package main

import (
	"embed"
	"io/fs"

	"github.com/hooto/httpsrv/v2"
)

//go:embed views
var views embed.FS

func main() {
	i := httpsrv.NewI18n("en")
	i.Add("en", map[string]string{"welcome": "Welcome"})
	i.Add("zh", map[string]string{"welcome": "欢迎"})

	sub, _ := fs.Sub(views, "views")
	r, err := httpsrv.TemplatesFS(sub, i.Funcs())
	if err != nil {
		panic(err)
	}

	app := httpsrv.New(httpsrv.WithViews(r), httpsrv.WithI18n(i))
	app.Use(httpsrv.AcceptLanguage("en", "zh")) // detect locale

	app.Get("/", func(c httpsrv.Ctx) error {
		return c.Render("home.html", map[string]any{"Lang": c.Locale()})
	})

	_ = app.Run(":8080")
}

home.html: <h1>{{T .Lang "welcome"}}</h1>