go/docs/pkg/i18n/GRAMMAR.md
Snider e9be13bcd3 docs(i18n): add comprehensive package documentation
- README.md: Quick start, all features, configuration options
- GRAMMAR.md: Verb conjugation, pluralisation, articles, templates
- EXTENDING.md: Custom loaders, handlers, framework integration

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 19:18:43 +00:00

5.3 KiB

Grammar Engine

The i18n grammar engine automatically handles verb conjugation, noun pluralisation, and article selection. It uses a combination of locale-defined rules and built-in English defaults.

Verb Conjugation

Past Tense

i18n.PastTense("delete")   // "deleted"
i18n.PastTense("create")   // "created"
i18n.PastTense("run")      // "ran" (irregular)
i18n.PastTense("build")    // "built" (irregular)

Rules applied (in order):

  1. Check locale JSON gram.verb.{verb}.past
  2. Check built-in irregular verbs map
  3. Apply regular conjugation rules:
    • Ends in 'e' → add 'd' (delete → deleted)
    • Ends in consonant + 'y' → change to 'ied' (try → tried)
    • Short verb ending in CVC → double consonant (stop → stopped)
    • Otherwise → add 'ed' (walk → walked)

Gerund (-ing form)

i18n.Gerund("build")   // "building"
i18n.Gerund("run")     // "running"
i18n.Gerund("make")    // "making"
i18n.Gerund("die")     // "dying"

Rules applied:

  1. Check locale JSON gram.verb.{verb}.gerund
  2. Check built-in irregular verbs map
  3. Apply regular rules:
    • Ends in 'ie' → change to 'ying' (die → dying)
    • Ends in 'e' (not 'ee') → drop 'e', add 'ing' (make → making)
    • Short verb ending in CVC → double consonant (run → running)
    • Otherwise → add 'ing' (build → building)

Noun Pluralisation

i18n.Pluralize("file", 1)     // "file"
i18n.Pluralize("file", 5)     // "files"
i18n.Pluralize("child", 2)    // "children" (irregular)
i18n.Pluralize("analysis", 3) // "analyses" (Latin)

Rules applied (in order):

  1. Check locale JSON gram.noun.{noun}.other
  2. Check built-in irregular nouns map
  3. Apply regular rules:
    • Ends in 's', 'x', 'z', 'ch', 'sh' → add 'es'
    • Ends in consonant + 'y' → change to 'ies'
    • Ends in 'f' or 'fe' → change to 'ves' (leaf → leaves)
    • Otherwise → add 's'

Built-in Irregular Nouns

Singular Plural
child children
person people
man men
woman women
foot feet
tooth teeth
mouse mice
datum data
index indices
crisis crises
fish fish
sheep sheep

Articles

i18n.Article("apple")     // "an apple"
i18n.Article("banana")    // "a banana"
i18n.Article("hour")      // "an hour" (silent h)
i18n.Article("user")      // "a user" (y sound)
i18n.Article("umbrella")  // "an umbrella"

Rules:

  1. Vowel sound words get "an" (a, e, i, o, u start)
  2. Consonant sound words get "a"
  3. Exception lists handle:
    • Silent 'h' words: hour, honest, honour, heir, herb
    • 'Y' sound words: user, union, unique, unit, universe

Composed Messages

Labels

i18n.Label("status")   // "Status:"
i18n.Label("version")  // "Version:"

Uses gram.punct.label suffix (default :) from locale.

Progress Messages

i18n.Progress("build")                  // "Building..."
i18n.ProgressSubject("check", "config") // "Checking config..."

Uses gram.punct.progress suffix (default ...) from locale.

Action Results

i18n.ActionResult("delete", "file")    // "File deleted"
i18n.ActionResult("create", "project") // "Project created"

Pattern: {Title(subject)} {past(verb)}

Action Failures

i18n.ActionFailed("delete", "file")  // "Failed to delete file"
i18n.ActionFailed("save", "config")  // "Failed to save config"

Pattern: Failed to {verb} {subject}

Locale Configuration

Define grammar in your locale JSON:

{
  "gram": {
    "verb": {
      "deploy": {
        "past": "deployed",
        "gerund": "deploying"
      },
      "sync": {
        "past": "synced",
        "gerund": "syncing"
      }
    },
    "noun": {
      "repository": {
        "one": "repository",
        "other": "repositories"
      },
      "schema": {
        "one": "schema",
        "other": "schemata"
      }
    },
    "article": {
      "indefinite": {
        "default": "a",
        "vowel": "an"
      },
      "definite": "the"
    },
    "punct": {
      "label": ":",
      "progress": "..."
    },
    "word": {
      "status": "status",
      "version": "version"
    }
  }
}

Template Functions

Use grammar functions in templates:

template.New("").Funcs(i18n.TemplateFuncs())
Function Example Result
past {{past "delete"}} "deleted"
gerund {{gerund "build"}} "building"
plural {{plural "file" 5}} "files"
article {{article "apple"}} "an apple"
title {{title "hello world"}} "Hello World"
lower {{lower "HELLO"}} "hello"
upper {{upper "hello"}} "HELLO"
quote {{quote "text"}} "text"

Language-Specific Grammar

The grammar engine loads language-specific data when available:

// Get grammar data for a language
data := i18n.GetGrammarData("de-DE")
if data != nil {
    // Access verb forms, noun forms, etc.
}

// Set grammar data programmatically
i18n.SetGrammarData("de-DE", &i18n.GrammarData{
    Verbs: map[string]i18n.VerbForms{
        "machen": {Past: "gemacht", Gerund: "machend"},
    },
})

Performance

Grammar results are computed on-demand but templates are cached:

  • First call: Parse template + apply grammar
  • Subsequent calls: Reuse cached template

The template cache uses sync.Map for thread-safe concurrent access.