cli/docs/plans/2026-01-30-i18n-v2-design.md
Snider a93cc3540a feat(plugin): add Claude Code plugin for host-uk framework
Core plugin providing:
- Skills: core CLI reference, PHP patterns, Go patterns
- Commands: /core:remember for context persistence
- Hooks:
  - PreToolUse: block dangerous commands (rm -rf, sed -i, grep -l |)
  - PreToolUse: enforce core CLI over raw go/php commands
  - PostToolUse: auto-format Go/PHP, check for debug statements
  - PostToolUse: warn about uncommitted work after git commit
  - PreCompact: save state to prevent amnesia after auto-compact
  - SessionStart: restore context from recent sessions (<3h)
- MCP: core CLI server integration

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-31 10:27:04 +00:00

3.7 KiB

i18n Package Refactor Design

Goal

Refactor pkg/i18n to be extensible without breaking changes in future. Based on Gemini review recommendations.

File Structure

Renamed/Merged

Current New Reason
interfaces.go types.go Contains types, not interfaces
mutate.go loader.go Loads/flattens JSON
actions.go hooks.go Missing key callbacks
checks.go (merge into loader.go) Loading helpers
mode.go (merge into types.go) Just one type

New Files

File Purpose
handler.go KeyHandler interface + built-in handlers
context.go TranslationContext + C() helper

Unchanged

grammar.go, language.go, localise.go, debug.go, numbers.go, time.go, i18n.go, intents.go, compose.go, transform.go

Interfaces

KeyHandler

// KeyHandler processes translation keys before standard lookup.
type KeyHandler interface {
    Match(key string) bool
    Handle(key string, args []any, next func() string) string
}

Built-in handlers:

  • LabelHandler - i18n.label.* → "Status:"
  • ProgressHandler - i18n.progress.* → "Building..."
  • CountHandler - i18n.count.* → "5 files"
  • NumericHandler - i18n.numeric.* → formatted numbers
  • DoneHandler - i18n.done.* → "File deleted"
  • FailHandler - i18n.fail.* → "Failed to delete file"

Loader

// Loader provides translation data to the Service.
type Loader interface {
    Load(lang string) (map[string]Message, *GrammarData, error)
    Languages() []string
}

Built-in: FSLoader for embedded/filesystem JSON.

TranslationContext

type TranslationContext struct {
    Context   string
    Gender    string
    Formality Formality
    Extra     map[string]any
}

func C(context string) *TranslationContext

Service Changes

type Service struct {
    loader       Loader
    messages     map[string]map[string]Message
    grammar      map[string]*GrammarData
    currentLang  string
    fallbackLang string
    formality    Formality
    mode         Mode
    debug        bool
    handlers     []KeyHandler
    mu           sync.RWMutex
}

Constructors

func New() (*Service, error)
func NewWithLoader(loader Loader, opts ...Option) (*Service, error)

type Option func(*Service)
func WithDefaultHandlers() Option
func WithFallback(lang string) Option
func WithFormality(f Formality) Option

T() Flow

  1. Parse args → extract Context, Subject, data
  2. Run handler chain (each can handle or call next)
  3. Standard lookup with context suffix fallback

Public API

Keep

  • T(key, args...), Raw(key, args...)
  • S(noun, value) - Subject builder
  • SetLanguage(), CurrentLanguage(), SetMode(), CurrentMode()
  • SetFormality(), SetDebug(), Direction(), IsRTL()
  • Grammar: PastTense(), Gerund(), Pluralize(), Article(), Title(), Label(), Progress()

Add

  • C(context) - Context builder
  • NewWithLoader() - Custom loader support
  • AddHandler(), PrependHandler() - Custom handlers

Remove (No Aliases)

  • NewSubject() - use S()
  • N() - use T("i18n.numeric.*")

Breaking Changes

  • Constructor signature changes
  • Internal file reorganisation
  • No backwards compatibility layer

Implementation Order

  1. Create new files (types.go, handler.go, loader.go, context.go, hooks.go)
  2. Move types from interfaces.go → types.go
  3. Implement Loader interface + FSLoader
  4. Implement KeyHandler interface + built-in handlers
  5. Implement TranslationContext
  6. Update Service struct + constructors
  7. Update T() to use handler chain
  8. Update package-level functions in i18n.go
  9. Delete old files
  10. Update tests