Documentation
¶
Overview ¶
Package i18n provides a lightweight internationalization (i18n) framework for Go applications, supporting translation of strings into multiple languages.
It supports language parsing, validation, translation lookup with fallback, formatted translations, and loading translations from embedded filesystems or raw JSON data.
Consumers are responsible for supplying their own translation files. The package does not embed any locale data itself.
Translation files must be nested JSON objects. Dot-separated lookup keys are derived from the nesting hierarchy:
{
"user": {
"created": "User created successfully",
"not_found": "User not found"
},
"error": {
"internal": "An internal error occurred."
}
}
The keys above are accessed as "user.created", "user.not_found", and "error.internal" respectively. Flat JSON (e.g. {"user.created": "..."}) is no longer supported.
Context-aware translation ¶
The Bundle.TCTX and Bundle.TfCTX methods (and their global counterparts TCTX and TfCTX) resolve the language automatically from a context.Context. The resolution priority is:
- A Language stored directly via WithLanguage.
- An *net/http.Request stored via WithRequest; its Accept-Language header is parsed and matched against the bundle's loaded languages.
- Default as a last resort.
The Middleware function provides a standard HTTP middleware that parses the Accept-Language header on every request and injects the resolved language into the context, so downstream handlers can simply call TCTX.
Example translation file (locales/en.json):
{
"user": {
"created": "User created successfully",
"not_found": "User not found"
},
"error": {
"internal": "An internal error occurred.",
"details": "Error in %s at line %d."
}
}
Example usage:
package main
import (
"embed"
"fmt"
"github.com/valentin-kaiser/go-core/i18n"
)
//go:embed locales/*.json
var localesFS embed.FS
func main() {
// Load translations from an embedded filesystem
bundle, err := i18n.New(i18n.WithFS(localesFS, "locales"))
if err != nil {
panic(err)
}
// Translate a key derived from the JSON nesting hierarchy
fmt.Println(bundle.T(i18n.German, "user.created"))
// Translate with format arguments
fmt.Println(bundle.Tf(i18n.English, "error.details", "file.txt", 42))
}
Index ¶
- Variables
- func GlobalMiddleware() func(http.Handler) http.Handler
- func Init(opts ...Option) error
- func Middleware(b *Bundle) func(http.Handler) http.Handler
- func RequestFromContext(ctx context.Context) (*http.Request, bool)
- func SetDefault(b *Bundle)
- func T(lang Language, key string) string
- func TCTX(ctx context.Context, key string) string
- func Tf(lang Language, key string, args ...any) string
- func TfCTX(ctx context.Context, key string, args ...any) string
- func Valid(lang string) bool
- func WithLanguage(ctx context.Context, lang Language) context.Context
- func WithRequest(ctx context.Context, r *http.Request) context.Context
- type Bundle
- func (b *Bundle) Has(lang Language, key string) bool
- func (b *Bundle) HasLanguage(lang Language) bool
- func (b *Bundle) Languages() []Language
- func (b *Bundle) Load(fsys fs.FS, dir string) error
- func (b *Bundle) Register(lang Language, translations map[string]string)
- func (b *Bundle) RegisterJSON(lang Language, data []byte) error
- func (b *Bundle) T(lang Language, key string) string
- func (b *Bundle) TCTX(ctx context.Context, key string) string
- func (b *Bundle) Tf(lang Language, key string, args ...any) string
- func (b *Bundle) TfCTX(ctx context.Context, key string, args ...any) string
- type ContextKey
- type Language
- type Option
Constants ¶
This section is empty.
Variables ¶
var ( // LanguageKey is the context key used to store and retrieve the resolved // Language directly. It takes priority over the request key when both are set. LanguageKey any = ContextKey("Language") // RequestKey is the context key used to store and retrieve an *http.Request. // The request's Accept-Language header is parsed to determine the language // when no direct Language is found in the context. RequestKey any = ContextKey("Request") )
Functions ¶
func GlobalMiddleware ¶
GlobalMiddleware returns an HTTP middleware that uses the global default Bundle. See Middleware for details.
func Init ¶
Init initialises the global default bundle with the given options, replacing any previously loaded translations. This function is safe for concurrent use.
func Middleware ¶
Middleware returns an HTTP middleware that resolves the caller's preferred language from the request's Accept-Language header, stores the resolved Language in the request context (retrievable via LanguageFromContext), and also stores the *http.Request itself (retrievable via RequestFromContext).
The resolved language is the best match among the languages loaded in the given Bundle. If the Accept-Language header is missing or no match is found, the Default language is used.
Usage with a standard http.ServeMux:
bundle, _ := i18n.New(i18n.WithFS(localesFS, "locales"))
mux := http.NewServeMux()
mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
msg := bundle.TCTX(r.Context(), "greeting")
fmt.Fprintln(w, msg)
})
http.ListenAndServe(":8080", i18n.Middleware(bundle)(mux))
func RequestFromContext ¶
RequestFromContext extracts the *http.Request stored by WithRequest. It returns the request and true if found, or nil and false otherwise.
func SetDefault ¶
func SetDefault(b *Bundle)
SetDefault replaces the global default bundle. It should be called early during application startup before any T/Tf calls are made. This function is safe for concurrent use.
func T ¶
T translates a key using the global default bundle. This function is safe for concurrent use.
func TCTX ¶
TCTX translates a key using the language resolved from the given context and the global default bundle. See Bundle.TCTX for the resolution order. This function is safe for concurrent use.
func Tf ¶
Tf translates and formats a key using the global default bundle. This function is safe for concurrent use.
func TfCTX ¶
TfCTX translates and formats a key using the language resolved from the given context and the global default bundle. See Bundle.TCTX for the resolution order. This function is safe for concurrent use.
func WithLanguage ¶
WithLanguage returns a new context that carries the given Language. Downstream code can retrieve it with LanguageFromContext.
func WithRequest ¶
WithRequest returns a new context that carries the given *http.Request. The Bundle.TCTX method will parse the request's Accept-Language header as a fallback when no direct Language is present in the context.
Types ¶
type Bundle ¶
type Bundle struct {
// contains filtered or unexported fields
}
Bundle holds loaded translations for one or more languages and provides lookup methods for retrieving translated strings.
func GetDefault ¶
func GetDefault() *Bundle
GetDefault returns the global default bundle. This function is safe for concurrent use.
func (*Bundle) HasLanguage ¶
HasLanguage reports whether the bundle contains translations for the given language.
func (*Bundle) Languages ¶
Languages returns all languages that have at least one translation loaded.
func (*Bundle) Load ¶
Load loads translations from an fs.FS at runtime. It scans the directory for all *.json files and derives the language code from each filename.
func (*Bundle) Register ¶
Register adds translations for a language from a Go map at runtime. It merges the new translations with any existing ones for that language.
func (*Bundle) RegisterJSON ¶
RegisterJSON adds translations for a language from raw JSON bytes at runtime. The JSON must be a nested object; keys are flattened to dot-separated strings internally (e.g. {"page": {"title": "Home"}} becomes "page.title").
func (*Bundle) T ¶
T translates a key for the given language. If the key is not found in the requested language, it falls back to Default. If still not found, the key itself is returned unchanged.
func (*Bundle) TCTX ¶
TCTX translates a key using the language resolved from the given context.
The resolution order is:
- A Language stored directly in the context via WithLanguage.
- An *http.Request stored in the context via WithRequest; the Accept-Language header is parsed and matched against the bundle's loaded languages.
- Default if neither of the above yields a result.
type ContextKey ¶
type ContextKey string
ContextKey is the type used for context keys in this package. Using a distinct type helps avoid collisions with other context keys in the application.
type Language ¶
type Language string
Language represents a BCP 47 language code.
func LanguageFromContext ¶
LanguageFromContext extracts the Language stored by WithLanguage. It returns the language and true if found, or "" and false otherwise.
type Option ¶
Option configures a Bundle during creation.
func WithEmbedFS ¶
WithEmbedFS is an alias for WithFS that explicitly takes an embed.FS. It reads translation files from the given directory inside the embedded filesystem.
func WithFS ¶
WithFS loads translation files from an embed.FS (or any fs.FS). It scans the given directory for JSON files named by language code (e.g. "en.json", "fr.json", "ja.json") and loads each one automatically. Any language is supported — the language code is derived from the filename. Files that cannot be read or parsed are silently skipped.
func WithJSON ¶
WithJSON registers translations for a language from raw JSON bytes. The JSON must be a nested object; dot-separated lookup keys are derived from the nesting hierarchy (e.g. {"page": {"title": "Home"}} is accessed as "page.title"). If the JSON data is malformed, an error is returned when the bundle is created, as it indicates a programming error that should be caught during development.