provisioning/docs/src/architecture/adr/adr-018-help-system-fluent-integration.md
2026-01-14 01:56:30 +00:00

9.2 KiB

ADR-018: Help System Fluent Integration & Data-Driven Architecture

Status: Proposed Date: 2026-01-13 Author: Architecture Team Supersedes: Hardcoded help strings in main_provisioning/help_system.nu

Context

The current help system in main_provisioning/help_system.nu (1303 lines) consists almost entirely of hardcoded string concatenation with embedded ANSI formatting codes:

def help-infrastructure [] {
    print "╔════════════════════════════════════════════════════╗"
    print "║   SERVER & INFRASTRUCTURE                          ║"
    print "╚════════════════════════════════════════════════════╝"
}

Current Problems:

  1. No Internationalization: Help text trapped in English-only code
  2. Hard to Maintain: Updating text requires editing Nushell code
  3. Mixed Concerns: Content (strings) mixed with presentation (ANSI codes)
  4. No Hot-Reload: Changes require recompilation
  5. Difficult to Test: String content buried in function definitions

Problem Statement

Metrics:

  • 1303 lines of code-embedded help text
  • 17 help categories with 65 strings total
  • All help functions manually maintained
  • No separation of data from presentation

Decision

Implement Data-Driven Help with Mozilla Fluent Integration:

  1. Extract help content to Fluent files (.ftl format)
  2. Support multilingual help (English base, Spanish translations)
  3. Implement runtime language resolution via LANG environment variable
  4. Reduce help_system.nu to wrapper functions only

Architecture

Help Content (Fluent Files)
  ├─ en-US/help.ftl (65 strings - English base)
  └─ es-ES/help.ftl (65 strings - Spanish translations)

Language Detection & Loading
  ├─ Check LANG environment variable
  ├─ Load appropriate Fluent file
  └─ Implement fallback chain (es-ES → en-US)

Help System Wrapper
  ├─ help-main [] - Display main menu
  ├─ help-infrastructure [] - Infrastructure category
  ├─ help-orchestration [] - Orchestration category
  └─ help-setup [] - Setup category

User Interface
  ├─ LANG=en_US provisioning help infrastructure
  └─ LANG=es_ES provisioning help infrastructure

Implementation

1. Fluent File Structure

en-US/help.ftl:

help-main-title = PROVISIONING SYSTEM
help-main-subtitle = Layered Infrastructure Automation
help-main-categories = COMMAND CATEGORIES
help-main-categories-hint = Use 'provisioning help <category>' for details
help-main-infrastructure-name = infrastructure
help-main-infrastructure-desc = Server, taskserv, cluster, VM, and infra management
help-main-orchestration-name = orchestration
help-main-orchestration-desc = Workflow, batch operations, and orchestrator control
help-infrastructure-title = SERVER & INFRASTRUCTURE
help-infra-server = Server Operations
help-infra-server-create = Create a new server
help-infra-server-list = List all servers
help-infra-server-status = Show server status
help-infra-taskserv = TaskServ Management
help-infra-taskserv-create = Deploy taskserv to server
help-infra-cluster = Cluster Management
help-infra-vm = Virtual Machine Operations
help-orchestration-title = ORCHESTRATION & WORKFLOWS
help-orch-control = Orchestrator Management
help-orch-start = Start orchestrator [--background]
help-orch-workflows = Single Task Workflows
help-orch-batch = Multi-Provider Batch Operations

es-ES/help.ftl (Spanish translations):

help-main-title = SISTEMA DE PROVISIÓN
help-main-subtitle = Automatización de Infraestructura por Capas
help-main-categories = CATEGORÍAS DE COMANDOS
help-main-categories-hint = Use 'provisioning help <categoría>' para más detalles
help-main-infrastructure-name = infraestructura
help-main-infrastructure-desc = Gestión de servidores, taskserv, clusters, VM e infraestructura
help-main-orchestration-name = orquestación
help-main-orchestration-desc = Flujos de trabajo, operaciones por lotes y control del orquestador
help-infrastructure-title = SERVIDOR E INFRAESTRUCTURA
help-infra-server = Operaciones de Servidor
help-infra-server-create = Crear un nuevo servidor
help-infra-server-list = Listar todos los servidores
help-infra-server-status = Mostrar estado del servidor
help-infra-taskserv = Gestión de TaskServ
help-infra-taskserv-create = Desplegar taskserv en servidor
help-infra-cluster = Gestión de Clusters
help-infra-vm = Operaciones de Máquinas Virtuales
help-orchestration-title = ORQUESTACIÓN Y FLUJOS DE TRABAJO
help-orch-control = Gestión del Orquestador
help-orch-start = Iniciar orquestador [--background]
help-orch-workflows = Flujos de Trabajo de Tarea Única
help-orch-batch = Operaciones por Lotes Multi-Proveedor

2. Fluent Loading in Nushell

def load-fluent-file [category: string] {
    let lang = ($env.LANG? | default "en_US" | str replace "_" "-")
    let fluent_path = $"provisioning/locales/($lang)/help.ftl"

    # Parse Fluent file and extract strings for category
    # Fallback to en-US if lang not available
}

3. Help System Wrapper

export def help-infrastructure [] {
    let strings = (load-fluent-file "infrastructure")

    # Apply formatting and render
    print $"╔════════════════════════════════════════════════════╗"
    print $"║   ($strings.title | str upcase)                   ║"
    print $"╚════════════════════════════════════════════════════╝"
}

Consequences

Positive

  • Internationalization Ready: Easy to add new languages (Portuguese, French, Japanese)
  • Data/Presentation Separation: Content in Fluent, formatting in Nushell
  • Maintainability: Edit Fluent files, not Nushell code
  • Hot-Reload Support: Can update help text without recompilation
  • Testing: Help content testable independently from rendering
  • Code Reduction: 1303 lines → ~50 lines (wrapper) + ~700 lines (Fluent data)

Negative

  • Tool Complexity: Need Fluent parser and loader
  • Fallback Chain Management: Must handle missing translations gracefully
  • Performance: File I/O for loading translations (mitigated by caching)

Integration Strategy

Phase 1: Infrastructure & Extraction

  • Create provisioning/locales/ directory structure
  • Create i18n-config.toml with locale configuration
  • Extract strings to en-US/help.ftl (65 strings)
  • Create Spanish translations es-ES/help.ftl

Phase 2: Integration (This Task)

  • Modify help_system.nu to load from Fluent
  • Implement language detection ($env.LANG)
  • Implement fallback chain logic
  • Test with LANG=en_US and LANG=es_ES

Phase 3: Validation & Documentation

  • Comprehensive integration tests
  • Performance benchmarks
  • Documentation for adding new languages
  • Examples in provisioning/docs/

Language Resolution Flow

1. Check LANG environment variable
   LANG=es_ES.UTF-8 → extract "es_ES" or "es-ES"

2. Check if locale file exists
   provisioning/locales/es-ES/help.ftl exists? → YES

3. Load locale file
   Parse and extract help strings

4. On missing key:
   Check fallback chain in i18n-config.toml
   es-ES → en-US

5. Render with formatting
   Apply ANSI codes, boxes, alignment

Testing Strategy

Unit Tests

# Test language detection
LANG=en_US provisioning help infrastructure
# Expected: English output

LANG=es_ES provisioning help infrastructure
# Expected: Spanish output

LANG=fr_FR provisioning help infrastructure
# Expected: Fallback to English (fr-FR not available)

File Structure

provisioning/
├── locales/
│   ├── i18n-config.toml           # Locale metadata & fallback chains
│   ├── en-US/
│   │   └── help.ftl               # 65 English help strings
│   └── es-ES/
│       └── help.ftl               # 65 Spanish help strings
└── core/nulib/main_provisioning/
    └── help_system.nu             # ~50 lines (wrapper only)

Configuration

i18n-config.toml defines:

[locales]
default = "en-US"
fallback = "en-US"

[locales.en-US]
name = "English (United States)"

[locales.es-ES]
name = "Spanish (Spain)"

[fallback_chains]
es-ES = ["en-US"]
  • ADR-010: Configuration Format Strategy
  • ADR-011: Nickel Migration
  • ADR-013: TypeDialog Integration (forms also use Fluent)

Open Questions

  1. Should help strings support Fluent attributes for metadata?
  2. Should we implement Fluent caching for performance?
  3. How do we handle dynamic help (commands not in Fluent)?
  4. Should help system auto-update when Fluent files change?

References