1 Forward-API
Virgil edited this page 2026-02-19 15:56:33 +00:00

Forward Composition API

The forward API composes grammatically correct text from base forms. This is the consumer-facing side of go-i18n — apps call these functions to build messages.

Service Setup

// Option 1: Default service (lazy-initialised, English)
svc := i18n.Default()

// Option 2: Explicit creation
svc, err := i18n.New(
    i18n.WithFallback("en"),
    i18n.WithDefaultHandlers(),
)
i18n.SetDefault(svc)

// Option 3: Custom loader
loader := i18n.NewFSLoader(myFS, "locales")
svc, err := i18n.NewWithLoader(loader)

Grammar Primitives

PastTense(verb) → string

3-tier lookup: JSON grammar data → irregular Go map → regular morphology rules.

i18n.PastTense("delete")  // "deleted"
i18n.PastTense("commit")  // "committed"
i18n.PastTense("go")      // "went" (irregular)
i18n.PastTense("run")     // "ran" (irregular)

Gerund(verb) → string

i18n.Gerund("delete")     // "deleting"
i18n.Gerund("commit")     // "committing"
i18n.Gerund("run")        // "running"

Pluralize(noun, count) → string

Returns singular for count=1, plural otherwise.

i18n.Pluralize("file", 1)     // "file"
i18n.Pluralize("file", 5)     // "files"
i18n.Pluralize("person", 3)   // "people" (irregular)
i18n.Pluralize("child", 2)    // "children" (irregular)

PluralForm(noun) → string

Always returns the plural form (no count check).

i18n.PluralForm("repository")  // "repositories"
i18n.PluralForm("child")       // "children"

Article(word) → string

Returns "a" or "an" based on phonetic rules, not spelling.

i18n.Article("file")     // "a"
i18n.Article("error")    // "an"
i18n.Article("URL")      // "a" (pronounced "yoo-arr-ell")
i18n.Article("hour")     // "an" (silent h)
i18n.Article("SSH")      // "an" (pronounced "ess-ess-aitch")

Uses consonant/vowel sound maps for exceptions, falls back to first-letter vowel check.

T() — Core Translation Function

T() resolves message IDs through a handler chain, then falls back to direct key lookup.

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"

Handler Chain

Handlers are evaluated in registration order. Each can intercept, transform, or delegate to the next handler. This is a middleware pattern.

Magic Namespace Handlers

Six built-in handlers are registered by WithDefaultHandlers():

i18n.label.* → LabelHandler

Produces labelled output with locale-specific suffix.

T("i18n.label.status")    // → "Status:"
T("i18n.label.progress")  // → "Progress:"

Format: Title(getWord(lang, word)) + label suffix (English: :, French: :)

i18n.progress.* → ProgressHandler

Produces gerund-form progress messages.

T("i18n.progress.build")              // → "Building..."
T("i18n.progress.build", "project")   // → "Building project..."
T("i18n.progress.delete", "cache")    // → "Deleting cache..."

Format: Title(Gerund(verb)) + optional subject + progress suffix (...)

i18n.count.* → CountHandler

Produces pluralised count messages.

T("i18n.count.file", 1)     // → "1 file"
T("i18n.count.file", 5)     // → "5 files"
T("i18n.count.person", 3)   // → "3 people"

i18n.done.* → DoneHandler

Produces past-tense completion messages.

T("i18n.done.delete", "config.yaml")  // → "Config.Yaml deleted"
T("i18n.done.delete")                 // → "Deleted"
T("i18n.done.push", "commits")        // → "Commits pushed"

i18n.fail.* → FailHandler

Produces failure messages.

T("i18n.fail.push", "commits")   // → "Failed to push commits"
T("i18n.fail.delete")            // → "Failed to delete"

i18n.numeric.* → NumericHandler

Locale-aware number formatting.

T("i18n.numeric.number", 1234567)   // → "1,234,567"
T("i18n.numeric.decimal", 3.14)     // → "3.14"
T("i18n.numeric.percent", 0.85)     // → "85%"
T("i18n.numeric.bytes", 1536000)    // → "1.5 MB"
T("i18n.numeric.ordinal", 3)        // → "3rd"
T("i18n.numeric.ago", 5, "minutes") // → "5 minutes ago"

Subject Builder — S()

Builds semantic context for complex translations:

s := i18n.S("file", "config.yaml")
s.Count(3)        // Set plural count
s.Gender("neuter") // Grammatical gender (for gendered languages)
s.In("workspace")  // Location context
s.Formal()         // Formal register

// All methods chain:
i18n.S("file", "config.yaml").Count(3).In("workspace").Formal()

The Subject carries metadata that gendered/formal language systems (French, German, Japanese) use to select the correct grammatical forms. English mostly ignores gender/formality, but the API is language-agnostic.