description: The consumer-facing API for composing grammatically correct text from base forms.
---
# Forward Composition API
The forward API composes grammatically correct text from base forms. This is the consumer-facing side of go-i18n -- applications call these functions to build messages.
## Service Setup
```go
// Option 1: Default service (lazy-initialised, English)
svc := i18n.Default()
// Option 2: Explicit creation with options
svc, err := i18n.New(
i18n.WithFallback("en"),
i18n.WithDefaultHandlers(),
)
i18n.SetDefault(svc)
// Option 3: Custom loader (your own filesystem)
loader := i18n.NewFSLoader(myFS, "locales")
svc, err := i18n.NewWithLoader(loader)
// Option 4: Load from an arbitrary fs.FS
svc, err := i18n.NewWithFS(myFS, "locales")
```
The service automatically detects the system language from `LANG`, `LC_ALL`, or `LC_MESSAGES` environment variables using BCP 47 tag matching.
### Options
| Option | Effect |
|--------|--------|
| `WithFallback("en")` | Set fallback language for missing translations |
| `WithDefaultHandlers()` | Register the six built-in `i18n.*` namespace handlers |
i18n.ActionFailed("push", "commits") // "Failed to push commits"
i18n.Label("status") // "Status:"
```
## T() -- Core Translation Function
`T()` resolves message IDs through a handler chain, then falls back to direct key lookup with language fallback.
```go
i18n.T("greeting") // Direct key lookup
i18n.T("i18n.label.status") // Via LabelHandler -> "Status:"
i18n.T("i18n.progress.build") // Via ProgressHandler -> "Building..."
i18n.T("i18n.count.file", 5) // Via CountHandler -> "5 files"
```
Resolution order:
1. Run through handler chain (stops at first match)
2. Look up key in current language messages
3. Look up key in fallback language messages
4. Try `common.action.{verb}` and `common.{verb}` variants
5. Handle missing key according to current mode
### Raw()
`Raw()` translates without running the `i18n.*` namespace handler chain. Useful when you want direct key lookup only.
```go
i18n.Raw("my.custom.key") // Direct lookup, no handler magic
```
## Magic Namespace Handlers
Six built-in handlers are registered by `WithDefaultHandlers()`. They intercept keys matching their `i18n.*` prefix and compose output from grammar primitives.
### i18n.label.* -- LabelHandler
Produces labelled output with locale-specific suffix.
```go
T("i18n.label.status") // "Status:"
T("i18n.label.progress") // "Progress:"
```
The suffix is language-specific: English uses `:`, French uses ` :` (space before colon).
The Subject carries metadata that gendered/formal language systems (French, German, Japanese) use to select correct grammatical forms. English mostly ignores gender/formality, but the API is language-agnostic.
## Translation Context -- C()
Provides disambiguation for translations where the same key has different meanings in different contexts: