282 lines
9.2 KiB
Markdown
282 lines
9.2 KiB
Markdown
|
|
# 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"]
|
||
|
|
```
|
||
|
|
|
||
|
|
## Related ADRs
|
||
|
|
|
||
|
|
- **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
|
||
|
|
|
||
|
|
- Mozilla Fluent: [https://projectfluent.org/](https://projectfluent.org/)
|
||
|
|
- Fluent Syntax: [https://projectfluent.org/fluent/guide/](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`
|
||
|
|
|