9.2 KiB
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:
- No Internationalization: Help text trapped in English-only code
- Hard to Maintain: Updating text requires editing Nushell code
- Mixed Concerns: Content (strings) mixed with presentation (ANSI codes)
- No Hot-Reload: Changes require recompilation
- 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:
- Extract help content to Fluent files (
.ftlformat) - Support multilingual help (English base, Spanish translations)
- Implement runtime language resolution via
LANGenvironment variable - 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.tomlwith 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.nuto load from Fluent - Implement language detection (
$env.LANG) - Implement fallback chain logic
- Test with
LANG=en_USandLANG=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"]
Related ADRs
- ADR-010: Configuration Format Strategy
- ADR-011: Nickel Migration
- ADR-013: TypeDialog Integration (forms also use Fluent)
Open Questions
- Should help strings support Fluent attributes for metadata?
- Should we implement Fluent caching for performance?
- How do we handle dynamic help (commands not in Fluent)?
- Should help system auto-update when Fluent files change?
References
- Mozilla Fluent: https://projectfluent.org/
- Fluent Syntax: https://projectfluent.org/fluent/guide/
- Nushell 0.109 Guidelines:
.claude/guidelines/nushell.md - Current Help Implementation:
provisioning/core/nulib/main_provisioning/help_system.nu - Fluent Files:
provisioning/locales/{en-US,es-ES}/help.ftl