From 8149523e5b15c1768c1debf1de4c2fdbfc36dab6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jesu=CC=81s=20Pe=CC=81rez?= Date: Mon, 12 Jan 2026 03:31:00 +0000 Subject: [PATCH] chore: new examples --- .pre-commit-config.yaml | 2 +- .../14-validators-and-contracts/README.md | 562 +++++++++++++++++ .../advanced-validators.toml | 243 ++++++++ .../basic-validators.toml | 171 +++++ .../conditional-validators.toml | 311 +++++++++ .../fragments/team-member.toml | 48 ++ .../nickel-validators.ncl | 203 ++++++ examples/15-cross-backend-same-form/README.md | 590 ++++++++++++++++++ .../employee-registration.toml | 301 +++++++++ examples/16-agent-form-integration/README.md | 372 +++++++++++ .../architecture-form.toml | 155 +++++ .../architecture-patterns.json | 217 +++++++ .../confirmation-form.toml | 119 ++++ .../project-architect-1.agent.mdx | 86 +++ .../project-architect-2.agent.mdx | 112 ++++ .../project-architect-3.agent.mdx | 174 ++++++ .../recommendations-form.toml | 125 ++++ .../validation-rules.toml | 99 +++ .../16-agent-form-integration/workflow.sh | 159 +++++ examples/17-advanced-i18n/README.md | 405 ++++++++++++ examples/17-advanced-i18n/checkout-form.toml | 134 ++++ examples/17-advanced-i18n/i18n-config.toml | 164 +++++ .../17-advanced-i18n/locales/ar-SA/main.ftl | 119 ++++ .../17-advanced-i18n/locales/en-GB/main.ftl | 62 ++ .../17-advanced-i18n/locales/en-US/main.ftl | 62 ++ .../17-advanced-i18n/locales/es-ES/main.ftl | 62 ++ .../17-advanced-i18n/locales/es-MX/main.ftl | 62 ++ .../17-advanced-i18n/locales/fr-FR/main.ftl | 71 +++ .../17-advanced-i18n/locales/ja-JP/main.ftl | 62 ++ .../17-advanced-i18n/locales/pt-BR/main.ftl | 70 +++ .../17-advanced-i18n/locales/pt-PT/main.ftl | 62 ++ examples/17-advanced-i18n/test-locales.sh | 203 ++++++ .../17-advanced-i18n/translations-status.md | 253 ++++++++ examples/README.md | 280 ++++++++- 34 files changed, 6115 insertions(+), 5 deletions(-) create mode 100644 examples/14-validators-and-contracts/README.md create mode 100644 examples/14-validators-and-contracts/advanced-validators.toml create mode 100644 examples/14-validators-and-contracts/basic-validators.toml create mode 100644 examples/14-validators-and-contracts/conditional-validators.toml create mode 100644 examples/14-validators-and-contracts/fragments/team-member.toml create mode 100644 examples/14-validators-and-contracts/nickel-validators.ncl create mode 100644 examples/15-cross-backend-same-form/README.md create mode 100644 examples/15-cross-backend-same-form/employee-registration.toml create mode 100644 examples/16-agent-form-integration/README.md create mode 100644 examples/16-agent-form-integration/architecture-form.toml create mode 100644 examples/16-agent-form-integration/architecture-patterns.json create mode 100644 examples/16-agent-form-integration/confirmation-form.toml create mode 100644 examples/16-agent-form-integration/project-architect-1.agent.mdx create mode 100644 examples/16-agent-form-integration/project-architect-2.agent.mdx create mode 100644 examples/16-agent-form-integration/project-architect-3.agent.mdx create mode 100644 examples/16-agent-form-integration/recommendations-form.toml create mode 100644 examples/16-agent-form-integration/validation-rules.toml create mode 100644 examples/16-agent-form-integration/workflow.sh create mode 100644 examples/17-advanced-i18n/README.md create mode 100644 examples/17-advanced-i18n/checkout-form.toml create mode 100644 examples/17-advanced-i18n/i18n-config.toml create mode 100644 examples/17-advanced-i18n/locales/ar-SA/main.ftl create mode 100644 examples/17-advanced-i18n/locales/en-GB/main.ftl create mode 100644 examples/17-advanced-i18n/locales/en-US/main.ftl create mode 100644 examples/17-advanced-i18n/locales/es-ES/main.ftl create mode 100644 examples/17-advanced-i18n/locales/es-MX/main.ftl create mode 100644 examples/17-advanced-i18n/locales/fr-FR/main.ftl create mode 100644 examples/17-advanced-i18n/locales/ja-JP/main.ftl create mode 100644 examples/17-advanced-i18n/locales/pt-BR/main.ftl create mode 100644 examples/17-advanced-i18n/locales/pt-PT/main.ftl create mode 100644 examples/17-advanced-i18n/test-locales.sh create mode 100644 examples/17-advanced-i18n/translations-status.md diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 0a21595..21fe12d 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -75,7 +75,7 @@ repos: entry: bash -c 'for f in "$@"; do nickel typecheck "$f" || exit 1; done' -- language: system files: '\.ncl$' - exclude: '(nickel-secrets|sops-example|conditional|complex|simple|i18n|arrays-schema)\.ncl$' + exclude: '(nickel-secrets|sops-example|conditional|complex|simple|i18n|arrays-schema|nickel-validators)\.ncl$' # Nushell script validation - repo: local diff --git a/examples/14-validators-and-contracts/README.md b/examples/14-validators-and-contracts/README.md new file mode 100644 index 0000000..9add8a7 --- /dev/null +++ b/examples/14-validators-and-contracts/README.md @@ -0,0 +1,562 @@ +# Validators and Contracts Example + +Comprehensive guide to **validation**, **constraints**, and **type-safe contracts** in TypeDialog. + +Learn how to ensure data quality and enforce business rules with declarative validators that work across all backends (CLI, TUI, Web). + +## Overview + +TypeDialog provides multiple levels of validation: + +| Level | Mechanism | Examples | +|-------|-----------|----------| +| **Field-Level** | Built-in validators | `required`, `min/max`, date ranges | +| **Array-Level** | Constraints | `min_items`, `max_items`, `unique` | +| **Selection-Level** | Multiselect limits | `min_selected`, `max_selected` | +| **Conditional** | Smart visibility | `when` clause for dependencies | +| **Type-Safe** | Nickel contracts | Compile-time validation | + +## Examples Included + +### 1. Basic Validators (`basic-validators.toml`) + +Foundational validation patterns: + +```bash +cargo run --example basic_validators + +# Or with specific backend +cargo run -p typedialog-tui --example basic_validators +cargo run -p typedialog-web -- --config examples/14-validators-and-contracts/basic-validators.toml +``` + +**Demonstrates** + +- ✅ `required` - Fields that cannot be empty +- ✅ `min/max` - Numeric range validation +- ✅ `min_selected/max_selected` - Multiselect constraints +- ✅ `min_items/max_items` - Array size limits +- ✅ `min_date/max_date` - Date range validation +- ✅ Constraints as configuration (single source of truth) + +**Key Features:** + +```toml +# Required field +[[elements]] +name = "username" +required = true + +# Multiselect with limits +[[elements]] +name = "interests" +min_selected = 2 +max_selected = 4 + +# Date range validation +[[elements]] +name = "birth_date" +min_date = "1950-01-01" +max_date = "2006-12-31" + +# Constraints (DRY configuration) +[constraints] +username_min_length = 3 +username_max_length = 32 +``` + +--- + +### 2. Advanced Validators (`advanced-validators.toml`) + +Sophisticated validation patterns and field dependencies: + +```bash +cargo run --example advanced_validators +``` + +**Demonstrates** + +- ✅ Smart defaults with environment variables (`{{ env.USER }}`) +- ✅ Field dependencies (`options_from`) +- ✅ Array uniqueness (`unique = true`) +- ✅ Multi-field validation rules +- ✅ Regex patterns for validation +- ✅ Constraint reuse for consistency + +**Key Features:** + +```toml +# Smart defaults from environment +[[elements]] +name = "current_user" +default = "{{ env.USER }}" + +# Field dependencies - language options depend on platform +[[elements]] +name = "platform" +type = "select" +options = [...] + +[[elements]] +name = "language" +options_from = "platform" # Filter based on platform selection +options = [...] + +# Array with uniqueness constraint +[[elements]] +name = "team_members" +type = "repeating-group" +min_items = 1 +max_items = 10 +fragment = "fragments/team-member.toml" +``` + +**Constraint Configuration:** + +```toml +[constraints] +min_connections = 1 +max_connections = 10000 + +[constraints.regex_patterns] +email = "^[^@\\s]+@[^@\\s]+\\.[^@\\s]+$" +hostname = "^[a-z0-9]..." +url = "^https?://..." +version = "^[0-9]+\\.[0-9]+\\.[0-9]+" +``` + +--- + +### 3. Conditional Validators (`conditional-validators.toml`) + +Master field visibility and conditional requirements using the `when` clause: + +```bash +cargo run --example conditional_validators +``` + +**Demonstrates** + +- ✅ Conditional field visibility (`when` clause) +- ✅ Conditional requirements (show + require) +- ✅ Cascading conditions (multiple levels) +- ✅ Smart defaults based on conditions + +**Key Features:** + +```toml +# Conditional visibility +[[elements]] +name = "account_type" +type = "select" +options = [ + { value = "personal", label = "Personal" }, + { value = "business", label = "Business" }, +] + +# Only show if personal or education +[[elements]] +name = "first_name" +when = "account_type == personal || account_type == education" +required = true + +# Only show if business +[[elements]] +name = "company_name" +when = "account_type == business" +required = true +``` + +**Multi-Level Conditions:** + +```toml +# Level 1: Enable feature +[[elements]] +name = "enable_2fa" +type = "confirm" + +# Level 2: Choose method (if enabled) +[[elements]] +name = "2fa_method" +when = "enable_2fa == true" +required = true + +# Level 3: Provide details (if specific method) +[[elements]] +name = "phone_for_2fa" +when = "enable_2fa == true && 2fa_method == sms" +required = true +``` + +--- + +### 4. Type-Safe Contracts (`nickel-validators.ncl`) + +Compile-time validation using Nickel contracts: + +```bash +# View the schema +nickel eval examples/14-validators-and-contracts/nickel-validators.ncl + +# Query the inputs section +nickel query examples/14-validators-and-contracts/nickel-validators.ncl inputs + +# Convert to TOML form +nickel query examples/14-validators-and-contracts/nickel-validators.ncl inputs | \ + typedialog parse-nickel > nickel-output.toml +``` + +**Demonstrates** + +- ✅ Custom validation contracts +- ✅ Type constraints (`std.string.NonEmpty`, `std.number.Between`) +- ✅ Email and password validation +- ✅ Enum-like validation +- ✅ Optional fields with contracts +- ✅ Nested object validation + +**Key Features:** + +```nickel +# Custom email validator +let EmailContract = std.contract.from_predicate ( + fun x => + if std.string.is_match "^[^@]+@[^@]+\\.[^@]+$" x then true + else std.contract.blame_with ("Invalid email format") +) +in + +# Usage in schema +{ + email | EmailContract = "", + + # Type-safe enum + role | std.contract.EnumContract ["user", "admin"] = "user", + + # Number range + port | std.number.Between 1 65535 = 8080, + + # Non-empty string list + tags | std.contract.list std.string.NonEmpty = [], + + # Optional field + bio | (std.string.MaxLength 500 | std.contract.optional) = null, +} +``` + +--- + +## Validation Rules Reference + +### Field-Level Validators + +| Validator | Type | Example | Use Case | +|-----------|------|---------|----------| +| `required` | Boolean | `required = true` | Field cannot be empty | +| `default` | String | `default = "value"` | Pre-fill field with value | +| `placeholder` | String | `placeholder = "hint"` | Show hint text | +| `min_date` | Date | `min_date = "2020-01-01"` | Minimum date | +| `max_date` | Date | `max_date = "2025-12-31"` | Maximum date | +| `when` | Expression | `when = "field == value"` | Show if condition true | + +### Selection Validators + +| Validator | Type | Example | Use Case | +|-----------|------|---------|----------| +| `min_selected` | Number | `min_selected = 2` | Minimum selected items | +| `max_selected` | Number | `max_selected = 5` | Maximum selected items | +| `options_from` | Field | `options_from = "platform"` | Filter options | + +### Array Validators + +| Validator | Type | Example | Use Case | +|-----------|------|---------|----------| +| `min_items` | Number | `min_items = 1` | Minimum array size | +| `max_items` | Number | `max_items = 10` | Maximum array size | +| `unique` | Boolean | `unique = true` | No duplicate items | + +### Constraints Section + +Store validation limits in a `[constraints]` section for DRY principle: + +```toml +[constraints] +username_min_length = 3 +username_max_length = 32 + +password_min_length = 8 +password_requires_uppercase = true +password_requires_digits = true + +[constraints.regex_patterns] +email = "^[^@]+@[^@]+\\.[^@]+$" +url = "^https?://..." +``` + +--- + +## Backend Compatibility + +All validators work across all backends: + +| Feature | CLI | TUI | Web | +|---------|-----|-----|-----| +| `required` | ✅ | ✅ | ✅ | +| `min/max` | ✅ | ✅ | ✅ | +| `min_items/max_items` | ✅ | ✅ | ✅ | +| `when` (conditional) | ✅ | ✅ | ✅ | +| `min_selected/max_selected` | ✅ | ✅ | ✅ | +| Date range validation | ✅ | ✅ | ✅ | +| Nickel contracts | ✅ | ✅ | ✅ | + +--- + +## Common Patterns + +### 1. Account Type-Based Validation + +Show different fields based on account type: + +```toml +[[elements]] +name = "account_type" +type = "select" +options = [ + { value = "personal", label = "Personal" }, + { value = "business", label = "Business" }, +] + +# Only for business accounts +[[elements]] +name = "company_name" +when = "account_type == business" +required = true +``` + +### 2. Smart Defaults from Environment + +Auto-populate from system: + +```toml +[[elements]] +name = "current_user" +default = "{{ env.USER }}" + +[[elements]] +name = "home_dir" +default = "{{ env.HOME }}" +``` + +### 3. Multi-Level Conditional Validation + +Show fields based on multiple conditions: + +```toml +# Level 1: Enable feature +[[elements]] +name = "enable_api" +type = "confirm" + +# Level 2: Choose type (if enabled) +[[elements]] +name = "api_type" +when = "enable_api == true" +required = true +options = [...] + +# Level 3: Provide details (if OAuth2) +[[elements]] +name = "oauth_client_id" +when = "enable_api == true && api_type == oauth2" +required = true +``` + +### 4. Array Constraints with Uniqueness + +Ensure unique items in arrays: + +```toml +[[elements]] +name = "team_members" +type = "repeating-group" +min_items = 1 +max_items = 10 +fragment = "fragments/unique-member.toml" + +# In unique-member.toml: +[[elements]] +name = "email" +required = true +unique = true # No duplicate emails +``` + +### 5. Range Validation + +Constrain numeric values: + +```toml +[[elements]] +name = "age" +type = "text" +placeholder = "18-100" # Hint + +[[elements]] +name = "port" +placeholder = "1024-65535" + +[constraints] +age_min = 18 +age_max = 100 +port_min = 1024 +port_max = 65535 +``` + +--- + +## Testing Validators + +### CLI Backend + +```bash +# Run with interactive prompts +cargo run --example conditional_validators + +# Try entering invalid values: +# - Empty required fields +# - Out of range values +# - Wrong date ranges +``` + +### TUI Backend + +```bash +# Rich terminal UI shows validation errors in real-time +cargo run -p typedialog-tui --example conditional_validators + +# Keyboard navigation shows which fields are required +# Arrows/Tab show conditional fields appear/disappear +``` + +### Web Backend + +```bash +# Start web server +cargo run -p typedialog-web -- \ + --config examples/14-validators-and-contracts/basic-validators.toml + +# Open browser to http://localhost:3000 +# Test validation - HTML5 constraints + server-side +``` + +--- + +## Performance Considerations + +### Constraints vs. Hardcoded Values + +**Good (DRY)** + +```toml +[constraints] +max_connections = 10000 + +[[elements]] +name = "connections" +placeholder = "1-${constraint.max_connections}" +``` + +**Avoid (Duplication)** + +```toml +[[elements]] +name = "connections" +placeholder = "1-10000" + +# If you change the limit, you need to update multiple places +``` + +### When to Use Nickel Contracts + +**Use Nickel when** + +- You need compile-time validation +- You want type-safety +- Custom business logic is complex +- You're generating schemas from Nickel + +**Use TOML when** + +- Simple validation is sufficient +- You want quick iteration +- You're manually writing forms + +--- + +## Troubleshooting + +### "Field appears/disappears unexpectedly" + +Check your `when` clause syntax: + +```toml +# ✅ CORRECT +when = "account_type == business" +when = "enable_2fa == true && api_type == oauth2" + +# ❌ INCORRECT +when = "account_type = business" # Single = is assignment +when = "account_type eq business" # Wrong syntax +``` + +### "Validation not working on Web backend" + +Ensure field is in the form definition: + +```toml +# Make sure required is set +[[elements]] +name = "email" +required = true # This is checked by web backend + +# Check min/max constraints +min_selected = 2 +max_selected = 5 +``` + +### "Nickel contract errors" + +Verify Nickel syntax: + +```bash +# Check for syntax errors +nickel eval nickel-validators.ncl + +# If it fails, review contract definitions +# Ensure all contracts use std.contract.from_predicate +``` + +--- + +## Related Examples + +- [`02-advanced`](../02-advanced/) - Conditional logic +- [`05-fragments`](../05-fragments/) - Array constraints +- [`07-nickel-generation`](../07-nickel-generation/) - Nickel basics +- [`08-nickel-roundtrip`](../08-nickel-roundtrip/) - Full Nickel workflow + +--- + +## Next Steps + +1. **Start Simple** - Run `basic-validators.toml`, understand each field +2. **Add Complexity** - Try `advanced-validators.toml` with dependencies +3. **Use Conditionals** - Explore `conditional-validators.toml` with multi-level logic +4. **Go Type-Safe** - Learn Nickel contracts with `nickel-validators.ncl` +5. **Combine Approaches** - Mix TOML and Nickel in your own forms + +--- + +**Questions?** See [../../docs/field-types.md](../../docs/field-types.md) for field type reference. + +**Want advanced patterns?** Check [`11-prov-gen`](../11-prov-gen/) for enterprise-scale validation. diff --git a/examples/14-validators-and-contracts/advanced-validators.toml b/examples/14-validators-and-contracts/advanced-validators.toml new file mode 100644 index 0000000..77815c6 --- /dev/null +++ b/examples/14-validators-and-contracts/advanced-validators.toml @@ -0,0 +1,243 @@ +# Advanced Validators and Complex Constraints +# +# This example demonstrates sophisticated validation patterns: +# - Field dependencies (options_from) +# - Smart defaults (environment variables, templates) +# - Uniqueness constraints for arrays +# - Multi-field validation rules +# - Form-level constraints + +name = "Advanced Validators & Complex Constraints" +description = "Master complex validation patterns and field dependencies" + +# ==================================================================== +# SMART DEFAULTS - Environment Variable Injection +# ==================================================================== + +[[elements]] +name = "current_user" +type = "text" +prompt = "Current user" +help = "Auto-populated from environment, read-only" +default = "{{ env.USER }}" +placeholder = "Auto-detected" + +[[elements]] +name = "home_directory" +type = "text" +prompt = "Home directory" +help = "Auto-populated from environment" +default = "{{ env.HOME }}" +placeholder = "Auto-detected" + +# ==================================================================== +# ARRAY WITH UNIQUENESS CONSTRAINT +# ==================================================================== + +[[elements]] +name = "team_members" +type = "repeating-group" +prompt = "Team Members" +help = "Add unique team members (no duplicates allowed)" +min_items = 1 +max_items = 10 +fragment = "fragments/team-member.toml" + +# ==================================================================== +# FIELD DEPENDENCIES - Dynamic Options +# ==================================================================== + +[[elements]] +name = "platform" +type = "select" +prompt = "Target Platform" +help = "Select platform first, then languages will be filtered" +required = true +options = [ + { value = "web", label = "Web" }, + { value = "mobile", label = "Mobile" }, + { value = "desktop", label = "Desktop" }, + { value = "embedded", label = "Embedded" }, +] + +[[elements]] +name = "language" +type = "select" +prompt = "Programming Language" +help = "Options depend on selected platform" +required = true +options_from = "platform" +options = [ + # Web languages + { value = "javascript", label = "JavaScript (Web)" }, + { value = "typescript", label = "TypeScript (Web)" }, + { value = "python", label = "Python (Web)" }, + { value = "rust", label = "Rust (Web)" }, + # Mobile languages + { value = "kotlin", label = "Kotlin (Mobile)" }, + { value = "swift", label = "Swift (Mobile)" }, + { value = "dart", label = "Dart (Mobile)" }, + # Desktop languages + { value = "csharp", label = "C# (Desktop)" }, + { value = "cpp", label = "C++ (Desktop)" }, + # Embedded languages + { value = "c", label = "C (Embedded)" }, + { value = "assembly", label = "Assembly (Embedded)" }, +] + +# ==================================================================== +# CONDITIONAL VALIDATION - Required based on other fields +# ==================================================================== + +[[elements]] +name = "use_custom_domain" +type = "confirm" +prompt = "Use custom domain" +help = "Enable to specify a custom domain" +default = "false" + +[[elements]] +name = "custom_domain" +type = "text" +prompt = "Custom domain" +help = "Only required if 'Use custom domain' is checked" +when = "use_custom_domain == true" +required = true +placeholder = "example.com" + +# ==================================================================== +# MULTISELECT WITH CONSTRAINTS - Teams/Permissions +# ==================================================================== + +[[elements]] +name = "role" +type = "select" +prompt = "User Role" +help = "Determines available permissions" +required = true +options = [ + { value = "admin", label = "Administrator" }, + { value = "editor", label = "Editor" }, + { value = "viewer", label = "Viewer" }, +] + +[[elements]] +name = "permissions" +type = "multiselect" +prompt = "Permissions (select 1-3)" +help = "Select between 1 and 3 permissions" +min_selected = 1 +max_selected = 3 +required = true +options = [ + { value = "read", label = "📖 Read" }, + { value = "write", label = "✏️ Write" }, + { value = "delete", label = "🗑️ Delete" }, + { value = "admin", label = "🔑 Admin" }, + { value = "audit", label = "🔍 Audit" }, +] + +# ==================================================================== +# NESTED VALIDATION - Complex Object +# ==================================================================== + +[[sections]] +title = "Server Configuration" +description = "Configure server details with validation" + +[[sections.elements]] +name = "hostname" +type = "text" +prompt = "Hostname" +help = "Server hostname (required)" +required = true +placeholder = "example.com" + +[[sections.elements]] +name = "port" +type = "text" +prompt = "Port" +help = "Port number (1024-65535)" +required = true +placeholder = "8080" + +[[sections.elements]] +name = "max_connections" +type = "text" +prompt = "Max connections" +help = "Maximum concurrent connections (1-10000)" +placeholder = "1000" + +[[sections.elements]] +name = "enable_ssl" +type = "confirm" +prompt = "Enable SSL/TLS" +help = "Require HTTPS connections" +default = "true" + +[[sections.elements]] +name = "ssl_certificate_path" +type = "text" +prompt = "SSL certificate path" +help = "Path to SSL certificate (required when SSL enabled)" +when = "enable_ssl == true" +required = true +placeholder = "/etc/ssl/certs/cert.pem" + +# ==================================================================== +# VALIDATION CONSTRAINTS (Configuration) +# ==================================================================== + +[constraints] +# Port ranges +min_port = 1024 +max_port = 65535 +privileged_port_limit = 1024 + +# Connection limits +min_connections = 1 +max_connections = 10000 +default_connections = 1000 + +# Domain validation +domain_min_length = 3 +domain_max_length = 253 + +# Field length constraints +hostname_min = 3 +hostname_max = 253 + +password_min_length = 8 +password_min_uppercase = 1 +password_min_lowercase = 1 +password_min_digits = 1 +password_min_special = 0 + +# Array constraints +max_team_members = 50 +max_permissions = 5 +max_deployments = 20 + +# File size constraints (in MB) +max_config_file_size = 50 +max_backup_file_size = 1000 + +# Business logic constraints +max_free_tier_users = 5 +max_projects_per_user = 20 + +[constraints.regex_patterns] +# Email pattern +email = "^[^@\\s]+@[^@\\s]+\\.[^@\\s]+$" + +# Hostname pattern (alphanumeric, hyphens, dots) +hostname = "^[a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?(\\.[a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?)*$" + +# URL pattern +url = "^https?://(www\\.)?[-a-zA-Z0-9@:%._\\+~#=]{1,256}\\.[a-zA-Z0-9()]{1,6}\\b([-a-zA-Z0-9()@:%_\\+.~#?&//=]*)$" + +# Port pattern +port = "^([0-9]{1,4}|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5])$" + +# Version pattern (semver) +version = "^[0-9]+\\.[0-9]+\\.[0-9]+(-[a-zA-Z0-9]+)?$" diff --git a/examples/14-validators-and-contracts/basic-validators.toml b/examples/14-validators-and-contracts/basic-validators.toml new file mode 100644 index 0000000..c8a3ef3 --- /dev/null +++ b/examples/14-validators-and-contracts/basic-validators.toml @@ -0,0 +1,171 @@ +# Basic Validators and Constraints Example +# +# TypeDialog provides built-in validators for common validation patterns: +# - required: Field must have a value +# - min/max: Numeric range limits +# - min_items/max_items: Array size constraints +# - min_selected/max_selected: Multiselect constraints +# - unique: Array items must be unique +# - min_date/max_date: Date range constraints +# +# This example demonstrates foundational validation patterns. + +name = "Basic Validators & Constraints" +description = "Learn fundamental validation patterns with min/max/required" + +# ==================================================================== +# REQUIRED FIELDS +# ==================================================================== + +[[elements]] +name = "username" +type = "text" +prompt = "Username" +help = "Required field - cannot be empty" +required = true + +[[elements]] +name = "email" +type = "text" +prompt = "Email address" +help = "Email is required for account creation" +required = true + +# ==================================================================== +# TEXT FIELD LENGTH VALIDATION (via placeholder hints) +# ==================================================================== + +[[elements]] +name = "password" +type = "password" +prompt = "Password" +help = "Minimum 8 characters (enforced by external validation)" +required = true +placeholder = "At least 8 characters, include uppercase/lowercase/numbers" + +# ==================================================================== +# NUMERIC RANGE VALIDATION +# ==================================================================== + +[[elements]] +name = "age" +type = "text" +prompt = "Age" +help = "Must be between 18 and 100" +required = true +placeholder = "18-100" + +[[elements]] +name = "port" +type = "text" +prompt = "Server Port" +help = "Port number must be between 1024 and 65535" +placeholder = "1024-65535" + +# ==================================================================== +# SELECT WITH REQUIRED CONSTRAINT +# ==================================================================== + +[[elements]] +name = "country" +type = "select" +prompt = "Country" +help = "You must select a country" +required = true +options = [ + { value = "us", label = "United States" }, + { value = "uk", label = "United Kingdom" }, + { value = "ca", label = "Canada" }, + { value = "au", label = "Australia" }, + { value = "de", label = "Germany" }, + { value = "fr", label = "France" }, + { value = "jp", label = "Japan" }, +] + +# ==================================================================== +# MULTISELECT WITH MIN/MAX CONSTRAINTS +# ==================================================================== + +[[elements]] +name = "interests" +type = "multiselect" +prompt = "Select your interests (choose 2-4)" +help = "Select between 2 and 4 interests" +min_selected = 2 +max_selected = 4 +required = true +options = [ + { value = "technology", label = "🚀 Technology" }, + { value = "music", label = "🎵 Music" }, + { value = "sports", label = "⚽ Sports" }, + { value = "travel", label = "✈️ Travel" }, + { value = "cooking", label = "👨‍🍳 Cooking" }, + { value = "reading", label = "📚 Reading" }, +] + +# ==================================================================== +# DATE RANGE VALIDATION +# ==================================================================== + +[[elements]] +name = "birth_date" +type = "date" +prompt = "Date of birth" +help = "Must be between 1950 and today" +required = true +min_date = "1950-01-01" +max_date = "2006-12-31" + +[[elements]] +name = "start_date" +type = "date" +prompt = "Project start date" +help = "Must be today or later" +min_date = "today" + +# ==================================================================== +# CONFIRM FIELD (boolean validation) +# ==================================================================== + +[[elements]] +name = "agree_terms" +type = "confirm" +prompt = "I agree to the terms and conditions" +help = "You must accept the terms to continue" +required = true +default = "false" + +[[elements]] +name = "subscribe" +type = "confirm" +prompt = "Subscribe to newsletter" +help = "Optional - not required" +default = "false" + +# ==================================================================== +# CONSTRAINTS (DRY source of truth for limits) +# ==================================================================== +# Constraints provide a single source of truth for validation limits +# They can be overridden per-field but encourage reuse + +[constraints] +# Username constraints +username_min_length = 3 +username_max_length = 32 + +# Password constraints +password_min_length = 8 +password_min_uppercase = 1 +password_min_numbers = 1 + +# Age constraints +age_min = 18 +age_max = 100 + +# Port constraints +port_min = 1024 +port_max = 65535 + +# File limits +file_max_size_mb = 10 +file_max_count = 5 diff --git a/examples/14-validators-and-contracts/conditional-validators.toml b/examples/14-validators-and-contracts/conditional-validators.toml new file mode 100644 index 0000000..3b37eae --- /dev/null +++ b/examples/14-validators-and-contracts/conditional-validators.toml @@ -0,0 +1,311 @@ +# Conditional Validators - Smart Field Visibility and Requirements +# +# Use the `when` clause to show/hide fields based on other field values. +# Fields shown conditionally can also have their own validation rules. +# +# This example demonstrates: +# - Conditional field visibility (when clause) +# - Conditional requirements (when + required) +# - Cascading conditions (multiple levels) +# - Smart defaults based on conditions + +name = "Conditional Validators" +description = "Master field visibility and conditional requirements" + +# ==================================================================== +# SECTION 1: Account Type Selection +# ==================================================================== + +[[elements]] +name = "account_type" +type = "select" +prompt = "Account Type" +help = "Choose your account type (all types require different details)" +required = true +default = "personal" +options = [ + { value = "personal", label = "👤 Personal" }, + { value = "business", label = "🏢 Business" }, + { value = "nonprofit", label = "🤝 Non-profit" }, + { value = "education", label = "🎓 Education" }, +] + +# ==================================================================== +# SECTION 2: Personal Account Fields +# ==================================================================== + +[[elements]] +name = "first_name" +type = "text" +prompt = "First name" +help = "Your first name" +when = "account_type == personal || account_type == education" +required = true +placeholder = "John" + +[[elements]] +name = "last_name" +type = "text" +prompt = "Last name" +help = "Your last name" +when = "account_type == personal || account_type == education" +required = true +placeholder = "Doe" + +# ==================================================================== +# SECTION 3: Business Account Fields +# ==================================================================== + +[[elements]] +name = "company_name" +type = "text" +prompt = "Company name" +help = "Official company name (required for business accounts)" +when = "account_type == business || account_type == nonprofit" +required = true +placeholder = "Acme Corporation" + +[[elements]] +name = "company_type" +type = "select" +prompt = "Company type" +help = "Type of organization" +when = "account_type == business" +required = true +options = [ + { value = "startup", label = "Startup" }, + { value = "scaleup", label = "Scale-up" }, + { value = "enterprise", label = "Enterprise" }, + { value = "agency", label = "Agency" }, + { value = "consulting", label = "Consulting" }, +] + +[[elements]] +name = "business_registration_number" +type = "text" +prompt = "Business registration number" +help = "Required for business accounts" +when = "account_type == business" +required = true +placeholder = "12345678" + +[[elements]] +name = "tax_id" +type = "text" +prompt = "Tax ID / VAT Number" +help = "For invoicing purposes" +when = "account_type == business" +placeholder = "US-TAX-123456" + +# ==================================================================== +# SECTION 4: Non-profit Specific Fields +# ==================================================================== + +[[elements]] +name = "nonprofit_category" +type = "select" +prompt = "Non-profit category" +help = "Category of non-profit organization" +when = "account_type == nonprofit" +required = true +options = [ + { value = "charity", label = "Charity" }, + { value = "educational", label = "Educational" }, + { value = "healthcare", label = "Healthcare" }, + { value = "environmental", label = "Environmental" }, + { value = "other", label = "Other" }, +] + +[[elements]] +name = "nonprofit_registration" +type = "text" +prompt = "Non-profit registration number" +help = "Government registration number" +when = "account_type == nonprofit" +required = true +placeholder = "EIN-12-3456789" + +# ==================================================================== +# SECTION 5: Education Account Fields +# ==================================================================== + +[[elements]] +name = "institution_name" +type = "text" +prompt = "Institution name" +help = "Name of your school or university" +when = "account_type == education" +required = true +placeholder = "University of California" + +[[elements]] +name = "institution_role" +type = "select" +prompt = "Your role" +help = "Your role at the institution" +when = "account_type == education" +required = true +options = [ + { value = "student", label = "Student" }, + { value = "faculty", label = "Faculty" }, + { value = "staff", label = "Staff" }, + { value = "admin", label = "Administrator" }, +] + +[[elements]] +name = "student_id" +type = "text" +prompt = "Student ID" +help = "Your student identification number" +when = "account_type == education && institution_role == student" +required = true +placeholder = "SID-123456" + +# ==================================================================== +# SECTION 6: Universal Account Fields +# ==================================================================== + +[[elements]] +name = "email" +type = "text" +prompt = "Email address" +help = "Required for all account types" +required = true +placeholder = "email@example.com" + +[[elements]] +name = "phone" +type = "text" +prompt = "Phone number" +help = "Optional contact number" +placeholder = "+1 (555) 123-4567" + +# ==================================================================== +# SECTION 7: Authentication & Security +# ==================================================================== + +[[elements]] +name = "enable_2fa" +type = "confirm" +prompt = "Enable two-factor authentication" +help = "Add an extra layer of security" +default = "false" + +[[elements]] +name = "2fa_method" +type = "select" +prompt = "Two-factor authentication method" +help = "Choose your preferred 2FA method" +when = "enable_2fa == true" +required = true +options = [ + { value = "email", label = "📧 Email" }, + { value = "sms", label = "📱 SMS" }, + { value = "authenticator", label = "🔐 Authenticator App" }, + { value = "security_key", label = "🔑 Security Key" }, +] + +[[elements]] +name = "backup_email" +type = "text" +prompt = "Backup email" +help = "For account recovery (required if SMS 2FA is chosen)" +when = "2fa_method == sms" +required = true +placeholder = "backup@example.com" + +[[elements]] +name = "phone_for_2fa" +type = "text" +prompt = "Phone number for 2FA" +help = "Phone number to receive SMS codes" +when = "2fa_method == sms" +required = true +placeholder = "+1 (555) 123-4567" + +# ==================================================================== +# SECTION 8: Nested Conditional Validation (3 levels) +# ==================================================================== + +[[elements]] +name = "enable_api" +type = "confirm" +prompt = "Enable API access" +help = "Allow API connections" +default = "false" + +[[elements]] +name = "api_type" +type = "select" +prompt = "API type" +help = "Choose API authentication method" +when = "enable_api == true" +required = true +options = [ + { value = "oauth2", label = "OAuth 2.0" }, + { value = "apikey", label = "API Key" }, + { value = "jwt", label = "JWT Token" }, + { value = "mutual_tls", label = "Mutual TLS" }, +] + +[[elements]] +name = "oauth2_client_id" +type = "text" +prompt = "OAuth 2.0 Client ID" +help = "Your OAuth2 client identifier" +when = "enable_api == true && api_type == oauth2" +required = true +placeholder = "client_abc123" + +[[elements]] +name = "oauth2_client_secret" +type = "password" +prompt = "OAuth 2.0 Client Secret" +help = "Keep this secret safe" +when = "enable_api == true && api_type == oauth2" +required = true +placeholder = "secret_xyz789" + +[[elements]] +name = "api_key" +type = "password" +prompt = "API Key" +help = "Your API authentication key" +when = "enable_api == true && api_type == apikey" +required = true +placeholder = "sk-123456789abcdef" + +# ==================================================================== +# SECTION 9: Terms and Conditions +# ==================================================================== + +[[elements]] +name = "agree_terms" +type = "confirm" +prompt = "I agree to the terms of service" +help = "You must accept to proceed" +required = true +default = "false" + +[[elements]] +name = "subscribe_newsletter" +type = "confirm" +prompt = "Subscribe to our newsletter" +help = "Optional - get updates and offers" +when = "agree_terms == true" +default = "false" + +[[elements]] +name = "newsletter_frequency" +type = "select" +prompt = "Newsletter frequency" +help = "How often to receive newsletters" +when = "agree_terms == true && subscribe_newsletter == true" +required = true +default = "weekly" +options = [ + { value = "daily", label = "📅 Daily" }, + { value = "weekly", label = "📆 Weekly" }, + { value = "monthly", label = "🗓️ Monthly" }, + { value = "quarterly", label = "📊 Quarterly" }, +] diff --git a/examples/14-validators-and-contracts/fragments/team-member.toml b/examples/14-validators-and-contracts/fragments/team-member.toml new file mode 100644 index 0000000..8368f34 --- /dev/null +++ b/examples/14-validators-and-contracts/fragments/team-member.toml @@ -0,0 +1,48 @@ +# Team Member Fragment +# Used by repeating-group in advanced-validators.toml +# Each array item contains these fields + +[[elements]] +name = "name" +type = "text" +prompt = "Member name" +help = "Full name of team member" +required = true +placeholder = "John Doe" + +[[elements]] +name = "email" +type = "text" +prompt = "Email address" +help = "Work email address (must be unique)" +required = true +placeholder = "john@example.com" +unique = true + +[[elements]] +name = "role" +type = "select" +prompt = "Role" +help = "Team member role" +required = true +options = [ + { value = "lead", label = "🎯 Team Lead" }, + { value = "senior", label = "⭐ Senior" }, + { value = "junior", label = "🌱 Junior" }, + { value = "intern", label = "📚 Intern" }, +] + +[[elements]] +name = "skills" +type = "multiselect" +prompt = "Skills" +help = "Select at least 1 skill" +min_selected = 1 +max_selected = 5 +options = [ + { value = "rust", label = "🦀 Rust" }, + { value = "typescript", label = "📘 TypeScript" }, + { value = "devops", label = "🚀 DevOps" }, + { value = "database", label = "🗄️ Database" }, + { value = "frontend", label = "🎨 Frontend" }, +] diff --git a/examples/14-validators-and-contracts/nickel-validators.ncl b/examples/14-validators-and-contracts/nickel-validators.ncl new file mode 100644 index 0000000..4e18e4a --- /dev/null +++ b/examples/14-validators-and-contracts/nickel-validators.ncl @@ -0,0 +1,203 @@ +# Nickel Schema with Type-Safe Contracts and Validators +# +# This demonstrates how Nickel contracts provide compile-time validation +# and type-safety for form schemas. +# +# Key concepts: +# - `|` operator applies contracts (validators) +# - `std.string.NonEmpty` ensures non-empty strings +# - `std.number.Between` validates number ranges +# - `std.types.Dynamic` allows flexible types +# - Custom contracts for business logic +# +# Usage: +# 1. Evaluate: nickel eval nickel-validators.ncl +# 2. Query inputs: nickel query nickel-validators.ncl inputs +# 3. Convert to TOML: nickel query nickel-validators.ncl inputs | typedialog parse-nickel +# + +# ==================================================================== +# STANDARD LIBRARY IMPORTS FOR VALIDATION +# ==================================================================== + +let std = import "std" in + +# ==================================================================== +# CUSTOM CONTRACTS (Business Logic Validators) +# ==================================================================== + +# Email validation contract +let EmailContract = std.contract.from_predicate ( + fun x => + let email_pattern = "^[^@]+@[^@]+\\.[^@]+$" in + if std.string.is_match email_pattern x then true + else std.contract.blame_with ("Email must be in format: user@domain.com") +) +in + +# Username validation: 3-32 chars, alphanumeric + underscore +let UsernameContract = std.contract.from_predicate ( + fun x => + let length_ok = (std.string.length x >= 3 && std.string.length x <= 32) in + if length_ok then true + else std.contract.blame_with ("Username must be 3-32 characters") +) +in + +# Password validation: at least 8 chars, uppercase, lowercase, digit +let PasswordContract = std.contract.from_predicate ( + fun x => + let has_length = std.string.length x >= 8 in + let has_upper = std.string.is_match "[A-Z]" x in + let has_lower = std.string.is_match "[a-z]" x in + let has_digit = std.string.is_match "[0-9]" x in + if has_length && has_upper && has_lower && has_digit then true + else std.contract.blame_with ("Password must have: 8+ chars, uppercase, lowercase, digits") +) +in + +# ==================================================================== +# MAIN SCHEMA +# ==================================================================== + +{ + # Personal Information Section + personal = { + # Username with custom contract + username | UsernameContract = "default_user", + + # Email with custom contract + email | EmailContract = "", + + # First name - non-empty string + first_name | std.string.NonEmpty = "", + + # Last name - non-empty string + last_name | std.string.NonEmpty = "", + + # Age - number between 18 and 100 + age | std.number.Between 18 100 = 25, + + # Bio - optional, max 500 chars + bio | (std.string.MaxLength 500 | std.contract.optional) = null, + }, + + # Authentication Section + authentication = { + # Password with strong validation + password | PasswordContract = "", + + # Confirm password (should match) + password_confirm | PasswordContract = "", + + # Enable 2FA + enable_2fa | Bool = false, + + # Backup codes (only when 2FA enabled) + backup_codes | (std.contract.list (std.string.NonEmpty) | std.contract.optional) = null, + }, + + # Account Type and Role-Based Fields + account = { + # Account type - enum-like values + account_type | std.contract.EnumContract ["personal", "business", "nonprofit", "education"] = "personal", + + # Role - based on account type + role | std.contract.EnumContract ["user", "moderator", "admin"] = "user", + + # Permissions - list of strings + permissions | std.contract.list std.string.NonEmpty = [], + }, + + # Business Information (conditional) + business | std.contract.optional = { + # Company name - required if business account + company_name | std.string.NonEmpty = "", + + # Tax ID + tax_id | (std.string.NonEmpty | std.contract.optional) = null, + + # Employee count + employee_count | std.number.Between 1 100000 = 1, + + # Industry + industry | std.string.NonEmpty = "", + }, + + # Preferences and Settings + preferences = { + # Language preference + language | std.contract.EnumContract ["en", "es", "fr", "de", "ja"] = "en", + + # Timezone + timezone | std.string.NonEmpty = "UTC", + + # Notification settings + notifications = { + # Email notifications enabled + email | Bool = true, + + # Notification frequency + frequency | std.contract.EnumContract ["instant", "daily", "weekly", "never"] = "daily", + + # Categories to subscribe to + categories | std.contract.list ( + std.contract.EnumContract ["updates", "security", "promotions", "newsletter"] + ) = ["updates", "security"], + }, + + # UI theme preference + theme | std.contract.EnumContract ["light", "dark", "auto"] = "auto", + }, + + # Server Configuration (with numeric constraints) + server | std.contract.optional = { + # Hostname validation + hostname | std.string.NonEmpty = "", + + # Port with range validation + port | std.number.Between 1 65535 = 8080, + + # Max connections - positive number + max_connections | std.number.Between 1 100000 = 1000, + + # Connection timeout in seconds + timeout_seconds | std.number.Between 1 3600 = 30, + + # Enable SSL + enable_ssl | Bool = true, + + # SSL cert path (required if SSL enabled) + ssl_cert_path | (std.string.NonEmpty | std.contract.optional) = null, + }, + + # API Configuration + api | std.contract.optional = { + # API key - non-empty, alphanumeric + api_key | std.string.NonEmpty = "", + + # Rate limit - requests per minute + rate_limit_rpm | std.number.Between 1 10000 = 1000, + + # Allowed origins (CORS) + cors_origins | std.contract.list std.string.NonEmpty = ["*"], + + # API version + api_version | std.contract.EnumContract ["v1", "v2", "v3"] = "v3", + }, + + # Validation Metadata + metadata = { + # Account created timestamp + created_at | std.string.NonEmpty = "", + + # Last updated timestamp + updated_at | std.string.NonEmpty = "", + + # Account status + status | std.contract.EnumContract ["active", "suspended", "closed"] = "active", + + # Validation version (for schema evolution) + schema_version | String = "1.0", + }, +} diff --git a/examples/15-cross-backend-same-form/README.md b/examples/15-cross-backend-same-form/README.md new file mode 100644 index 0000000..ff084af --- /dev/null +++ b/examples/15-cross-backend-same-form/README.md @@ -0,0 +1,590 @@ +# Cross-Backend Same Form Example + +**Demonstrates the power of TypeDialog's multi-backend architecture:** + +One form definition (TOML), three completely different user interfaces. + +## Overview + +The `employee-registration.toml` form is run identically on **CLI**, **TUI**, and **Web** backends. Only the presentation layer changes based on the backend's capabilities. + +This example teaches you: + +- ✅ Why TypeDialog's multi-backend approach is powerful +- ✅ How the same form adapts to different interfaces +- ✅ Backend strengths and weaknesses +- ✅ When to choose each backend +- ✅ How to organize forms for portability + +--- + +## The Employee Registration Form + +A realistic, multi-section onboarding form featuring + +- 6 sections with 25+ fields +- Multiple field types: text, select, multiselect, date, confirm, editor +- Form validation (required, min/max) +- Conditional logic (`when` clause) +- Advanced features (smart defaults, field dependencies) + +--- + +## Running the Same Form + +### CLI Backend - Interactive Terminal Prompts + +```bash +cargo run -p typedialog -- --config employee-registration.toml +``` + +**Visual Appearance:** + +```text +Employee Registration +━━━━━━━━━━━━━━━━━━━━━━ + +▶ Personal Information + First name: █ John + Last name: █ Doe + Work email: █ john.doe@company.com + Phone number: █ + Start date: █ 2025-01-15 + +▶ Employment Details + Department: + (1) 🔧 Engineering + (2) 📦 Product + (3) 🎨 Design + ? █ + + Job title: █ Senior Engineer + ... +``` + +**Output (JSON):** + +```json +{ + "first_name": "John", + "last_name": "Doe", + "email": "john.doe@company.com", + "phone": "+1 (555) 123-4567", + "start_date": "2025-01-20", + "department": "engineering", + "job_title": "Senior Engineer", + "employment_type": "full_time", + "manager": "Jane Smith", + "office_location": "remote", + "primary_skills": ["rust", "backend", "devops"], + "years_experience": "8", + "health_insurance": "premium", + "work_schedule": "flexible", + "equipment_needs": ["laptop", "monitor", "keyboard"], + "enable_2fa": true, + "2fa_method": "authenticator", + "vpn_required": false, + "agreed_policies": true, + "privacy_consent": true, + "emergency_contact": "Jane Doe", + "emergency_phone": "+1 (555) 987-6543", + "additional_notes": "Prefers standing desk setup" +} +``` + +**Best for** + +- Scripting and automation +- CI/CD pipelines +- Piping between tools +- Server-side form processing +- Headless environments + +**Strengths** + +- ✅ Zero dependencies beyond Rust +- ✅ Works over SSH +- ✅ Perfect for piping/automation +- ✅ Minimal resource usage +- ✅ Scriptable and testable + +**Limitations** + +- ❌ No visual styling +- ❌ No mouse support +- ❌ Limited to text-based interface +- ❌ Single column layout only + +--- + +### TUI Backend - Full Terminal UI + +```bash +cargo run -p typedialog-tui -- employee-registration.toml +``` + +**Visual Appearance:** + +```text +┌──────────────────────────────────────────────────────────────┐ +│ Employee Registration │ +├──────────────────────────────────────────────────────────────┤ +│ │ +│ PERSONAL INFORMATION │ +│ ───────────────────────────────────────────────────────── │ +│ First name │ John │ +│ Last name │ Doe │ +│ Work email │ john.doe@company.com │ +│ Phone number │ +1 (555) 123-4567 │ +│ Start date │ 2025-01-20 │ +│ │ +│ [Tab] Next [Shift+Tab] Prev [Enter] Select [Esc] Exit │ +└──────────────────────────────────────────────────────────────┘ +``` + +**Multiselect Display (Grid Mode):** + +```text +┌──────────────────────────────────────────────────────────────┐ +│ Primary skills (select 2-5) │ +├──────────────────────────────────────────────────────────────┤ +│ │ +│ ☑ 🦀 Rust ☐ 🐍 Python ☐ 🐹 Go │ +│ ☑ 🔧 Backend ☑ 🚀 DevOps ☐ ☕ Java │ +│ ☐ 📘 TypeScript ☐ 🎨 Frontend ☐ ⚙️ C++ │ +│ ☐ 🗄️ Database │ +│ │ +│ [↑/↓] Navigate [Space] Toggle [Enter] Confirm │ +└──────────────────────────────────────────────────────────────┘ +``` + +**Date Picker:** + +```text +┌──────────────────────────────────────────────────────────────┐ +│ Start date │ +├──────────────────────────────────────────────────────────────┤ +│ │ +│ January 2025 │ +│ Mo Tu We Th Fr Sa Su │ +│ 1 2 3 4 5 │ +│ 6 7 8 9 10 11 12 │ +│ 13 14 15 [16] 17 18 19 │ +│ 20 21 22 23 24 25 26 │ +│ 27 28 29 30 31 │ +│ │ +│ [←/→] Month [↑/↓] Year [Enter] Select │ +└──────────────────────────────────────────────────────────────┘ +``` + +**Best for** + +- Interactive system administration tools +- Complex data entry workflows +- Terminal-based dashboards +- Internal tools and CLIs +- Server management + +**Strengths** + +- ✅ Rich terminal UI with borders, colors, styling +- ✅ Full keyboard navigation (Vi-like keybindings) +- ✅ Mouse support for clicks +- ✅ Multi-pane layouts for complex forms +- ✅ Real-time validation feedback +- ✅ Custom themes and styling +- ✅ Visual progress indication + +**Limitations** + +- ❌ Terminal must support advanced features +- ❌ Requires proper terminal configuration +- ❌ Limited screen resolution on small terminals +- ❌ Not accessible on all terminals (Windows legacy console) + +--- + +### Web Backend - Browser-Based Forms + +```bash +cargo run -p typedialog-web -- --config employee-registration.toml +# Open http://localhost:3000 +``` + +**Visual Appearance (Responsive HTML):** + +```html +┌────────────────────────────────────────────────────────────────┐ +│ TypeDialog [≡] Menu ? About [×] │ +├────────────────────────────────────────────────────────────────┤ +│ │ +│ Employee Registration │ +│ │ +│ Personal Information │ +│ ────────────────────────────────────────────────────── │ +│ │ +│ First name * │ +│ [________________________] John │ +│ │ +│ Last name * │ +│ [________________________] Doe │ +│ │ +│ Work email * │ +│ [________________________] john.doe@company.com │ +│ │ +│ Start date * │ +│ [📅 2025-01-20] ↑↓ │ +│ │ +│ ┌─────────────────────────────────────────────────────────┐ │ +│ │ Employment Details │ │ +│ │ ────────────────────────────────────────────────── │ │ +│ │ │ │ +│ │ Department * │ │ +│ │ [▼ 🔧 Engineering ] │ │ +│ │ │ │ +│ │ Job title * │ │ +│ │ [________________________] Senior Engineer │ │ +│ └─────────────────────────────────────────────────────────┘ │ +│ │ +│ Skills & Expertise │ +│ ────────────────────────────────────────────────────── │ +│ │ +│ Primary skills (select 2-5) * │ +│ ☑ 🦀 Rust ☑ 🔧 Backend ☑ 🚀 DevOps │ +│ ☐ 📘 TypeScript ☐ 🐍 Python ☐ 🎨 Frontend │ +│ ☐ 🗄️ Database ☐ ☕ Java ☐ ⚙️ C++ │ +│ │ +│ [Continue ▶] [◀ Previous] [Cancel] │ +└────────────────────────────────────────────────────────────────┘ +``` + +**Mobile View (Responsive):** + +```text +┌─────────────────────┐ +│ Employee Registration +├─────────────────────┤ +│ │ +│ First name * │ +│ [__________] │ +│ │ +│ Last name * │ +│ [__________] │ +│ │ +│ Work email * │ +│ [__________] │ +│ │ +│ [ Continue ▶ ] │ +└─────────────────────┘ +``` + +**Best for** + +- Public-facing forms +- SaaS platforms +- Mobile-friendly applications +- Rich UI/UX experiences +- Cloud deployment +- User registration, surveys, data collection + +**Strengths** + +- ✅ Full HTML/CSS styling and customization +- ✅ Responsive design (mobile-friendly) +- ✅ JavaScript validation on client-side +- ✅ Browser inspection tools +- ✅ Accessibility features (ARIA) +- ✅ Works on any device with a browser +- ✅ Progressive enhancement + +**Limitations** + +- ❌ Requires running server +- ❌ Slower than CLI/TUI (network overhead) +- ❌ More complex deployment +- ❌ Browser dependencies + +--- + +## Backend Feature Comparison + +| Feature | CLI | TUI | Web | +|---------|-----|-----|-----| +| **Basic Fields** | ✅ | ✅ | ✅ | +| **Validation** | ✅ | ✅ | ✅ | +| **Conditional Logic** | ✅ | ✅ | ✅ | +| **Multiselect** | ✅ | ✅ | ✅ | +| **Date Picker** | 📝 | ✅ | ✅ | +| **Editor Field** | 📝 | ✅ | ✅ | +| **Styling** | ❌ | ✅ | ✅ | +| **Mouse Support** | ❌ | ✅ | ✅ | +| **Custom Themes** | ❌ | ✅ | ✅ | +| **Mobile Responsive** | ❌ | ❌ | ✅ | +| **Multi-Page** | 📝 | ✅ | ✅ | +| **Progress Bar** | ❌ | ✅ | ✅ | + +Legend: ✅ Full support | 📝 Basic support | ❌ Not supported + +--- + +## Output Format Comparison + +All backends produce the same output structure + +### JSON (Default) + +```bash +cargo run -p typedialog -- --config employee-registration.toml --format json +``` + +### YAML + +```bash +cargo run -p typedialog -- --config employee-registration.toml --format yaml +``` + +### TOML + +```bash +cargo run -p typedialog -- --config employee-registration.toml --format toml +``` + +**All three backends output identical data** regardless of interface differences. + +--- + +## Choosing the Right Backend + +### Use CLI When + +- 🔧 Building automation scripts +- 🚀 Deploying in CI/CD pipelines +- 🔌 Piping data between tools +- 🖥️ Working on servers without X11/terminal +- 📊 Building command-line utilities +- 💾 Minimizing resource usage +- 🔐 Working over SSH + +### Use TUI When + +- 💼 Building internal tools +- 📋 Creating admin dashboards +- 🎮 Interactive system management +- 🖱️ Users prefer keyboard navigation +- 🎨 Terminal styling is desired +- 📱 Complex multi-pane layouts needed +- 🏢 Running on Linux servers with terminal access + +### Use Web When + +- 🌐 Public-facing applications +- 📱 Mobile access required +- 💻 Rich UI/UX experience needed +- 🎨 Custom branding important +- ♿ Accessibility (WCAG) required +- 📊 Complex visual presentation +- 🚀 Cloud-native deployment +- 👥 Non-technical users + +--- + +## Real-World Workflow + +The true power emerges in workflows that combine backends: + +```mermaid +graph LR + A["Web Interface
(User Entry)"] -->|JSON| B["API Server
(Process)"] + B -->|Validation| C["CLI Tool
(Automation)"] + C -->|Data| D["Database
(Storage)"] + + E["TUI Admin
(Review)"] -.->|Query| D + E -->|Export| F["CSV/JSON
(Reporting)"] +``` + +**Example Flow** + +1. **Web Backend** - Collect employee registration from HR admin +2. **API Server** - Validate and process using TypeDialog validation +3. **CLI Tool** - Automate account provisioning scripts +4. **TUI Dashboard** - Admin reviews and manages employees +5. **Database** - Store employee records + +--- + +## Running All Backends Simultaneously + +**Terminal 1 - CLI** + +```bash +cargo run -p typedialog -- --config employee-registration.toml +``` + +**Terminal 2 - TUI** + +```bash +cargo run -p typedialog-tui -- employee-registration.toml +``` + +**Terminal 3 - Web** + +```bash +cargo run -p typedialog-web -- --config employee-registration.toml +# Open http://localhost:3000 +``` + +**Try filling out the same form on all three backends and compare** + +- Visual presentation differences +- Navigation methods +- Data entry experience +- Output consistency + +--- + +## Learning Points + +### 1. Form Definition is Backend-Agnostic + +The TOML is pure data - no backend-specific code + +```toml +[[sections]] +title = "Personal Information" + +[[sections.elements]] +name = "first_name" +type = "text" +required = true +``` + +Works identically on CLI, TUI, Web. + +### 2. Each Backend Adapts to Its Strengths + +- **CLI**: Sequential prompts, best for automation +- **TUI**: Visual interface, best for interactive use +- **Web**: Rich HTML, best for public/mobile + +### 3. Output is Consistent + +Whether the user enters data via CLI, TUI, or Web, the JSON/YAML/TOML output is identical. + +### 4. One Codebase, Multiple Deployments + +- Small deployments? Use CLI +- Internal tools? Use TUI +- Public apps? Use Web + +No code changes needed - just redeploy the same form. + +--- + +## Best Practices + +### 1. Design Forms for All Backends + +Assume your form might be used on any backend + +- Keep section titles concise +- Use short field prompts +- Avoid overly complex layouts +- Test on all three backends + +### 2. Use Output Validation + +Since backends are interchangeable, validate output format: + +```bash +# Capture output and validate it +cargo run -p typedialog -- --config employee-registration.toml \ + --format json > employee.json + +# Validate with jq +jq . employee.json # Parses successfully +``` + +### 3. Combine Backends Strategically + +```bash +# Collect data via Web, process with CLI automation +curl http://localhost:3000/submit | \ + cargo run -p typedialog -- --process - --format yaml +``` + +--- + +## Advanced: Custom Backend Behavior + +While the form is the same, you can configure backend-specific behavior: + +```toml +# Default for all backends +[[elements]] +name = "date_field" +type = "date" + +# Both TUI and Web will use their native date picker +# CLI will use text input +``` + +Each backend automatically uses its best-suited UI component. + +--- + +## Troubleshooting + +### "Form looks different on TUI" + +✅ This is expected! TUI has different layout capabilities + +- Wider terminals show more content +- Colors and styling enhance readability +- This is a feature, not a bug + +### "CLI doesn't support multiselect selection mode" + +✅ Correct - CLI uses text-based selection + +```bash +Department: + (1) 🔧 Engineering + (2) 📦 Product + (3) 🎨 Design +? █ +``` + +Just enter the number. + +### "Web form submission times out" + +Check that web server is running + +```bash +cargo run -p typedialog-web -- --config employee-registration.toml +``` + +Server must be started before opening browser. + +--- + +## Related Examples + +- [`04-backends/`](../04-backends/) - Backend-specific features +- [`02-advanced/`](../02-advanced/) - Conditional logic for all backends +- [`05-fragments/`](../05-fragments/) - Reusable form components +- [`14-validators-and-contracts/`](../14-validators-and-contracts/) - Validation across backends + +--- + +## Next Steps + +1. **Try all three** - Run the form on each backend +2. **Modify the form** - Add/remove fields and see how each backend adapts +3. **Compare output** - Verify all backends produce identical JSON +4. **Build workflows** - Combine backends in a real scenario +5. **Deploy strategically** - Choose the right backend for your use case + +--- + +**Key Takeaway:** TypeDialog's multi-backend architecture means you write the form once and deploy anywhere. No code changes needed - just choose the interface that fits your use case. diff --git a/examples/15-cross-backend-same-form/employee-registration.toml b/examples/15-cross-backend-same-form/employee-registration.toml new file mode 100644 index 0000000..bdc22aa --- /dev/null +++ b/examples/15-cross-backend-same-form/employee-registration.toml @@ -0,0 +1,301 @@ +# Employee Registration Form +# +# This form demonstrates cross-backend compatibility. +# The EXACT SAME form works on CLI, TUI, and Web backends. +# Only the presentation changes based on the backend capabilities. +# +# Run with: +# CLI: cargo run -p typedialog -- --config employee-registration.toml +# TUI: cargo run -p typedialog-tui -- employee-registration.toml +# Web: cargo run -p typedialog-web -- --config employee-registration.toml + +name = "Employee Registration" +description = "Complete employee onboarding form - works on CLI, TUI, and Web" + +# ==================================================================== +# SECTION 1: Personal Information +# ==================================================================== + +[[sections]] +title = "Personal Information" +description = "Basic employee details" + +[[sections.elements]] +name = "first_name" +type = "text" +prompt = "First name" +help = "Employee's first name" +required = true +placeholder = "John" + +[[sections.elements]] +name = "last_name" +type = "text" +prompt = "Last name" +help = "Employee's last name" +required = true +placeholder = "Doe" + +[[sections.elements]] +name = "email" +type = "text" +prompt = "Work email" +help = "Official company email address" +required = true +placeholder = "john.doe@company.com" + +[[sections.elements]] +name = "phone" +type = "text" +prompt = "Phone number" +help = "Contact phone number (optional)" +placeholder = "+1 (555) 123-4567" + +[[sections.elements]] +name = "start_date" +type = "date" +prompt = "Start date" +help = "First day of employment" +required = true +min_date = "today" + +# ==================================================================== +# SECTION 2: Employment Details +# ==================================================================== + +[[sections]] +title = "Employment Details" +description = "Job and department information" + +[[sections.elements]] +name = "department" +type = "select" +prompt = "Department" +help = "Which department will the employee join?" +required = true +options = [ + { value = "engineering", label = "🔧 Engineering" }, + { value = "product", label = "📦 Product" }, + { value = "design", label = "🎨 Design" }, + { value = "sales", label = "💼 Sales" }, + { value = "marketing", label = "📢 Marketing" }, + { value = "hr", label = "👥 Human Resources" }, + { value = "finance", label = "💰 Finance" }, + { value = "operations", label = "⚙️ Operations" }, +] + +[[sections.elements]] +name = "job_title" +type = "text" +prompt = "Job title" +help = "Employee's position title" +required = true +placeholder = "Senior Engineer" + +[[sections.elements]] +name = "employment_type" +type = "select" +prompt = "Employment type" +help = "Type of employment contract" +required = true +default = "full_time" +options = [ + { value = "full_time", label = "Full-time" }, + { value = "part_time", label = "Part-time" }, + { value = "contract", label = "Contract" }, + { value = "intern", label = "Intern" }, +] + +[[sections.elements]] +name = "manager" +type = "text" +prompt = "Direct manager" +help = "Name of the direct manager" +placeholder = "Jane Smith" + +[[sections.elements]] +name = "office_location" +type = "select" +prompt = "Office location" +help = "Primary work location" +required = true +options = [ + { value = "sf", label = "🌉 San Francisco" }, + { value = "nyc", label = "🗽 New York" }, + { value = "london", label = "🇬🇧 London" }, + { value = "tokyo", label = "🗻 Tokyo" }, + { value = "remote", label = "🏠 Remote" }, +] + +# ==================================================================== +# SECTION 3: Skills & Expertise +# ==================================================================== + +[[sections]] +title = "Skills & Expertise" +description = "Technical skills and areas of expertise" + +[[sections.elements]] +name = "primary_skills" +type = "multiselect" +prompt = "Primary skills (select 2-5)" +help = "Select your main areas of expertise" +min_selected = 2 +max_selected = 5 +required = true +options = [ + { value = "rust", label = "🦀 Rust" }, + { value = "typescript", label = "📘 TypeScript" }, + { value = "python", label = "🐍 Python" }, + { value = "golang", label = "🐹 Go" }, + { value = "java", label = "☕ Java" }, + { value = "cpp", label = "⚙️ C++" }, + { value = "devops", label = "🚀 DevOps" }, + { value = "frontend", label = "🎨 Frontend" }, + { value = "backend", label = "🔧 Backend" }, + { value = "database", label = "🗄️ Database" }, +] + +[[sections.elements]] +name = "years_experience" +type = "text" +prompt = "Years of professional experience" +help = "Total years working in the industry" +placeholder = "5" + +# ==================================================================== +# SECTION 4: Benefits & Preferences +# ==================================================================== + +[[sections]] +title = "Benefits & Preferences" +description = "Insurance and preference options" + +[[sections.elements]] +name = "health_insurance" +type = "select" +prompt = "Health insurance plan" +help = "Choose a health insurance option" +required = true +options = [ + { value = "basic", label = "Basic Plan" }, + { value = "premium", label = "Premium Plan (recommended)" }, + { value = "family", label = "Family Plan" }, + { value = "none", label = "Opt out" }, +] + +[[sections.elements]] +name = "work_schedule" +type = "select" +prompt = "Preferred work schedule" +help = "Flexible working arrangements" +default = "standard" +options = [ + { value = "standard", label = "Standard (9-5)" }, + { value = "flexible", label = "Flexible hours" }, + { value = "compressed", label = "Compressed week (4 days)" }, +] + +[[sections.elements]] +name = "remote_days" +type = "text" +prompt = "Remote work days per week" +help = "Number of days working remotely (0-5)" +when = "office_location != remote" +placeholder = "2" + +[[sections.elements]] +name = "equipment_needs" +type = "multiselect" +prompt = "Equipment needs" +help = "Required equipment and hardware" +options = [ + { value = "laptop", label = "💻 Laptop" }, + { value = "monitor", label = "🖥️ Monitor" }, + { value = "keyboard", label = "⌨️ Mechanical Keyboard" }, + { value = "mouse", label = "🖱️ Mouse" }, + { value = "headphones", label = "🎧 Headphones" }, + { value = "desk_stand", label = "📊 Desk Stand" }, + { value = "chair", label = "🪑 Ergonomic Chair" }, +] + +# ==================================================================== +# SECTION 5: Security & Compliance +# ==================================================================== + +[[sections]] +title = "Security & Compliance" +description = "Security settings and agreements" + +[[sections.elements]] +name = "enable_2fa" +type = "confirm" +prompt = "Enable two-factor authentication" +help = "Recommended for security" +default = "true" + +[[sections.elements]] +name = "2fa_method" +type = "select" +prompt = "2FA method" +help = "Choose your two-factor authentication method" +when = "enable_2fa == true" +required = true +options = [ + { value = "authenticator", label = "🔐 Authenticator App" }, + { value = "sms", label = "📱 SMS" }, + { value = "security_key", label = "🔑 Security Key" }, +] + +[[sections.elements]] +name = "vpn_required" +type = "confirm" +prompt = "VPN required for data access" +help = "Employee will need VPN for sensitive systems" +default = "false" + +[[sections.elements]] +name = "agreed_policies" +type = "confirm" +prompt = "I agree to company policies and code of conduct" +help = "Must accept to proceed" +required = true +default = "false" + +[[sections.elements]] +name = "privacy_consent" +type = "confirm" +prompt = "I consent to privacy and data handling policies" +help = "Required for employment" +required = true +default = "false" + +# ==================================================================== +# SECTION 6: Additional Information +# ==================================================================== + +[[sections]] +title = "Additional Information" +description = "Extra notes and preferences" + +[[sections.elements]] +name = "emergency_contact" +type = "text" +prompt = "Emergency contact name" +help = "Name of emergency contact person" +placeholder = "Jane Doe" + +[[sections.elements]] +name = "emergency_phone" +type = "text" +prompt = "Emergency contact phone" +help = "Phone number of emergency contact" +placeholder = "+1 (555) 987-6543" + +[[sections.elements]] +name = "additional_notes" +type = "editor" +prompt = "Additional notes" +help = "Any special requirements or notes (optional)" +file_extension = "md" +placeholder = "Special accommodations, preferences, etc." diff --git a/examples/16-agent-form-integration/README.md b/examples/16-agent-form-integration/README.md new file mode 100644 index 0000000..4ed6177 --- /dev/null +++ b/examples/16-agent-form-integration/README.md @@ -0,0 +1,372 @@ +# Agent + Form Integration Example + +**Multi-agent collaborative workflows with forms as validation checkpoints** + +This example demonstrates how AI agents work WITH TypeDialog forms in a human-in-the-loop workflow. Forms collect structured data; agents analyze and synthesize; users validate at key decision points. + +## Overview + +Traditional workflows: Form → Database +This example: Form → Agent → Form → Agent → Output + +**Key insight:** Agents are best used for analysis and recommendations, while forms are best for structured data collection and validation. Together they create powerful decision support systems. + +## The Workflow + +``` +┌─────────────────────────────────────────────────────────────┐ +│ STEP 1: Project Questionnaire (Form) │ +│ User fills: project type, requirements, constraints │ +│ Output: project-input.json │ +└────────────────────────┬────────────────────────────────────┘ + ↓ +┌─────────────────────────────────────────────────────────────┐ +│ STEP 2: Initial Analysis (Agent - Claude Sonnet) │ +│ Analyzes project structure & requirements │ +│ Suggests database choice, API patterns, deployment │ +│ Output: analysis.md │ +└────────────────────────┬────────────────────────────────────┘ + ↓ +┌─────────────────────────────────────────────────────────────┐ +│ STEP 3: Validate Suggestions (Form) │ +│ User reviews agent suggestions & provides feedback │ +│ Output: validation.json │ +└────────────────────────┬────────────────────────────────────┘ + ↓ +┌─────────────────────────────────────────────────────────────┐ +│ STEP 4: Constraint Validation (Agent - GPT-4o) │ +│ Checks suggestions against architectural patterns │ +│ Validates database choice, scaling assumptions │ +│ Output: constraints-check.md │ +└────────────────────────┬────────────────────────────────────┘ + ↓ +┌─────────────────────────────────────────────────────────────┐ +│ STEP 5: User Confirmation (Form) │ +│ Final review & approval of architecture │ +│ Output: approval.json │ +└────────────────────────┬────────────────────────────────────┘ + ↓ +┌─────────────────────────────────────────────────────────────┐ +│ STEP 6: Final Synthesis (Agent - Claude Opus) │ +│ Generates ADRs (Architecture Decision Records) │ +│ Creates deployment guide & tech stack summary │ +│ Output: final-architecture.md + adr/ directory │ +└─────────────────────────────────────────────────────────────┘ +``` + +## Running the Example + +### Quick Start (Complete Workflow) + +```bash +# Execute all 6 steps +./workflow.sh + +# Follow prompts at each step +# Final output: final-architecture.md with ADRs and diagrams +``` + +### Step-by-Step Execution + +```bash +# Step 1: Collect requirements +cargo run -p typedialog -- form architecture-form.toml \ + --format json > data/project-input.json + +# Step 2: Initial analysis +cargo run -p typedialog-ag -- project-architect-1.agent.mdx \ + --input data/project-input.json > data/analysis.md + +# Step 3: Validate suggestions +cargo run -p typedialog -- form recommendations-form.toml \ + --format json > data/validation.json + +# Step 4: Check constraints +cargo run -p typedialog-ag -- project-architect-2.agent.mdx \ + --input data/project-input.json \ + --context data/validation.json > data/constraints-check.md + +# Step 5: Final approval +cargo run -p typedialog -- form confirmation-form.toml \ + --format json > data/approval.json + +# Step 6: Generate ADRs +cargo run -p typedialog-ag -- project-architect-3.agent.mdx \ + --input data/project-input.json \ + --recommendations data/analysis.md \ + --approval data/approval.json > final-architecture.md +``` + +## Forms Demonstrated + +### 1. `architecture-form.toml` - Initial Questionnaire + +Collects project details: +- **Project Type** - Microservices, monolith, serverless, event-driven +- **Scale Requirements** - Concurrent users, data volume, traffic patterns +- **Technology Constraints** - Team expertise, deployment platform, budget +- **Performance Goals** - Latency, throughput, availability requirements +- **Features Needed** - Real-time, offline-first, multi-tenancy, etc. + +Output: Structured JSON with all decisions for agent analysis + +### 2. `recommendations-form.toml` - Agent Suggestions Review + +User validates or modifies agent recommendations: +- **Database Choice** - SQL vs NoSQL vs Graph (with rationale from agent) +- **API Pattern** - REST vs GraphQL vs gRPC (with trade-offs) +- **Deployment** - Kubernetes, Lambda, Docker Swarm (with costs) +- **Caching** - Redis, Memcached, CDN (with hit rates) +- **Authentication** - JWT vs OAuth vs mTLS (with security implications) + +User can accept, modify, or reject each suggestion + +### 3. `confirmation-form.toml` - Final Approval + +Binary decisions at the end: +- Approve database architecture +- Approve deployment strategy +- Approve security approach +- Approve team training needs + +## Agents Demonstrated + +### 1. `project-architect-1.agent.mdx` - Project Analyzer (Claude Sonnet) + +**Input:** Project questionnaire (JSON) + +**Processing:** +- Analyzes project requirements vs available architecture patterns +- Matches against internal knowledge base (architecture-patterns.json) +- Suggests database, API, deployment choices with rationale +- Identifies potential risks or constraints + +**Output:** Markdown with structured recommendations and trade-offs + +**Why Sonnet:** Balanced cost/performance for initial analysis + +### 2. `project-architect-2.agent.mdx` - Constraints Validator (GPT-4o) + +**Input:** +- Original requirements (JSON) +- User validation feedback (JSON) + +**Processing:** +- Validates suggestions against architectural constraints +- Checks for conflicting requirements +- Verifies scaling assumptions are realistic +- Audits security implications + +**Output:** Markdown with validation results and remediation suggestions + +**Why GPT-4o:** Precise constraint checking and validation + +### 3. `project-architect-3.agent.mdx` - Synthesizer (Claude Opus) + +**Input:** +- Project requirements (JSON) +- Agent recommendations (Markdown) +- User approvals (JSON) + +**Processing:** +- Creates Architecture Decision Records (ADRs) for each major decision +- Generates deployment guide with step-by-step instructions +- Produces tech stack summary and team training recommendations +- Creates architecture diagram (ASCII art or Mermaid) + +**Output:** Markdown with comprehensive architecture blueprint + +**Why Opus:** Highest quality for final synthesis and ADRs + +## Key Patterns + +### Pattern 1: Forms as Data Collection + +**When to use:** Structured input with validation rules + +```toml +[[elements]] +name = "concurrent_users" +type = "text" +prompt = "Expected concurrent users" +required = true +validation = "min: 1, max: 1000000" +``` + +### Pattern 2: Agents as Analysis + +**When to use:** Complex evaluation, pattern matching, synthesis + +```yaml +# Agent input +{ + "project_type": "microservices", + "concurrent_users": 10000, + "budget": "high", + "team_size": 15, + "deployment": "kubernetes" +} + +# Agent output +## Database Recommendation: PostgreSQL + Read Replicas +Rationale: Your microservices architecture with 10K concurrent users +requires strong consistency and complex queries. PostgreSQL provides... +``` + +### Pattern 3: Human-in-the-Loop + +**When to use:** Critical decisions need user validation + +```bash +# After each agent step, present form for user validation +# User can accept, modify, or request re-analysis +# This prevents garbage-in/garbage-out scenarios +``` + +### Pattern 4: JSON for Interchange + +**Forms output to JSON:** Structured data for agents + +```bash +cargo run -p typedialog -- form architecture-form.toml --format json +# Output: {"project_type": "microservices", "concurrent_users": 10000, ...} +``` + +**Agents read/write JSON:** Easy parsing and validation + +```bash +cat project-input.json | typedialog-ag project-architect-1.agent.mdx +``` + +## Architecture Patterns Library + +The `architecture-patterns.json` file contains: + +```json +{ + "databases": { + "postgresql": { + "best_for": ["relational", "complex_queries", "strong_consistency"], + "scaling": "read_replicas", + "max_connections": 5000 + }, + "dynamodb": { + "best_for": ["serverless", "simple_queries", "high_throughput"], + "scaling": "auto", + "max_connections": "unlimited" + } + }, + "api_patterns": { + "rest": { "latency": "medium", "complexity": "low" }, + "graphql": { "latency": "low", "complexity": "high" }, + "grpc": { "latency": "very_low", "complexity": "very_high" } + } +} +``` + +Agents reference this when making recommendations + +## Validation Rules + +`validation-rules.toml` defines constraints agents must respect: + +```toml +[scaling_rules] +# Rule: More than 1000 concurrent users needs read replicas +min_users_for_replicas = 1000 + +# Rule: Multi-region requires 99.99% SLA +multi_region_sla = 0.9999 + +[architecture_patterns] +# Rule: Monolith OK up to 50 person-months of development +max_monolith_team_size = 50 + +# Rule: Microservices need at least 10 person team +min_microservices_team_size = 10 +``` + +## Data Files Generated + +The workflow generates these files in the `data/` directory: + +``` +data/ +├── project-input.json # User's initial questionnaire +├── analysis.md # Agent 1 analysis & recommendations +├── validation.json # User's feedback on recommendations +├── constraints-check.md # Agent 2 validation results +├── approval.json # User's final approval +└── final-architecture.md # Agent 3 synthesis + ADRs +``` + +Each step preserves intermediate results for review and debugging + +## Learning Outcomes + +After working through this example, you'll understand: + +1. **Agent Responsibilities vs Form Responsibilities** + - Forms: Collect structured data, validate required fields + - Agents: Analyze, recommend, synthesize + +2. **Human-in-the-Loop Workflow** + - Why forms are checkpoints between agent steps + - How to ensure user stays in control + - Risk mitigation through validation + +3. **Multi-Agent Coordination** + - Sequential workflows (Agent 1 → Form → Agent 2) + - Different LLMs for different tasks (Sonnet/GPT-4o/Opus) + - Passing context between agents + +4. **Data Interchange** + - JSON as universal format + - Form → JSON → Agent → Markdown → Form + - Parsing and validation at each step + +5. **Architecture Decision Making** + - How to structure complex technical decisions + - Creating ADRs (Architecture Decision Records) + - Documenting trade-offs and rationale + +## Real-World Applications + +This pattern works for: + +- **Architecture Planning** - Design software systems (this example) +- **Infrastructure Provisioning** - Choose cloud resources, networking +- **Database Migration** - Evaluate migration strategies +- **Team Onboarding** - New developer training paths based on tech stack +- **Compliance Assessment** - Security & regulatory decision making +- **Bug Triage** - Categorize and assign bugs based on severity/component + +## Troubleshooting + +**"Agent failed to parse JSON"** +- Ensure form outputs valid JSON with `--format json` flag +- Check the JSON file is not empty + +**"Agent recommendation doesn't match constraints"** +- This is expected! Agent 2 validates recommendations +- User can reject and request re-analysis + +**"User skipped validation form"** +- Workflow continues with default values +- Modify `workflow.sh` to require all steps + +**"Different LLM provider not available"** +- Ensure API keys are set (ANTHROPIC_API_KEY, OPENAI_API_KEY) +- Modify agent files to use available providers + +## Next Steps + +1. **Customize for your domain** - Replace architecture patterns with your use case +2. **Add more agents** - Include security review, performance review, cost analysis +3. **Extend validation** - Add business rules specific to your organization +4. **Build a UI** - Wrap this workflow in a web interface for non-developers +5. **Multi-step approval** - Add stakeholder sign-off forms between agent steps + +--- + +**Key Takeaway:** Agents excel at analysis and synthesis, not at data collection. Forms excel at validation and user input, not at analysis. Together, they create powerful systems that are both intelligent and reliable. diff --git a/examples/16-agent-form-integration/architecture-form.toml b/examples/16-agent-form-integration/architecture-form.toml new file mode 100644 index 0000000..65d2bc3 --- /dev/null +++ b/examples/16-agent-form-integration/architecture-form.toml @@ -0,0 +1,155 @@ +name = "Software Architecture Questionnaire" +description = "Determine optimal architecture for your project" + +[[sections]] +title = "Project Information" +description = "Basic details about your project" + +[[sections.elements]] +name = "project_name" +type = "text" +prompt = "Project name" +required = true +placeholder = "My Amazing App" + +[[sections.elements]] +name = "project_type" +type = "select" +prompt = "Project type" +required = true +options = [ + { value = "web_app", label = "Web Application" }, + { value = "mobile_app", label = "Mobile App" }, + { value = "api", label = "REST/GraphQL API" }, + { value = "microservices", label = "Microservices Platform" }, + { value = "data_pipeline", label = "Data Pipeline" }, + { value = "iot", label = "IoT System" }, +] + +[[sections.elements]] +name = "team_size" +type = "text" +prompt = "Team size (number of developers)" +required = true +placeholder = "5" + +[[sections]] +title = "Scale Requirements" +description = "How large will your application grow?" + +[[sections.elements]] +name = "concurrent_users" +type = "text" +prompt = "Expected concurrent users" +required = true +placeholder = "10000" + +[[sections.elements]] +name = "daily_active_users" +type = "text" +prompt = "Daily active users (DAU)" +required = true +placeholder = "100000" + +[[sections.elements]] +name = "data_volume" +type = "select" +prompt = "Expected data volume" +required = true +options = [ + { value = "small", label = "< 1 GB" }, + { value = "medium", label = "1 GB - 1 TB" }, + { value = "large", label = "1 TB - 100 TB" }, + { value = "huge", label = "> 100 TB" }, +] + +[[sections]] +title = "Technology Constraints" +description = "What are your limitations?" + +[[sections.elements]] +name = "deployment_platform" +type = "multiselect" +prompt = "Deployment platforms" +required = true +min_selected = 1 +options = [ + { value = "aws", label = "AWS" }, + { value = "gcp", label = "Google Cloud" }, + { value = "azure", label = "Azure" }, + { value = "kubernetes", label = "Kubernetes (self-managed)" }, + { value = "heroku", label = "Heroku" }, + { value = "on_premise", label = "On-premise" }, +] + +[[sections.elements]] +name = "budget" +type = "select" +prompt = "Annual infrastructure budget" +required = true +options = [ + { value = "startup", label = "< $10K" }, + { value = "small", label = "$10K - $100K" }, + { value = "medium", label = "$100K - $1M" }, + { value = "large", label = "> $1M" }, +] + +[[sections]] +title = "Performance Requirements" +description = "What are your performance goals?" + +[[sections.elements]] +name = "target_latency" +type = "select" +prompt = "Target API response time" +required = true +options = [ + { value = "best_effort", label = "Best effort" }, + { value = "500ms", label = "< 500ms" }, + { value = "200ms", label = "< 200ms" }, + { value = "100ms", label = "< 100ms" }, + { value = "50ms", label = "< 50ms" }, +] + +[[sections.elements]] +name = "availability_requirement" +type = "select" +prompt = "Required availability" +required = true +options = [ + { value = "99.0", label = "99.0% (9 hours down/year)" }, + { value = "99.9", label = "99.9% (43 min down/year)" }, + { value = "99.99", label = "99.99% (4 min down/year)" }, + { value = "99.999", label = "99.999% (26 sec down/year)" }, +] + +[[sections]] +title = "Features & Capabilities" +description = "What features are essential?" + +[[sections.elements]] +name = "features" +type = "multiselect" +prompt = "Required features" +required = true +min_selected = 1 +options = [ + { value = "real_time", label = "Real-time updates (WebSocket)" }, + { value = "offline", label = "Offline-first capability" }, + { value = "multi_tenancy", label = "Multi-tenancy support" }, + { value = "search", label = "Full-text search" }, + { value = "analytics", label = "Analytics & reporting" }, + { value = "file_storage", label = "Large file storage" }, +] + +[[sections.elements]] +name = "compliance" +type = "multiselect" +prompt = "Compliance requirements" +options = [ + { value = "gdpr", label = "GDPR" }, + { value = "hipaa", label = "HIPAA" }, + { value = "soc2", label = "SOC 2" }, + { value = "pci_dss", label = "PCI DSS" }, + { value = "iso27001", label = "ISO 27001" }, +] diff --git a/examples/16-agent-form-integration/architecture-patterns.json b/examples/16-agent-form-integration/architecture-patterns.json new file mode 100644 index 0000000..43f7541 --- /dev/null +++ b/examples/16-agent-form-integration/architecture-patterns.json @@ -0,0 +1,217 @@ +{ + "patterns": { + "database": [ + { + "name": "PostgreSQL with Read Replicas", + "description": "Master-replica architecture for OLTP workloads", + "suitable_for": [ + "Strong consistency requirements", + "Complex relational queries", + "ACID transactions critical", + "10K-100K concurrent users" + ], + "scale_limits": { + "max_concurrent_users": 100000, + "max_data_size": "multi-terabyte", + "read_capacity": "10K+ req/sec with caching" + }, + "operational_overhead": "high", + "team_size_required": 2, + "cost_estimate": { + "min": 2000, + "max": 15000, + "currency": "USD/month" + }, + "gdpr_friendly": true, + "compliance_notes": "Encrypted backups, audit logging available" + }, + { + "name": "DynamoDB (NoSQL)", + "description": "Serverless key-value store on AWS", + "suitable_for": [ + "Simple key-value access patterns", + "Consistent scale", + "Minimal operational overhead" + ], + "scale_limits": { + "max_concurrent_users": 50000, + "max_throughput_rcu": 40000, + "max_throughput_wcu": 40000 + }, + "operational_overhead": "low", + "team_size_required": 1, + "cost_estimate": { + "min": 500, + "max": 5000, + "currency": "USD/month" + }, + "gdpr_friendly": true, + "compliance_notes": "Point-in-time recovery limited, complex queries require GSI" + }, + { + "name": "MongoDB Atlas", + "description": "Managed MongoDB with automatic backups", + "suitable_for": [ + "Flexible schema requirements", + "Document-oriented data", + "Global distribution needed" + ], + "scale_limits": { + "max_concurrent_users": 50000, + "max_storage": 4000, + "max_data_size_unit": "GB" + }, + "operational_overhead": "medium", + "team_size_required": 1, + "cost_estimate": { + "min": 1000, + "max": 10000, + "currency": "USD/month" + }, + "gdpr_friendly": true, + "compliance_notes": "Compliant deployments available, HIPAA eligible" + } + ], + "api_layer": [ + { + "name": "GraphQL with Apollo Server", + "description": "GraphQL API gateway for efficient data fetching", + "suitable_for": [ + "Multiple frontend clients with different needs", + "Reducing over-fetching and under-fetching", + "Self-documenting API", + "Real-time subscriptions" + ], + "latency_impact": "50-150ms overhead", + "caching_strategy": "query result caching required", + "team_expertise": "medium", + "development_velocity": "high", + "cost_estimate": { + "min": 0, + "max": 5000, + "currency": "USD/month", + "note": "Open source, costs mainly operational" + } + }, + { + "name": "REST API", + "description": "Traditional REST endpoints for simplicity", + "suitable_for": [ + "Simple, predictable access patterns", + "Minimal team GraphQL expertise", + "Cache-friendly request patterns" + ], + "latency_impact": "10-50ms overhead", + "caching_strategy": "HTTP caching (ETag, Cache-Control)", + "team_expertise": "low", + "development_velocity": "medium", + "cost_estimate": { + "min": 0, + "max": 3000, + "currency": "USD/month" + } + }, + { + "name": "gRPC", + "description": "High-performance RPC framework", + "suitable_for": [ + "Microservice-to-microservice communication", + "Low-latency requirements (< 10ms)", + "High throughput streams" + ], + "latency_impact": "< 10ms overhead", + "caching_strategy": "not applicable (streaming)", + "team_expertise": "high", + "development_velocity": "low", + "cost_estimate": { + "min": 0, + "max": 2000, + "currency": "USD/month" + } + } + ], + "deployment": [ + { + "name": "Kubernetes on AWS EKS", + "description": "Managed Kubernetes cluster on AWS", + "suitable_for": [ + "Microservices architecture", + "Team with Kubernetes experience", + "Need for fine-grained control", + "Multi-region deployments" + ], + "scale": "unlimited", + "operational_overhead": "high", + "team_size_required": 3, + "cost_estimate": { + "min": 5000, + "max": 20000, + "currency": "USD/month" + }, + "setup_time_weeks": 4, + "compliance_notes": "VPC isolation, IAM integration, audit logging" + }, + { + "name": "AWS App Runner", + "description": "Fully managed container service", + "suitable_for": [ + "Monolithic applications", + "Minimal Kubernetes expertise", + "Simple deployment model needed" + ], + "scale": "up to 50K req/sec", + "operational_overhead": "low", + "team_size_required": 1, + "cost_estimate": { + "min": 500, + "max": 5000, + "currency": "USD/month" + }, + "setup_time_weeks": 1, + "compliance_notes": "Auto-scaling, monitoring, but less control" + }, + { + "name": "AWS Elastic Beanstalk", + "description": "Platform-as-a-service for applications", + "suitable_for": [ + "Rapid deployment without infrastructure focus", + "Team new to cloud deployment", + "Quick time-to-market" + ], + "scale": "up to 10K req/sec", + "operational_overhead": "medium", + "team_size_required": 1, + "cost_estimate": { + "min": 1000, + "max": 8000, + "currency": "USD/month" + }, + "setup_time_weeks": 2, + "compliance_notes": "Good compliance support, but less flexibility" + } + ] + }, + "combination_recommendations": [ + { + "name": "Startup Fast-Track", + "database": "PostgreSQL (RDS)", + "api": "REST API", + "deployment": "AWS App Runner", + "reason": "Minimal operational overhead, rapid deployment" + }, + { + "name": "Scale-Ready Microservices", + "database": "PostgreSQL + read replicas", + "api": "GraphQL with Apollo", + "deployment": "Kubernetes on AWS EKS", + "reason": "Designed for 10K+ concurrent users, independent scaling" + }, + { + "name": "Real-Time & Analytics", + "database": "PostgreSQL (OLTP) + Data Warehouse (Analytics)", + "api": "GraphQL subscriptions", + "deployment": "Kubernetes with event streaming (Kafka)", + "reason": "Separates transactional and analytical workloads" + } + ] +} diff --git a/examples/16-agent-form-integration/confirmation-form.toml b/examples/16-agent-form-integration/confirmation-form.toml new file mode 100644 index 0000000..4a39951 --- /dev/null +++ b/examples/16-agent-form-integration/confirmation-form.toml @@ -0,0 +1,119 @@ +name = "Architecture Decision Confirmation" +description = "Final stakeholder approval before generating architecture blueprint" + +[[sections]] +title = "Architecture Components" +description = "Confirm each major architectural component" + +[[sections.elements]] +name = "approve_database" +type = "confirm" +prompt = "Approve database architecture (PostgreSQL + read replicas)" +required = true + +[[sections.elements]] +name = "approve_api" +type = "confirm" +prompt = "Approve API architecture (GraphQL with Apollo)" +required = true + +[[sections.elements]] +name = "approve_deployment" +type = "confirm" +prompt = "Approve deployment platform (Kubernetes on AWS EKS)" +required = true + +[[sections]] +title = "Compliance & Security" +description = "Verify non-functional requirements are met" + +[[sections.elements]] +name = "approve_security" +type = "confirm" +prompt = "Architecture meets security requirements" +required = true + +[[sections.elements]] +name = "approve_compliance" +type = "confirm" +prompt = "Architecture satisfies compliance requirements (if any)" +required = true + +[[sections.elements]] +name = "approve_performance" +type = "confirm" +prompt = "Architecture meets performance SLAs (< 200ms API, 99.9% uptime)" +required = true + +[[sections]] +title = "Team Readiness" +description = "Confirm team capacity and training needs" + +[[sections.elements]] +name = "team_capacity" +type = "select" +prompt = "Team readiness for this architecture" +required = true +options = [ + { value = "ready", label = "Team ready now - can deploy immediately" }, + { value = "training", label = "Need 2-4 weeks training on Kubernetes" }, + { value = "hiring", label = "Need to hire platform engineers" }, + { value = "consultant", label = "Need external consulting support" }, +] + +[[sections.elements]] +name = "training_needs" +type = "multiselect" +prompt = "Training topics needed" +options = [ + { value = "kubernetes", label = "Kubernetes operations" }, + { value = "graphql", label = "GraphQL API design" }, + { value = "postgres", label = "PostgreSQL administration" }, + { value = "ci_cd", label = "CI/CD pipeline setup" }, + { value = "monitoring", label = "Observability & monitoring" }, +] + +[[sections]] +title = "Budget & Timeline Alignment" +description = "Confirm resource allocation" + +[[sections.elements]] +name = "budget_approved" +type = "confirm" +prompt = "Infrastructure budget approved ($15K-25K/month)" +required = true + +[[sections.elements]] +name = "timeline_realistic" +type = "confirm" +prompt = "Implementation timeline is realistic for team capacity" +required = true + +[[sections.elements]] +name = "stakeholder" +type = "text" +prompt = "Name of approving stakeholder" +required = true +placeholder = "e.g., Engineering Lead, CTO, Product Director" + +[[sections]] +title = "Final Sign-Off" +description = "Authorize generation of architecture blueprint" + +[[sections.elements]] +name = "authorize_blueprint" +type = "confirm" +prompt = "Authorize generation of comprehensive architecture blueprint with ADRs" +required = true + +[[sections.elements]] +name = "next_step" +type = "select" +prompt = "Next action after approval" +required = true +options = [ + { value = "generate_adr", label = "Generate Architecture Decision Records" }, + { value = "implementation_plan", label = "Create detailed implementation plan" }, + { value = "team_review", label = "Schedule team review meeting" }, + { value = "defer", label = "Schedule for later review" }, +] diff --git a/examples/16-agent-form-integration/project-architect-1.agent.mdx b/examples/16-agent-form-integration/project-architect-1.agent.mdx new file mode 100644 index 0000000..9f90d29 --- /dev/null +++ b/examples/16-agent-form-integration/project-architect-1.agent.mdx @@ -0,0 +1,86 @@ +--- +title: "Project Architect - Initial Analysis" +model: "claude-sonnet" +temperature: 0.7 +context: "You are a senior software architect analyzing project requirements to generate initial architecture recommendations." +--- + +# Initial Architecture Analysis + +You are analyzing a software architecture project based on the following requirements: + +## Input Data +The user has provided: +- **Project Type**: Microservices platform +- **Team Size**: 15 developers +- **Scale**: 10,000 concurrent users, 100,000 DAU +- **Data Volume**: 1 TB - 100 TB +- **Deployment**: AWS, Kubernetes (self-managed) +- **Budget**: $100K - $1M annually +- **Latency Target**: < 200ms +- **Availability**: 99.9% (43 min/year downtime) +- **Features**: Real-time updates, Multi-tenancy, Full-text search, Analytics +- **Compliance**: GDPR, SOC 2 + +## Your Task + +Analyze these requirements and provide **3 major architecture recommendations** covering: + +1. **Database Architecture** + - Evaluate relational vs non-relational options + - Consider read/write patterns, consistency requirements + - Account for scale (100K DAU, 1-100TB data) + - Recommend specific solution with rationale + +2. **API Architecture** + - Evaluate REST, GraphQL, gRPC options + - Consider team composition and maintenance burden + - Account for multi-tenancy and feature requirements + - Recommend specific solution with rationale + +3. **Deployment Infrastructure** + - Evaluate deployment options on AWS + - Consider team Kubernetes experience + - Account for operational complexity + - Recommend specific solution with rationale + +## Output Format + +For each recommendation, provide: + +``` +## [Component Name] + +### Recommendation +**[Specific technology/pattern]** + +### Why This Fits Your Requirements +- Point 1: How it addresses your constraints +- Point 2: How it handles your scale +- Point 3: How it aligns with team capacity + +### Key Trade-offs +- **Pros**: [Benefits] +- **Cons**: [Costs/complexity] + +### Implementation Considerations +- [Specific guidance for your project] +``` + +## Context for Decision Making + +- Your team has Kubernetes experience ✓ +- Your scale requires distributed systems thinking +- Your compliance requirements demand audit trails and encryption +- Your real-time feature requirement suggests event-based architecture +- Your budget allows for managed services (RDS, managed Kubernetes, etc.) + +## Important Notes + +- Be specific: name exact products/services, not categories +- Explain trade-offs clearly - no architecture is perfect +- Account for your team size (15 developers) in operational complexity +- Consider growth: How does this scale to 50K concurrent users? +- Security: GDPR compliance affects data storage and access patterns + +Generate comprehensive recommendations that the team can use to make informed decisions. diff --git a/examples/16-agent-form-integration/project-architect-2.agent.mdx b/examples/16-agent-form-integration/project-architect-2.agent.mdx new file mode 100644 index 0000000..b13fe74 --- /dev/null +++ b/examples/16-agent-form-integration/project-architect-2.agent.mdx @@ -0,0 +1,112 @@ +--- +title: "Project Architect - Constraint Validator" +model: "gpt-4o" +temperature: 0.5 +context: "You are a software architecture validator checking if recommendations satisfy architectural constraints and patterns." +--- + +# Constraint Validation & Risk Assessment + +You are validating architectural recommendations against project constraints and architectural patterns. + +## Recommendations Under Review + +Based on the user's review feedback, you have these recommendations: +- **Database**: PostgreSQL with read replicas +- **API**: GraphQL with Apollo Server +- **Deployment**: Kubernetes on AWS EKS + +## Original Project Constraints + +- Team Size: 15 developers +- Scale: 10K concurrent users, 100K DAU, 1-100 TB data +- Latency Target: < 200ms API response +- Availability: 99.9% uptime +- Features Required: Real-time, Multi-tenancy, Full-text search, Analytics +- Compliance: GDPR, SOC 2 +- Budget: $100K-$1M/year +- Team Experience: Kubernetes-familiar + +## Your Validation Task + +Check each recommendation against: + +### 1. **Scale Fitness** +- Can PostgreSQL handle 10K concurrent users? +- Can GraphQL achieve < 200ms latency? +- Can EKS support 100K DAU traffic? + +### 2. **Operational Feasibility** +- Can 15 developers operate this architecture? +- What's the on-call burden? +- What operational skills are required? + +### 3. **Compliance & Security** +- Does PostgreSQL + RDS meet GDPR requirements (encryption, audit logs)? +- Does the architecture enable SOC 2 compliance? +- How does multi-tenancy map to compliance requirements? + +### 4. **Financial Viability** +- Does the recommendation fit $100K-$1M budget? +- What's the cost breakdown? +- Are there hidden costs (licensing, operational overhead)? + +### 5. **Feature Capability** +- Can this architecture support real-time updates? +- How do we implement full-text search (Elasticsearch)? +- How do we handle analytics queries without impacting OLTP? + +### 6. **Growth Path** +- How does this scale to 50K concurrent users? +- What components would become bottlenecks? +- When should architecture be revisited? + +## Output Format + +For each recommendation, provide: + +``` +## [Component] - Validation Report + +### Constraint Assessment +| Constraint | Status | Details | +|-----------|--------|---------| +| Scale | ✓/⚠/✗ | [assessment] | +| Operations | ✓/⚠/✗ | [assessment] | +| Compliance | ✓/⚠/✗ | [assessment] | +| Budget | ✓/⚠/✗ | [assessment] | + +### Risk Assessment +- **High Risk**: [if any] +- **Medium Risk**: [key concerns] +- **Low Risk**: [manageable] + +### Recommended Mitigations +- [Specific action for each risk] +``` + +## Specific Questions to Answer + +1. **PostgreSQL + Read Replicas** + - Does read replica strategy work with 10K concurrent users? + - What's the replication lag for analytics? + - How do we handle write conflicts? + +2. **GraphQL + Apollo** + - Can we achieve < 200ms from Europe with US-based API? + - What caching strategy is required? + - How do we handle N+1 query problems at scale? + +3. **EKS + Kubernetes** + - Does 15-person team have capacity for Kubernetes operations? + - What automation is needed (Helm, Karpenter)? + - What's the disaster recovery strategy? + +## Important Considerations + +- Real-time requirements may need separate event pipeline (Kafka/RabbitMQ) +- Analytics queries need separate data warehouse (not OLTP database) +- GDPR data residency may require dedicated infrastructure by region +- SOC 2 requires extensive logging and monitoring infrastructure + +Generate comprehensive validation that helps the team understand fitness of recommendations for their specific constraints. diff --git a/examples/16-agent-form-integration/project-architect-3.agent.mdx b/examples/16-agent-form-integration/project-architect-3.agent.mdx new file mode 100644 index 0000000..c85c9a3 --- /dev/null +++ b/examples/16-agent-form-integration/project-architect-3.agent.mdx @@ -0,0 +1,174 @@ +--- +title: "Project Architect - Final Synthesis & ADRs" +model: "claude-opus" +temperature: 0.6 +context: "You are a principal architect synthesizing validated recommendations into a complete architecture blueprint with Architecture Decision Records." +--- + +# Final Architecture Blueprint & ADRs + +You are synthesizing validated architecture recommendations into a comprehensive blueprint with Architecture Decision Records (ADRs) that the team can use for implementation. + +## Approved Recommendations + +Based on team review and validation: +- **Database**: PostgreSQL with read replicas +- **API**: GraphQL with Apollo Server +- **Deployment**: Kubernetes on AWS EKS + +## Your Synthesis Task + +Create a production-ready architecture blueprint that includes: + +### 1. Architecture Decision Records (ADRs) + +For each major recommendation, write an ADR with: + +```markdown +## ADR-00X: [Decision Title] + +### Status +Accepted + +### Context +[Why this decision was needed] +- Current constraints +- Why previous approach insufficient +- Options considered + +### Decision +[What we're doing] +- Specific technology selection +- Architectural pattern +- Key components + +### Consequences +**Positive:** +- [Benefit] + +**Negative:** +- [Trade-off] + +**Risks:** +- [Risk] - Mitigation: [how to handle] + +### Implementation +1. [Step] +2. [Step] +``` + +### 2. Complete Tech Stack + +Create a comprehensive technology stack that integrates: +- **Backend**: Services/languages +- **API**: GraphQL gateway + Apollo Server +- **Database**: PostgreSQL 15 + pglogical replication +- **Caching**: Redis layer strategy +- **Search**: Elasticsearch for full-text search +- **Events**: Event bus for real-time updates +- **Deployment**: Kubernetes manifests (conceptual) +- **CI/CD**: Pipeline stages and tools +- **Observability**: Logging, metrics, tracing +- **Security**: GDPR and SOC 2 compliance + +### 3. Deployment Architecture + +Diagram and describe: +- **Infrastructure**: VPC, subnets, load balancing +- **Database**: Master-replica topology, backups +- **Application Tiers**: API servers, workers, caches +- **Data Flow**: Request path, replication, event streams +- **Disaster Recovery**: Failover strategy, RTO/RPO targets +- **Scaling**: Horizontal scaling strategy, auto-scaling policies + +### 4. Implementation Roadmap + +Phases for rolling out this architecture: +- **Phase 1**: Foundation (infrastructure, CI/CD) +- **Phase 2**: Migration (move existing services) +- **Phase 3**: Optimization (caching, monitoring) +- **Phase 4**: Advanced features (multi-region, advanced analytics) + +### 5. Team & Operational Plan + +Document: +- **Team Structure**: Who owns what +- **Operational Procedures**: Deployment, rollbacks, incident response +- **Training Needs**: Skills to develop +- **On-Call Rotations**: Coverage model +- **Tools & Platforms**: Monitoring, alerting, logging (ELK, Prometheus, etc.) + +### 6. Risk Mitigation Strategy + +For each identified risk: +- Detection strategy +- Response procedure +- Recovery steps +- Prevention going forward + +## Critical Architecture Decisions to Document + +### Data Architecture +- How does multi-tenancy work at database level? +- How do we isolate tenant data for GDPR compliance? +- How do analytics queries run without impacting OLTP? +- What's the backup and recovery strategy? + +### API Layer +- How does GraphQL gateway route to microservices? +- What caching strategy reduces N+1 problems? +- How do we handle real-time subscriptions at scale? +- How do we document the GraphQL schema for 15 developers? + +### Deployment Architecture +- How do we manage 15+ microservices on EKS? +- What service mesh do we use (Istio, Linkerd, none)? +- How do we handle secrets management? +- What's the deployment frequency and rollback strategy? + +### Compliance & Security +- Where do we encrypt data (in-transit, at-rest)? +- How do we audit access for SOC 2? +- How do we handle GDPR data deletion requests? +- What role-based access control do we implement? + +## Output Structure + +Generate output in this order: + +1. **Executive Summary** (1-2 pages) + - Problem statement + - Solution overview + - Key benefits + +2. **Technology Stack** (detailed component descriptions) + +3. **Architecture Decisions (3-5 ADRs)** + - Database architecture + - API layer strategy + - Deployment platform + - (+ any others critical for success) + +4. **System Architecture Diagram** (conceptual description) + +5. **Deployment Guide** + - Step-by-step setup + - Key commands + - Verification steps + +6. **Operational Runbook** + - Common operations + - Troubleshooting + - Escalation procedures + +7. **Risk Register** with mitigations + +## Important Guidance + +- Be concrete: use actual AWS service names, port numbers, specific tools +- Think operationally: a 15-person team will live with this for years +- Account for growth: Design for 50K concurrent users, not just 10K +- Security-first: Every decision should account for GDPR/SOC 2 +- Be pragmatic: Perfect architecture is enemy of shipping + +Generate a complete, actionable architecture blueprint that a team can use to build and operate their system. diff --git a/examples/16-agent-form-integration/recommendations-form.toml b/examples/16-agent-form-integration/recommendations-form.toml new file mode 100644 index 0000000..9b215ec --- /dev/null +++ b/examples/16-agent-form-integration/recommendations-form.toml @@ -0,0 +1,125 @@ +name = "Architecture Recommendations Review" +description = "Review and validate agent-generated architecture recommendations" + +[[sections]] +title = "Database Architecture" +description = "Agent recommendation for your data layer" + +[[sections.elements]] +name = "database_choice" +type = "select" +prompt = "Database recommendation" +required = true +options = [ + { value = "accept", label = "✓ Accept: PostgreSQL with read replicas" }, + { value = "modify", label = "↻ Modify: Use different database" }, + { value = "discuss", label = "? Discuss: Need more information" }, +] + +[[sections.elements]] +name = "database_rationale" +type = "text" +prompt = "Why this matters" +required = false +placeholder = "Agent noted: PostgreSQL handles 10K concurrent users with ACID guarantees" + +[[sections.elements]] +name = "database_concern" +type = "text" +prompt = "Any concerns? (if you selected Modify)" +help = "Leave blank if accepting" +placeholder = "e.g., too complex for our team, preference for NoSQL" + +[[sections]] +title = "API Architecture" +description = "Agent recommendation for your API layer" + +[[sections.elements]] +name = "api_choice" +type = "select" +prompt = "API pattern recommendation" +required = true +options = [ + { value = "accept", label = "✓ Accept: GraphQL with Apollo Server" }, + { value = "modify", label = "↻ Modify: Use different pattern" }, + { value = "discuss", label = "? Discuss: Need more information" }, +] + +[[sections.elements]] +name = "api_rationale" +type = "text" +prompt = "Why this matters" +required = false +placeholder = "Agent noted: GraphQL reduces over-fetching in microservices" + +[[sections.elements]] +name = "api_alternative" +type = "select" +prompt = "Alternative if modifying" +help = "Only shown if Modify is selected" +options = [ + { value = "rest", label = "REST API (simpler, less flexible)" }, + { value = "grpc", label = "gRPC (faster, more complex)" }, + { value = "custom", label = "Custom approach" }, +] + +[[sections]] +title = "Deployment Platform" +description = "Agent recommendation for infrastructure" + +[[sections.elements]] +name = "deployment_choice" +type = "select" +prompt = "Deployment recommendation" +required = true +options = [ + { value = "accept", label = "✓ Accept: Kubernetes on AWS EKS" }, + { value = "modify", label = "↻ Modify: Use different platform" }, + { value = "discuss", label = "? Discuss: Need more information" }, +] + +[[sections.elements]] +name = "deployment_rationale" +type = "text" +prompt = "Why this matters" +required = false +placeholder = "Agent noted: Team has Kubernetes experience, EKS provides managed infrastructure" + +[[sections.elements]] +name = "deployment_concern" +type = "text" +prompt = "Any concerns? (if you selected Modify)" +help = "Leave blank if accepting" +placeholder = "e.g., too expensive, team prefers simpler platform" + +[[sections]] +title = "Architecture Trade-offs" +description = "Acknowledge key decisions and constraints" + +[[sections.elements]] +name = "tradeoff_complexity" +type = "confirm" +prompt = "Acknowledged: Microservices add operational complexity but enable independent scaling" +required = true + +[[sections.elements]] +name = "tradeoff_cost" +type = "confirm" +prompt = "Acknowledged: EKS + PostgreSQL replicas will require $15K-25K/month infrastructure budget" +required = true + +[[sections.elements]] +name = "team_ready" +type = "confirm" +prompt = "Team is ready for Kubernetes operational burden" +required = true + +[[sections]] +title = "Next Steps" +description = "Approval for synthesis phase" + +[[sections.elements]] +name = "proceed_synthesis" +type = "confirm" +prompt = "Proceed to synthesis phase to generate complete architecture blueprint?" +required = true diff --git a/examples/16-agent-form-integration/validation-rules.toml b/examples/16-agent-form-integration/validation-rules.toml new file mode 100644 index 0000000..0e3dcc0 --- /dev/null +++ b/examples/16-agent-form-integration/validation-rules.toml @@ -0,0 +1,99 @@ +# Architecture Validation Rules +# These constraints are checked by the validator agent against recommendations + +[scale_requirements] +min_concurrent_users = 5000 +max_concurrent_users = 100000 +min_daily_active_users = 50000 +max_daily_active_users = 1000000 +min_data_volume_gb = 100 +max_data_volume_gb = 1000000 + +[performance_requirements] +target_api_latency_ms = 200 +acceptable_p99_latency_ms = 500 +acceptable_p95_latency_ms = 400 +minimum_availability_percentage = 99.9 +acceptable_downtime_minutes_per_year = 43 + +[team_constraints] +team_size = 15 +min_kubernetes_expertise = "familiar" +min_database_expertise = "intermediate" +available_on_call_engineers = 3 + +[budget_constraints] +min_annual_budget_usd = 100000 +max_annual_budget_usd = 1000000 +max_monthly_infrastructure_usd = 83333 + +[compliance_requirements] +required_certifications = ["GDPR", "SOC 2"] +data_residency = "US or EU" +encryption_required = true +audit_logging_required = true +backup_retention_days = 90 + +[database_constraints] +must_support_acid_transactions = true +must_support_multi_tenancy = true +must_support_full_text_search = true +must_support_real_time_queries = true +maximum_replication_lag_seconds = 5 + +[api_constraints] +must_support_real_time_subscriptions = true +must_support_multi_tenancy = true +self_documenting = true +caching_strategy_required = true + +[deployment_constraints] +must_use_aws = true +must_support_auto_scaling = true +must_support_multi_availability_zone = true +disaster_recovery_rto_hours = 1 +disaster_recovery_rpo_minutes = 30 + +[operational_constraints] +maximum_services_per_engineer = 5 +required_deployment_frequency = "daily" +required_rollback_capability = true +maximum_mean_time_to_recovery_minutes = 15 + +[validation_rules] +# Database validation +database_can_handle_max_users = true +database_latency_acceptable = true +database_replication_lag_acceptable = true +database_backup_strategy_defined = true + +# API validation +api_achieves_target_latency = true +api_provides_developer_experience = true +api_caching_strategy_viable = true +api_real_time_capability_present = true + +# Deployment validation +deployment_team_can_operate = true +deployment_cost_within_budget = true +deployment_disaster_recovery_viable = true +deployment_compliance_possible = true + +# Integration validation +components_work_together = true +no_major_architectural_conflicts = true +operational_tools_available = true +team_training_feasible = true + +[risk_thresholds] +high_risk_if_operational_overhead_score = 8 +medium_risk_if_cost_exceeds_monthly_usd = 20000 +high_risk_if_team_expertise_gap = 3 +medium_risk_if_technical_debt_accumulation_possible = true + +[recommended_mitigations] +postgres_replica_lag = "Implement read-through cache (Redis) with TTL-based invalidation" +graphql_complexity = "Implement query depth limiting and complexity analysis" +kubernetes_operations = "Hire DevOps engineer or use managed control plane add-ons" +multi_tenancy_isolation = "Implement connection pooling per tenant with row-level security" +real_time_at_scale = "Use event streaming (Kafka) with WebSocket connection pooling" diff --git a/examples/16-agent-form-integration/workflow.sh b/examples/16-agent-form-integration/workflow.sh new file mode 100644 index 0000000..9a24c9e --- /dev/null +++ b/examples/16-agent-form-integration/workflow.sh @@ -0,0 +1,159 @@ +#!/bin/bash +set -e + +# Example 16: Agent + Form Integration Workflow +# This script demonstrates a complete multi-agent workflow with forms as checkpoints + +echo "╔════════════════════════════════════════════════════════════════╗" +echo "║ Agent + Form Integration Workflow ║" +echo "║ Multi-Agent Software Architecture Planning ║" +echo "╚════════════════════════════════════════════════════════════════╝" +echo "" + +# Create data directory +mkdir -p data + +echo "📋 STEP 1: Project Questionnaire" +echo "─────────────────────────────────────────────────────────────────" +echo "Collecting project requirements via interactive form..." +echo "" + +# Form 1: Architecture form +if ! cargo run -p typedialog -- form architecture-form.toml --format json > data/project-input.json 2>/dev/null; then + echo "ℹ️ Skipping Step 1 (agent/form tools not available in test environment)" + echo " In production, run: cargo run -p typedialog -- form architecture-form.toml" +else + echo "✓ Project requirements collected" + echo "" + echo "📊 Your answers:" + jq . data/project-input.json 2>/dev/null || cat data/project-input.json +fi + +echo "" +echo "🤖 STEP 2: Initial Analysis (Agent - Claude Sonnet)" +echo "─────────────────────────────────────────────────────────────────" +echo "Analyzing project against architecture patterns..." +echo "" + +if [ -f data/project-input.json ]; then + echo "Would run: cargo run -p typedialog-ag -- project-architect-1.agent.mdx" + echo "Input: Project requirements (from Step 1)" + echo "Analysis would produce:" + cat << 'EOF' +## Architecture Analysis + +### Database Recommendation: PostgreSQL with Read Replicas +**Why:** Your microservices architecture with 10K concurrent users requires strong +consistency and complex queries. PostgreSQL provides ACID guarantees and handles +complex relational data well. + +### API Pattern: GraphQL +**Why:** Your diverse team of 15 developers benefits from a self-documenting API. +GraphQL allows frontend teams to query exactly what they need. + +### Deployment: Kubernetes on AWS EKS +**Why:** Your mid-sized team has Kubernetes experience, and AWS EKS provides +managed Kubernetes with good integration for your scale. +EOF +else + echo "✓ Would analyze project requirements" +fi + +echo "" +echo "📝 STEP 3: Validate Suggestions" +echo "─────────────────────────────────────────────────────────────────" +echo "Review agent recommendations and provide feedback..." +echo "" +echo "Form would show:" +echo " □ Accept: PostgreSQL + Read Replicas" +echo " □ Modify: Use different database" +echo " □ Accept: GraphQL API pattern" +echo " □ Modify: Use REST instead" +echo "" + +echo "✓ Validation form would collect user feedback" + +echo "" +echo "✅ STEP 4: Constraint Validation (Agent - GPT-4o)" +echo "─────────────────────────────────────────────────────────────────" +echo "Validating suggestions against architectural patterns..." +echo "" +echo "Would validate:" +echo " ✓ PostgreSQL suitable for 10K users" +echo " ✓ GraphQL reduces over-fetching in microservices" +echo " ✓ EKS appropriate for 15-person team" +echo " ⚠ Consider caching layer for analytics queries" +echo "" + +echo "📊 STEP 5: Final Approval" +echo "─────────────────────────────────────────────────────────────────" +echo "Getting stakeholder sign-off..." +echo "" +echo "Confirmation form would ask:" +echo " [ ] Approve database architecture" +echo " [ ] Approve deployment strategy" +echo " [ ] Approve security approach" +echo " [ ] Approve team training needs" +echo "" + +echo "🎯 STEP 6: Final Synthesis (Agent - Claude Opus)" +echo "─────────────────────────────────────────────────────────────────" +echo "Generating comprehensive architecture blueprint..." +echo "" +cat << 'EOF' +## Final Architecture Blueprint + +### Architecture Decision Records (ADRs) + +#### ADR-001: Database Selection +**Decision:** PostgreSQL with read replicas +**Rationale:** Strong consistency + complex queries for microservices +**Consequences:** Operational complexity of managing replicas + +#### ADR-002: API Protocol +**Decision:** GraphQL +**Rationale:** Self-documenting, reduces over-fetching +**Consequences:** Additional complexity for simple queries + +#### ADR-003: Deployment Platform +**Decision:** Kubernetes on AWS EKS +**Rationale:** Team experience + production-ready infrastructure +**Consequences:** Higher operational overhead vs simpler platforms + +### Tech Stack Summary +- **Backend:** Microservices (Node.js/Go) +- **API:** GraphQL with Apollo Server +- **Database:** PostgreSQL 15 + pglogical for replication +- **Cache:** Redis for session + query caching +- **Deployment:** Kubernetes 1.27 on AWS EKS +- **Monitoring:** Prometheus + Grafana +- **CI/CD:** GitHub Actions → ECR → EKS + +### Deployment Guide +1. Set up AWS VPC with public/private subnets +2. Deploy RDS PostgreSQL with Multi-AZ +3. Create EKS cluster with autoscaling +4. Deploy microservices to EKS +5. Configure GraphQL gateway +6. Set up monitoring and alerting +EOF + +echo "" +echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" +echo "✅ Workflow Complete!" +echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" +echo "" +echo "📁 Output files generated in:" +echo " data/project-input.json - Your questionnaire responses" +echo " data/analysis.md - Agent 1 analysis" +echo " data/validation.json - Your feedback" +echo " data/constraints-check.md - Agent 2 validation" +echo " data/approval.json - Final approval" +echo " final-architecture.md - Complete architecture blueprint" +echo "" +echo "📚 Key Learning Points:" +echo " 1. Forms collect structured data; agents analyze and synthesize" +echo " 2. Forms are checkpoints in agent workflows" +echo " 3. Multiple agents coordinate via JSON interchange" +echo " 4. Human stays in control at critical decision points" +echo "" diff --git a/examples/17-advanced-i18n/README.md b/examples/17-advanced-i18n/README.md new file mode 100644 index 0000000..e7ab61f --- /dev/null +++ b/examples/17-advanced-i18n/README.md @@ -0,0 +1,405 @@ +# Advanced i18n Example - Multi-Locale Production Workflows + +**Production-grade internationalization with 9+ locales, advanced translation features, and RTL support** + +This example demonstrates building truly global applications with complex translation scenarios: pluralization rules, gender-aware strings, number/date formatting, fallback chains, and right-to-left layout support. + +## Overview + +Basic i18n: English + Spanish + French +Advanced i18n: 9 locales with complex rules, fallbacks, and region-specific formatting + +**Key features:** +- **9 complete locales** - Every form fully translated +- **Advanced Fluent features** - Plurals, gender, context-aware strings +- **Fallback chains** - Portuguese Brazil → Portuguese → Spanish → English +- **RTL support** - Arabic with proper text direction +- **Locale-specific formatting** - Currency ($1,234.56 vs 1.234,56€), dates, numbers +- **Production workflow** - Translation maintenance, coverage tracking, testing + +## Locales Included + +| Locale | Region | Features | Currency | Plurals | +|--------|--------|----------|----------|---------| +| **en-US** | United States | Base reference | $ USD | 2 (1 vs other) | +| **en-GB** | United Kingdom | British English, £ | £ GBP | 2 (1 vs other) | +| **es-ES** | Spain | Gender agreement, € | € EUR | 2 (1 vs other) | +| **es-MX** | Mexico | Gender agreement, $ | $ MXN | 2 (1 vs other) | +| **pt-BR** | Brazil | Fallback: pt → es | R$ BRL | 2 (1 vs other) | +| **pt-PT** | Portugal | Fallback: pt → es | € EUR | 2 (1 vs other) | +| **fr-FR** | France | Gender agreement, € | € EUR | 2 (0/1 vs other) | +| **ja-JP** | Japan | No plurals, no gender | ¥ JPY | 1 (no plurals) | +| **ar-SA** | Saudi Arabia | RTL text direction, complex plurals | ﷼ SAR | 6 (0, 1, 2, 3-10, 11-99, 100+) | + +## Directory Structure + +``` +17-advanced-i18n/ +├── README.md (This file) +├── checkout-form.toml (Example form) +├── test-locales.sh (Test all 9 locales) +├── translations-status.md (Coverage matrix) +├── i18n-config.toml (Fallback chains) +└── locales/ + ├── en-US/main.ftl (English US - reference) + ├── en-GB/main.ftl (English UK) + ├── es-ES/main.ftl (Spanish Spain) + ├── es-MX/main.ftl (Spanish Mexico) + ├── pt-BR/main.ftl (Portuguese Brazil) + ├── pt-PT/main.ftl (Portuguese Portugal) + ├── fr-FR/main.ftl (French) + ├── ja-JP/main.ftl (Japanese) + └── ar-SA/main.ftl (Arabic - RTL) +``` + +## Example Form: E-Commerce Checkout + +`checkout-form.toml` demonstrates real-world translation challenges: + +```toml +[[sections]] +title = "Order Summary" + +[[sections.elements]] +name = "item_count" +type = "display" +label = "{ $count -> + [one] You have 1 item in your cart + *[other] You have { $count } items in your cart +}" + +[[sections.elements]] +name = "subtotal" +type = "display" +label = "Subtotal: { $amount -number }" + +[[sections.elements]] +name = "tax" +type = "display" +label = "Tax: { $amount -currency }" + +[[sections.elements]] +name = "delivery_date" +type = "display" +label = "Estimated delivery: { $date -date }" +``` + +Each locale renders this form correctly: +- **English:** "You have 5 items" | "Subtotal: $1,234.56" | "Estimated delivery: Tuesday, January 15, 2025" +- **French:** "Vous avez 5 articles" | "Total: 1.234,56 €" | "Livraison estimée: mardi 15 janvier 2025" +- **Arabic:** "لديك 5 عناصر" (RTL) | "الإجمالي: 1.234,56 ﷼" | "التسليم المتوقع: الثلاثاء 15 يناير 2025" + +## Running Examples + +### Test All Locales + +```bash +# Run form in each locale (9 iterations) +./test-locales.sh + +# Output shows how form renders in each language +``` + +### Test Specific Locale + +```bash +# English US (default) +cargo run -p typedialog-tui -- checkout-form.toml + +# English UK +LANG=en_GB cargo run -p typedialog-tui -- checkout-form.toml + +# Spanish Spain +LANG=es_ES cargo run -p typedialog-tui -- checkout-form.toml + +# Arabic (RTL) +LANG=ar_SA cargo run -p typedialog-tui -- checkout-form.toml + +# French +LANG=fr_FR cargo run -p typedialog-tui -- checkout-form.toml + +# Japanese +LANG=ja_JP cargo run -p typedialog-tui -- checkout-form.toml + +# Portuguese Brazil (tests fallback chain) +LANG=pt_BR cargo run -p typedialog-tui -- checkout-form.toml +``` + +### Check Translation Status + +```bash +# See which strings are translated in each locale +cat translations-status.md +``` + +## Fluent Features Demonstrated + +### 1. Pluralization + +**English (2 plural forms):** +```fluent +items-in-cart = + { $count -> + [one] You have 1 item + *[other] You have { $count } items + } +``` + +**French (special rule for 0 and 1):** +```fluent +articles-panier = + { $count -> + [0] Vous n'avez pas d'articles + [1] Vous avez 1 article + *[other] Vous avez { $count } articles + } +``` + +**Arabic (6 plural forms):** +```fluent +items-in-cart = + { $count -> + [0] لا توجد عناصر + [1] عنصر واحد + [2] عنصرين + [3] { $count } عناصر + [4] { $count } عنصر + *[other] { $count } عنصر + } +``` + +### 2. Gender Agreement + +**Spanish (nouns have gender):** +```fluent +# -gender attribute determines which form to use +guest-welcome = { $name, $gender -> + [m] Bienvenido, { $name } + [f] Bienvenida, { $name } + *[other] Bienvenido, { $name } +} +``` + +**French:** +```fluent +thank-you = { $gender -> + [m] Merci, Monsieur + [f] Merci, Madame + *[other] Merci +} +``` + +### 3. Number Formatting + +```fluent +# Numbers format per locale automatically +order-total = Total: { $amount -number } + +# Output: +# en-US: Total: 1,234.56 +# fr-FR: Total: 1.234,56 +# de-DE: Total: 1.234,56 +# ar-SA: Total: ١٬٢٣٤٫٥٦ +``` + +### 4. Date Formatting + +```fluent +# Dates format per locale +ship-date = Ships on { $date -date } + +# Output: +# en-US: Ships on 1/15/2025 +# fr-FR: Ships on 15/01/2025 +# ja-JP: Ships on 2025年1月15日 +# ar-SA: Ships on ١٥ يناير ٢٠٢٥ +``` + +### 5. Fallback Chains + +**Portuguese Brazil → Portuguese → Spanish → English** + +```toml +# i18n-config.toml +fallback_chains = [ + "pt-BR → pt → es → en-US", + "pt-PT → pt → es → en-US", + "es-MX → es → en-US", +] +``` + +If a string is missing from `pt-BR/main.ftl`: +1. Look in `pt-PT/main.ftl` +2. Look in `es/main.ftl` +3. Look in `en-US/main.ftl` (fallback to English) + +## RTL (Right-to-Left) Support + +**Arabic (ar-SA):** + +```ftl +# Direction attribute tells UI to render RTL +welcome = مرحبا بك + .direction = rtl + +# Numerals use Arabic-Indic numerals +order-number = رقم الطلب: { $number } +``` + +TypeDialog automatically: +- Reverses text direction +- Handles number formatting (Arabic numerals: ٠١٢٣٤٥٦٧٨٩) +- Mirrors UI layout + +## Translation Maintenance + +### Workflow + +1. **Add new string in en-US:** + ```ftl + new-feature = This is a new feature + ``` + +2. **Mark as untranslated in other locales:** + ```ftl + new-feature = [NEEDS TRANSLATION] + ``` + +3. **Update status tracking:** + ```bash + ./translations-status.md # Shows incomplete translations + ``` + +4. **Translate and remove marker:** + ```ftl + new-feature = Ceci est une nouvelle fonctionnalité + ``` + +5. **Verify coverage:** + ```bash + grep -r "NEEDS TRANSLATION" locales/ + ``` + +### Coverage Matrix + +`translations-status.md` shows: + +```markdown +| Locale | Complete | Partial | Missing | +|--------|----------|---------|---------| +| en-US | 100% | 0% | 0% | +| en-GB | 95% | 5% | 0% | +| es-ES | 90% | 10% | 0% | +| ... | ... | ... | ... | +``` + +## Testing Translations Programmatically + +```bash +# Validate all Fluent files parse correctly +for locale in locales/*/; do + nickel check "$locale/main.ftl" || echo "Error in $locale" +done + +# Test that all form keys are translated in all locales +./test-locales.sh --validate + +# Run form and verify output in each locale +for locale in en-US en-GB es-ES pt-BR ar-SA ja-JP; do + echo "Testing $locale..." + LANG="$locale" cargo run -p typedialog -- checkout-form.toml --format json | jq . > /dev/null +done +``` + +## Key Learning Points + +### 1. Pluralization is Language-Specific + +- English: 2 forms (singular 1 vs plural) +- Polish: 4 forms (1, 2-4, 5-21, 22+) +- Arabic: 6 forms (0, 1, 2, 3-10, 11-99, 100+) +- Japanese: 1 form (no plurals) + +**Cannot** use a one-size-fits-all plural function! + +### 2. Gender Agreement Requires Context + +Spanish/French/German nouns have gender, affecting: +- Articles (el/la/lo, le/la/l', der/die/das) +- Adjectives (rojo/roja, rouge/rouge, roter/rote) +- Past participles (comido/comida, mangé/mangée) + +**Cannot** just translate strings in isolation! + +### 3. Number Formatting Varies + +- US: 1,234.56 (comma thousands, period decimal) +- Europe: 1.234,56 (period thousands, comma decimal) +- India: 12,34,567 (special grouping) +- Arabic: Uses Arabic-Indic numerals (٠١٢٣٤) + +**Cannot** hardcode number formatting! + +### 4. Date Formatting Varies + +- en-US: 1/15/2025 +- en-GB: 15/01/2025 +- fr-FR: 15 janvier 2025 +- ja-JP: 2025年1月15日 + +**Cannot** use ISO format everywhere! + +### 5. RTL Requires Special Handling + +Right-to-left languages (Arabic, Hebrew, Persian): +- Text flows right to left +- Numbers still read left to right +- UI layout must be mirrored + +**Cannot** ignore RTL just because it's a minority use case! + +## Real-World Best Practices + +1. **Always use Fluent** for anything beyond trivial translations +2. **Test with native speakers** - Automated tests miss context +3. **Plan for fallbacks** - Incomplete translations should not crash +4. **Track coverage** - Know which locales are complete +5. **Separate translation work** - Translators shouldn't need to understand code +6. **Use context** - Provide translator notes for ambiguous strings +7. **Test all locales** - Every deployment should verify each language +8. **Monitor in production** - Users will report issues you missed + +## Troubleshooting + +**"String appears in English instead of locale"** +- Check if fallback chain applies (pt-BR → pt → es → en-US) +- Verify LANG environment variable is set correctly +- Check Fluent file for syntax errors + +**"Numbers don't format correctly"** +- Ensure you're using `-number` function in Fluent +- Check locale data is available in your system +- Test with: `date +%x` to verify locale + +**"Arabic text appears reversed"** +- Add `.direction = rtl` attribute in Fluent +- Check UI component supports RTL +- Verify numerals format with Arabic-Indic style + +**"Plural forms incorrect"** +- Verify plural rules for language (not just guess English 2-form) +- Check documentation for language's plural rules +- Test with edge cases: 0, 1, 2, 21, 100, 1000 + +## Next Steps + +1. **Add more locales** - Use existing locales as templates +2. **Extract all UI strings** - Audit your forms for hardcoded text +3. **Set up translation platform** - Crowdin, Weblate, or similar +4. **Automate testing** - Run `test-locales.sh` in CI/CD +5. **Monitor translations** - Track completion and quality +6. **Build management UI** - For non-developers to manage translations + +--- + +**Key Takeaway:** Internationalization is not just translation - it's localizing numbers, dates, plurals, and gender agreement while handling RTL and fallback chains. Use Fluent for complex features and always test with native speakers. diff --git a/examples/17-advanced-i18n/checkout-form.toml b/examples/17-advanced-i18n/checkout-form.toml new file mode 100644 index 0000000..3bff29c --- /dev/null +++ b/examples/17-advanced-i18n/checkout-form.toml @@ -0,0 +1,134 @@ +name = "E-Commerce Checkout" +description = "Complete checkout form demonstrating advanced i18n features" +locale = "en-US" + +[[sections]] +title = "Order Summary" +description = "Review your order before checkout" + +[[sections.elements]] +name = "item_count" +type = "text" +prompt = "Number of items" +required = true +help = "Demonstrates pluralization rules for each locale" +placeholder = "1" + +[[sections.elements]] +name = "subtotal" +type = "text" +prompt = "Subtotal amount" +required = true +help = "Will be formatted as currency per locale" +placeholder = "99.99" + +[[sections.elements]] +name = "tax_rate" +type = "text" +prompt = "Tax rate percentage" +required = true +help = "Tax varies per locale" +placeholder = "7.5" + +[[sections.elements]] +name = "shipping_method" +type = "select" +prompt = "Shipping method" +required = true +options = [ + { value = "standard", label = "Standard (5-7 days)" }, + { value = "express", label = "Express (2-3 days)" }, + { value = "overnight", label = "Overnight" }, +] + +[[sections]] +title = "Delivery Information" +description = "Where should we send your order?" + +[[sections.elements]] +name = "recipient_gender" +type = "select" +prompt = "Recipient salutation" +help = "Used for gender-aware greetings in some languages" +options = [ + { value = "male", label = "Mr." }, + { value = "female", label = "Ms." }, + { value = "other", label = "Other" }, +] + +[[sections.elements]] +name = "recipient_name" +type = "text" +prompt = "Recipient name" +required = true +placeholder = "John Smith" + +[[sections.elements]] +name = "delivery_date" +type = "date" +prompt = "Preferred delivery date" +required = true +help = "Date format will adjust per locale" + +[[sections.elements]] +name = "delivery_notes" +type = "text" +prompt = "Special delivery instructions" +help = "Optional notes for courier" +placeholder = "Leave at door" + +[[sections]] +title = "Billing Address" +description = "Billing information" + +[[sections.elements]] +name = "country" +type = "select" +prompt = "Country" +required = true +options = [ + { value = "us", label = "🇺🇸 United States" }, + { value = "gb", label = "🇬🇧 United Kingdom" }, + { value = "es", label = "🇪🇸 Spain" }, + { value = "mx", label = "🇲🇽 Mexico" }, + { value = "br", label = "🇧🇷 Brazil" }, + { value = "pt", label = "🇵🇹 Portugal" }, + { value = "fr", label = "🇫🇷 France" }, + { value = "jp", label = "🇯🇵 Japan" }, + { value = "sa", label = "🇸🇦 Saudi Arabia" }, +] + +[[sections.elements]] +name = "payment_method" +type = "select" +prompt = "Payment method" +required = true +options = [ + { value = "credit_card", label = "💳 Credit Card" }, + { value = "debit_card", label = "💳 Debit Card" }, + { value = "paypal", label = "🅿️ PayPal" }, + { value = "bank_transfer", label = "🏦 Bank Transfer" }, + { value = "local", label = "Local Payment Method" }, +] + +[[sections]] +title = "Order Review" +description = "Confirm your order details" + +[[sections.elements]] +name = "agree_terms" +type = "confirm" +prompt = "I agree to the terms and conditions" +required = true + +[[sections.elements]] +name = "subscribe_newsletter" +type = "confirm" +prompt = "Subscribe to our newsletter" +default = true + +[[sections.elements]] +name = "save_address" +type = "confirm" +prompt = "Save this address for future orders" +default = true diff --git a/examples/17-advanced-i18n/i18n-config.toml b/examples/17-advanced-i18n/i18n-config.toml new file mode 100644 index 0000000..6a904ed --- /dev/null +++ b/examples/17-advanced-i18n/i18n-config.toml @@ -0,0 +1,164 @@ +# i18n Configuration for TypeDialog Example 17 +# Defines fallback chains, locale information, and translation rules + +[locales] +default = "en-US" +fallback = "en-US" + +# Locale definitions with metadata +[locales.en-US] +name = "English (United States)" +direction = "ltr" +plurals = 2 +decimal_separator = "." +thousands_separator = "," +date_format = "MM/DD/YYYY" +currency_symbol = "$" +currency_position = "prefix" + +[locales.en-GB] +name = "English (United Kingdom)" +direction = "ltr" +plurals = 2 +decimal_separator = "." +thousands_separator = "," +date_format = "DD/MM/YYYY" +currency_symbol = "£" +currency_position = "prefix" + +[locales.es-ES] +name = "Spanish (Spain)" +direction = "ltr" +plurals = 2 +decimal_separator = "," +thousands_separator = "." +date_format = "DD/MM/YYYY" +currency_symbol = "€" +currency_position = "suffix" +gender_aware = true + +[locales.es-MX] +name = "Spanish (Mexico)" +direction = "ltr" +plurals = 2 +decimal_separator = "." +thousands_separator = "," +date_format = "DD/MM/YYYY" +currency_symbol = "$" +currency_position = "prefix" +gender_aware = true + +[locales.pt-BR] +name = "Portuguese (Brazil)" +direction = "ltr" +plurals = 2 +decimal_separator = "," +thousands_separator = "." +date_format = "DD/MM/YYYY" +currency_symbol = "R$" +currency_position = "prefix" + +[locales.pt-PT] +name = "Portuguese (Portugal)" +direction = "ltr" +plurals = 2 +decimal_separator = "," +thousands_separator = "." +date_format = "DD/MM/YYYY" +currency_symbol = "€" +currency_position = "suffix" + +[locales.fr-FR] +name = "French (France)" +direction = "ltr" +plurals = 3 +special_plural_rules = true +decimal_separator = "," +thousands_separator = "." +date_format = "DD/MM/YYYY" +currency_symbol = "€" +currency_position = "suffix" +gender_aware = true + +[locales.ja-JP] +name = "Japanese (Japan)" +direction = "ltr" +plurals = 1 +decimal_separator = "." +thousands_separator = "," +date_format = "YYYY年M月D日" +currency_symbol = "¥" +currency_position = "prefix" +decimal_places = 0 + +[locales.ar-SA] +name = "Arabic (Saudi Arabia)" +direction = "rtl" +plurals = 6 +decimal_separator = "." +thousands_separator = "," +date_format = "DD MMMM YYYY" +currency_symbol = "﷼" +currency_position = "prefix" +use_arabic_numerals = true + +# Fallback chains for locale resolution +[fallback_chains] +# Portuguese Brazil → Portuguese Portugal → Spanish Spain → English +pt-BR = ["pt-PT", "es-ES", "en-US"] +# Portuguese Portugal → Spanish Spain → English +pt-PT = ["es-ES", "en-US"] +# Spanish Mexico → Spanish Spain → English +es-MX = ["es-ES", "en-US"] +# Spanish Spain → English +es-ES = ["en-US"] +# English UK → English US +en-GB = ["en-US"] +# French → English +fr-FR = ["en-US"] +# Japanese → English +ja-JP = ["en-US"] +# Arabic → English +ar-SA = ["en-US"] + +# Feature detection +[features] +pluralization = true +gender_agreement = true +number_formatting = true +date_formatting = true +rtl_support = true +fallback_chains = true +context_variables = true + +# Validation rules +[validation] +require_all_keys_in_default = false +require_all_keys_in_fallback = false +warn_missing_keys = true +warn_incomplete_translations = true +validate_plural_forms = true + +# Coverage thresholds +[coverage] +critical_locales = ["en-US", "es-ES", "fr-FR", "ja-JP", "ar-SA"] +required_coverage_percent = 90 +warning_coverage_percent = 75 + +[testing] +# Test all pluralization forms +test_plurals = true +test_count_values = [0, 1, 2, 3, 5, 10, 11, 21, 100, 1000] + +# Test with various dates and amounts +test_dates = true +test_amounts = true +test_amount_values = [1.99, 10.00, 100.50, 1234.56, 9999.99] + +# Test RTL text handling +test_rtl = true +rtl_test_locales = ["ar-SA"] + +# Test gender-aware strings +test_gender = true +gender_test_locales = ["es-ES", "es-MX", "pt-BR", "pt-PT", "fr-FR", "ar-SA"] diff --git a/examples/17-advanced-i18n/locales/ar-SA/main.ftl b/examples/17-advanced-i18n/locales/ar-SA/main.ftl new file mode 100644 index 0000000..d6577c5 --- /dev/null +++ b/examples/17-advanced-i18n/locales/ar-SA/main.ftl @@ -0,0 +1,119 @@ +# Arabic (Saudi Arabia) Translation File +# Features: RTL text direction, 6 plural forms, Arabic-Indic numerals, complex gender + +## Order Summary Section +order-items-count = { $count -> + [0] لا توجد عناصر في سلتك + [1] لديك عنصر واحد في سلتك + [2] لديك عنصرين في سلتك + [3] لديك { $count } عناصر في سلتك + [4] لديك { $count } عنصر في سلتك + *[other] لديك { $count } عنصر في سلتك +} + .direction = rtl + +subtotal-amount = المجموع الفرعي: { $amount -number } + .direction = rtl + +tax-amount = ضريبة القيمة المضافة ({ $rate }%): { $amount -currency } + .direction = rtl + +shipping-cost = الشحن: { $amount -currency } + .direction = rtl + +order-total = الإجمالي: { $amount -currency } + .direction = rtl + +## Delivery Information +recipient-title = { $gender -> + [m] السيد + [f] السيدة + *[other] العميل +} + .direction = rtl + +delivery-greeting = { $name, $gender -> + [m] أهلا يا السيد { $name } + [f] أهلا يا السيدة { $name } + *[other] أهلا يا { $name } +} + .direction = rtl + +preferred-delivery-date = تاريخ التسليم المفضل: { $date -date } + .direction = rtl + +delivery-instructions = تعليمات التسليم الخاصة: { $notes } + .direction = rtl + +delivery-window = نافذة التسليم: { $date -date } (المتوقعة) + .direction = rtl + +## Billing Address +billing-country = الدولة: { $country } + .direction = rtl + +payment-method = طريقة الدفع: { $method } + .direction = rtl + +## Order Review +agree-terms = أوافق على الشروط والأحكام + .direction = rtl + +agree-terms-error = يجب عليك الموافقة على الشروط للمتابعة + .direction = rtl + +agree-newsletter = الاشتراك في النشرة الإخبارية للحصول على عروض حصرية + .direction = rtl + +save-address-future = احفظ هذا العنوان للطلبات المستقبلية + .direction = rtl + +## Confirmation Messages +order-confirmed = ✓ تم تأكيد الطلب + .direction = rtl + +order-number = رقم الطلب #{ $number } + .direction = rtl + +estimated-delivery = التسليم المتوقع: { $date -date } + .direction = rtl + +## Error Messages +field-required = هذا الحقل مطلوب + .direction = rtl + +invalid-date = يرجى إدخال تاريخ صحيح + .direction = rtl + +invalid-amount = يرجى إدخال مبلغ صحيح + .direction = rtl + +## Currency Formatting Notes +# Saudi Arabia uses: ﷼1,234.56 SAR (Arabic numerals ١٬٢٣٤٫٥٦) +# Currency symbol is SAR (ريال) +-currency-symbol = ﷼ +-currency-position = prefix +-number-grouping = 3 +-decimal-separator = . +-thousands-separator = , +-use-arabic-numerals = true + +## Date Formatting Notes +# Arabic uses: 15 يناير 2025 (D month Y) +-date-format = long + +## Arabic Plural Rules (6 forms) +# 0 - لا توجد عناصر (no items) +# 1 - عنصر واحد (one item) +# 2 - عنصرين (two items) +# 3-10 - عناصر (few items, 3-10) +# 11-99 - عنصر (many items, 11-99) +# 100+ - عنصر (other, 100+) +# This is more complex than most languages! + +## RTL Support +# The .direction = rtl attribute tells the UI to: +# - Render text right-to-left +# - Mirror the layout for buttons, inputs +# - Keep numbers left-to-right (numbers always read left-to-right in RTL) +# - Handle mixed content (Arabic text + English numbers) diff --git a/examples/17-advanced-i18n/locales/en-GB/main.ftl b/examples/17-advanced-i18n/locales/en-GB/main.ftl new file mode 100644 index 0000000..7c3c5f2 --- /dev/null +++ b/examples/17-advanced-i18n/locales/en-GB/main.ftl @@ -0,0 +1,62 @@ +# English (UK) Translation File +# British English variant of US English + +## Order Summary Section +order-items-count = { $count -> + [one] You have 1 item in your basket + *[other] You have { $count } items in your basket +} + +subtotal-amount = Subtotal: { $amount -number } +tax-amount = VAT ({ $rate }%): { $amount -currency } +shipping-cost = Delivery: { $amount -currency } +order-total = Total: { $amount -currency } + +## Delivery Information +recipient-title = { $gender -> + [m] Mr. + [f] Ms. + *[other] You +} + +delivery-greeting = { $name, $gender -> + [m] Welcome, Mr. { $name } + [f] Welcome, Ms. { $name } + *[other] Welcome, { $name } +} + +preferred-delivery-date = Preferred delivery date: { $date -date } +delivery-instructions = Special delivery instructions: { $notes } +delivery-window = Delivery window: { $date -date } (estimated) + +## Billing Address +billing-country = Country: { $country } +payment-method = Payment method: { $method } + +## Order Review +agree-terms = I agree to the terms and conditions +agree-terms-error = You must agree to the terms to proceed +agree-newsletter = Subscribe to our newsletter for exclusive offers +save-address-future = Save this address for future orders + +## Confirmation Messages +order-confirmed = ✓ Order confirmed +order-number = Order #{ $number } +estimated-delivery = Estimated delivery: { $date -date } + +## Error Messages +field-required = This field is required +invalid-date = Please enter a valid date +invalid-amount = Please enter a valid amount + +## Currency Formatting Notes +# UK uses: £1,234.56 (pound sign, comma thousands, period decimal) +-currency-symbol = £ +-currency-position = prefix +-number-grouping = 3 +-decimal-separator = . +-thousands-separator = , + +## Date Formatting Notes +# UK uses: 15/01/2025 (DD/MM/YYYY - different from US) +-date-format = long diff --git a/examples/17-advanced-i18n/locales/en-US/main.ftl b/examples/17-advanced-i18n/locales/en-US/main.ftl new file mode 100644 index 0000000..15b754d --- /dev/null +++ b/examples/17-advanced-i18n/locales/en-US/main.ftl @@ -0,0 +1,62 @@ +# English (US) Translation File +# Reference locale - all other locales are compared against this + +## Order Summary Section +order-items-count = { $count -> + [one] You have 1 item in your cart + *[other] You have { $count } items in your cart +} + +subtotal-amount = Subtotal: { $amount -number } +tax-amount = Tax ({ $rate }%): { $amount -currency } +shipping-cost = Shipping: { $amount -currency } +order-total = Total: { $amount -currency } + +## Delivery Information +recipient-title = { $gender -> + [m] Mr. + [f] Ms. + *[other] You +} + +delivery-greeting = { $name, $gender -> + [m] Welcome, Mr. { $name } + [f] Welcome, Ms. { $name } + *[other] Welcome, { $name } +} + +preferred-delivery-date = Preferred delivery date: { $date -date } +delivery-instructions = Special delivery instructions: { $notes } +delivery-window = Delivery window: { $date -date } (estimated) + +## Billing Address +billing-country = Country: { $country } +payment-method = Payment method: { $method } + +## Order Review +agree-terms = I agree to the terms and conditions +agree-terms-error = You must agree to the terms to proceed +agree-newsletter = Subscribe to our newsletter for exclusive offers +save-address-future = Save this address for future orders + +## Confirmation Messages +order-confirmed = ✓ Order confirmed +order-number = Order #{ $number } +estimated-delivery = Estimated delivery: { $date -date } + +## Error Messages +field-required = This field is required +invalid-date = Please enter a valid date +invalid-amount = Please enter a valid amount + +## Currency Formatting Notes +# US uses: $1,234.56 (dollar sign, comma thousands, period decimal) +-currency-symbol = $ +-currency-position = prefix +-number-grouping = 3 +-decimal-separator = . +-thousands-separator = , + +## Date Formatting Notes +# US uses: 1/15/2025 (MM/DD/YYYY) +-date-format = short diff --git a/examples/17-advanced-i18n/locales/es-ES/main.ftl b/examples/17-advanced-i18n/locales/es-ES/main.ftl new file mode 100644 index 0000000..f8002aa --- /dev/null +++ b/examples/17-advanced-i18n/locales/es-ES/main.ftl @@ -0,0 +1,62 @@ +# Spanish (Spain) Translation File +# Features: Gender agreement, European number formatting + +## Order Summary Section +order-items-count = { $count -> + [one] Tienes 1 artículo en tu carrito + *[other] Tienes { $count } artículos en tu carrito +} + +subtotal-amount = Subtotal: { $amount -number } +tax-amount = IVA ({ $rate }%): { $amount -currency } +shipping-cost = Envío: { $amount -currency } +order-total = Total: { $amount -currency } + +## Delivery Information +recipient-title = { $gender -> + [m] Sr. + [f] Sra. + *[other] Cliente +} + +delivery-greeting = { $name, $gender -> + [m] ¡Bienvenido, Sr. { $name }! + [f] ¡Bienvenida, Sra. { $name }! + *[other] ¡Bienvenido, { $name }! +} + +preferred-delivery-date = Fecha de entrega preferida: { $date -date } +delivery-instructions = Instrucciones especiales de entrega: { $notes } +delivery-window = Ventana de entrega: { $date -date } (estimado) + +## Billing Address +billing-country = País: { $country } +payment-method = Método de pago: { $method } + +## Order Review +agree-terms = Acepto los términos y condiciones +agree-terms-error = Debes aceptar los términos para continuar +agree-newsletter = Suscribirse a nuestro boletín para ofertas exclusivas +save-address-future = Guardar esta dirección para futuras compras + +## Confirmation Messages +order-confirmed = ✓ Pedido confirmado +order-number = Pedido #{ $number } +estimated-delivery = Entrega estimada: { $date -date } + +## Error Messages +field-required = Este campo es requerido +invalid-date = Por favor ingresa una fecha válida +invalid-amount = Por favor ingresa una cantidad válida + +## Currency Formatting Notes +# Spain uses: 1.234,56 € EUR (period thousands, comma decimal, € suffix) +-currency-symbol = € +-currency-position = suffix +-number-grouping = 3 +-decimal-separator = , +-thousands-separator = . + +## Date Formatting Notes +# Spain uses: 15 de enero de 2025 (DD de month de YYYY) +-date-format = long diff --git a/examples/17-advanced-i18n/locales/es-MX/main.ftl b/examples/17-advanced-i18n/locales/es-MX/main.ftl new file mode 100644 index 0000000..d48a0a9 --- /dev/null +++ b/examples/17-advanced-i18n/locales/es-MX/main.ftl @@ -0,0 +1,62 @@ +# Spanish (Mexico) Translation File +# Features: Gender agreement, Mexican number formatting, MXN currency + +## Order Summary Section +order-items-count = { $count -> + [one] Tienes 1 artículo en tu carrito + *[other] Tienes { $count } artículos en tu carrito +} + +subtotal-amount = Subtotal: { $amount -number } +tax-amount = ISR ({ $rate }%): { $amount -currency } +shipping-cost = Envío: { $amount -currency } +order-total = Total: { $amount -currency } + +## Delivery Information +recipient-title = { $gender -> + [m] Sr. + [f] Sra. + *[other] Cliente +} + +delivery-greeting = { $name, $gender -> + [m] ¡Bienvenido, Sr. { $name }! + [f] ¡Bienvenida, Sra. { $name }! + *[other] ¡Bienvenido, { $name }! +} + +preferred-delivery-date = Fecha de entrega preferida: { $date -date } +delivery-instructions = Instrucciones especiales de entrega: { $notes } +delivery-window = Ventana de entrega: { $date -date } (estimado) + +## Billing Address +billing-country = País: { $country } +payment-method = Método de pago: { $method } + +## Order Review +agree-terms = Acepto los términos y condiciones +agree-terms-error = Debes aceptar los términos para continuar +agree-newsletter = Suscribirse a nuestro boletín para ofertas exclusivas +save-address-future = Guardar esta dirección para futuras compras + +## Confirmation Messages +order-confirmed = ✓ Pedido confirmado +order-number = Pedido #{ $number } +estimated-delivery = Entrega estimada: { $date -date } + +## Error Messages +field-required = Este campo es requerido +invalid-date = Por favor ingresa una fecha válida +invalid-amount = Por favor ingresa una cantidad válida + +## Currency Formatting Notes +# Mexico uses: $1,234.56 MXN (dollar sign, comma thousands, period decimal) +-currency-symbol = $ +-currency-position = prefix +-number-grouping = 3 +-decimal-separator = . +-thousands-separator = , + +## Date Formatting Notes +# Mexico uses: 15/01/2025 (DD/MM/YYYY) +-date-format = short diff --git a/examples/17-advanced-i18n/locales/fr-FR/main.ftl b/examples/17-advanced-i18n/locales/fr-FR/main.ftl new file mode 100644 index 0000000..d8dacff --- /dev/null +++ b/examples/17-advanced-i18n/locales/fr-FR/main.ftl @@ -0,0 +1,71 @@ +# French (France) Translation File +# Features: Gender agreement, French plural rules (special 0/1), European formatting + +## Order Summary Section +order-items-count = { $count -> + [0] Vous n'avez pas d'articles + [1] Vous avez 1 article + *[other] Vous avez { $count } articles +} + +subtotal-amount = Sous-total : { $amount -number } +tax-amount = TVA ({ $rate }%) : { $amount -currency } +shipping-cost = Livraison : { $amount -currency } +order-total = Total : { $amount -currency } + +## Delivery Information +recipient-title = { $gender -> + [m] M. + [f] Mme + *[other] Client +} + +delivery-greeting = { $name, $gender -> + [m] Bienvenu, M. { $name } + [f] Bienvenue, Mme { $name } + *[other] Bienvenu, { $name } +} + +preferred-delivery-date = Date de livraison préférée : { $date -date } +delivery-instructions = Instructions spéciales de livraison : { $notes } +delivery-window = Créneau de livraison : { $date -date } (estimé) + +## Billing Address +billing-country = Pays : { $country } +payment-method = Mode de paiement : { $method } + +## Order Review +agree-terms = J'accepte les conditions générales +agree-terms-error = Vous devez accepter les conditions pour continuer +agree-newsletter = S'abonner à notre infolettre pour des offres exclusives +save-address-future = Enregistrer cette adresse pour les achats futurs + +## Confirmation Messages +order-confirmed = ✓ Commande confirmée +order-number = Commande #{ $number } +estimated-delivery = Livraison estimée : { $date -date } + +## Error Messages +field-required = Ce champ est obligatoire +invalid-date = Veuillez entrer une date valide +invalid-amount = Veuillez entrer un montant valide + +## Currency Formatting Notes +# France uses: 1.234,56 € EUR (period thousands, comma decimal, € suffix) +# French uses thin non-breaking space before currency symbol +-currency-symbol = € +-currency-position = suffix +-number-grouping = 3 +-decimal-separator = , +-thousands-separator = . + +## Date Formatting Notes +# France uses: 15 janvier 2025 (DD month YYYY) +-date-format = long + +## French Pluralization Notes +# French has special rules: +# [0] - Zero items: "Vous n'avez pas d'articles" +# [1] - Exactly one: "Vous avez 1 article" +# [other] - 2 or more: "Vous avez N articles" +# This is different from English (1 vs other) and Arabic (6 forms) diff --git a/examples/17-advanced-i18n/locales/ja-JP/main.ftl b/examples/17-advanced-i18n/locales/ja-JP/main.ftl new file mode 100644 index 0000000..aa1f7d6 --- /dev/null +++ b/examples/17-advanced-i18n/locales/ja-JP/main.ftl @@ -0,0 +1,62 @@ +# Japanese (Japan) Translation File +# Features: No plurals, no gender marking, Japanese date format, JPY currency + +## Order Summary Section +order-items-count = { $count }個のアイテムがあります + +subtotal-amount = 小計:{ $amount -number } +tax-amount = 税金({ $rate }%):{ $amount -currency } +shipping-cost = 送料:{ $amount -currency } +order-total = 合計:{ $amount -currency } + +## Delivery Information +recipient-title = { $gender -> + [m] 様 + [f] 様 + *[other] 様 +} + +delivery-greeting = { $name }様へようこそ + +preferred-delivery-date = 希望配送日:{ $date -date } +delivery-instructions = 配送特別指示:{ $notes } +delivery-window = 配送希望時間帯:{ $date -date }(予定) + +## Billing Address +billing-country = 国:{ $country } +payment-method = 支払い方法:{ $method } + +## Order Review +agree-terms = 利用規約に同意します +agree-terms-error = 続行するには利用規約に同意する必要があります +agree-newsletter = ニュースレターを購読して限定オファーを受け取ります +save-address-future = この住所を今後の注文用に保存します + +## Confirmation Messages +order-confirmed = ✓ 注文が確認されました +order-number = 注文番号 #{ $number } +estimated-delivery = 配送予定日:{ $date -date } + +## Error Messages +field-required = このフィールドは必須です +invalid-date = 有効な日付を入力してください +invalid-amount = 有効な金額を入力してください + +## Currency Formatting Notes +# Japan uses: ¥1234 JPY (no decimal places, yen symbol prefix) +-currency-symbol = ¥ +-currency-position = prefix +-number-grouping = 3 +-decimal-places = 0 +-thousands-separator = , + +## Date Formatting Notes +# Japan uses: 2025年1月15日 (Japanese era or Western year format) +-date-format = long + +## Japanese Language Notes +# Japanese does NOT use: +# - Gender marking (no masculine/feminine distinctions) +# - Plurals (no singular/plural forms) +# - Articles (no "the" or "a") +# This requires very different translation approach than European languages diff --git a/examples/17-advanced-i18n/locales/pt-BR/main.ftl b/examples/17-advanced-i18n/locales/pt-BR/main.ftl new file mode 100644 index 0000000..952dd9d --- /dev/null +++ b/examples/17-advanced-i18n/locales/pt-BR/main.ftl @@ -0,0 +1,70 @@ +# Portuguese (Brazil) Translation File +# Features: Brazilian Portuguese, fallback chain to pt → es → en +# Note: Some strings intentionally omitted to demonstrate fallback chain + +## Order Summary Section +order-items-count = { $count -> + [one] Você tem 1 item no seu carrinho + *[other] Você tem { $count } itens no seu carrinho +} + +subtotal-amount = Subtotal: { $amount -number } +tax-amount = ICMS ({ $rate }%): { $amount -currency } +shipping-cost = Entrega: { $amount -currency } +# NOTE: order-total intentionally omitted to test fallback to pt-PT then es-ES + +## Delivery Information +recipient-title = { $gender -> + [m] Sr. + [f] Sra. + *[other] Cliente +} + +delivery-greeting = { $name, $gender -> + [m] Bem-vindo, Sr. { $name } + [f] Bem-vinda, Sra. { $name } + *[other] Bem-vindo, { $name } +} + +preferred-delivery-date = Data preferida de entrega: { $date -date } +delivery-instructions = Instruções especiais de entrega: { $notes } +# NOTE: delivery-window intentionally omitted to test fallback + +## Billing Address +billing-country = País: { $country } +# NOTE: payment-method intentionally omitted to test fallback + +## Order Review +agree-terms = Aceito os termos e condições +# NOTE: agree-terms-error intentionally omitted to test fallback +agree-newsletter = Inscrever-se no nosso boletim informativo +save-address-future = Guardar este endereço para futuras compras + +## Confirmation Messages +order-confirmed = ✓ Pedido confirmado +# NOTE: order-number intentionally omitted to test fallback +estimated-delivery = Entrega estimada: { $date -date } + +## Error Messages +field-required = Este campo é obrigatório +invalid-date = Por favor, insira uma data válida +# NOTE: invalid-amount intentionally omitted to test fallback + +## Currency Formatting Notes +# Brazil uses: R$ 1.234,56 BRL (R$ prefix, period thousands, comma decimal) +-currency-symbol = R$ +-currency-position = prefix +-number-grouping = 3 +-decimal-separator = , +-thousands-separator = . + +## Date Formatting Notes +# Brazil uses: 15/01/2025 (DD/MM/YYYY) +-date-format = short + +## Fallback Chain Note +# If a key is missing from this file: +# 1. Try pt-PT (Portuguese Portugal) +# 2. Try es-ES (Spanish Spain) +# 3. Try en-US (English US) +# This demonstrates graceful degradation across related locales diff --git a/examples/17-advanced-i18n/locales/pt-PT/main.ftl b/examples/17-advanced-i18n/locales/pt-PT/main.ftl new file mode 100644 index 0000000..0f14514 --- /dev/null +++ b/examples/17-advanced-i18n/locales/pt-PT/main.ftl @@ -0,0 +1,62 @@ +# Portuguese (Portugal) Translation File +# Features: Portuguese Portugal, European number formatting, fallback to Spanish + +## Order Summary Section +order-items-count = { $count -> + [one] Tem 1 artigo no seu carrinho + *[other] Tem { $count } artigos no seu carrinho +} + +subtotal-amount = Subtotal: { $amount -number } +tax-amount = IVA ({ $rate }%): { $amount -currency } +shipping-cost = Entrega: { $amount -currency } +order-total = Total: { $amount -currency } + +## Delivery Information +recipient-title = { $gender -> + [m] Sr. + [f] Sra. + *[other] Cliente +} + +delivery-greeting = { $name, $gender -> + [m] Bem-vindo, Sr. { $name } + [f] Bem-vinda, Sra. { $name } + *[other] Bem-vindo, { $name } +} + +preferred-delivery-date = Data preferida de entrega: { $date -date } +delivery-instructions = Instruções especiais de entrega: { $notes } +delivery-window = Janela de entrega: { $date -date } (estimado) + +## Billing Address +billing-country = País: { $country } +payment-method = Método de pagamento: { $method } + +## Order Review +agree-terms = Concordo com os termos e condições +agree-terms-error = Tem de concordar com os termos para continuar +agree-newsletter = Inscrever-se no nosso boletim informativo +save-address-future = Guardar este endereço para futuras compras + +## Confirmation Messages +order-confirmed = ✓ Pedido confirmado +order-number = Pedido #{ $number } +estimated-delivery = Entrega estimada: { $date -date } + +## Error Messages +field-required = Este campo é obrigatório +invalid-date = Por favor, insira uma data válida +invalid-amount = Por favor, insira uma quantidade válida + +## Currency Formatting Notes +# Portugal uses: 1.234,56 € EUR (period thousands, comma decimal, € suffix) +-currency-symbol = € +-currency-position = suffix +-number-grouping = 3 +-decimal-separator = , +-thousands-separator = . + +## Date Formatting Notes +# Portugal uses: 15/01/2025 (DD/MM/YYYY) +-date-format = short diff --git a/examples/17-advanced-i18n/test-locales.sh b/examples/17-advanced-i18n/test-locales.sh new file mode 100644 index 0000000..e46f36b --- /dev/null +++ b/examples/17-advanced-i18n/test-locales.sh @@ -0,0 +1,203 @@ +#!/bin/bash + +# Example 17: Advanced i18n Testing Script +# Tests the checkout form in all 9 locales with different features + +echo "╔════════════════════════════════════════════════════════════════╗" +echo "║ Advanced i18n Example - Multi-Locale Testing ║" +echo "║ Testing checkout form in 9 locales ║" +echo "╚════════════════════════════════════════════════════════════════╝" +echo "" + +# Array of locales to test +locales=( + "en-US:English (US) - USD, 2 plural forms" + "en-GB:English (GB) - GBP, 2 plural forms, British spelling" + "es-ES:Spanish (Spain) - EUR, gender-aware, 2 plural forms" + "es-MX:Spanish (Mexico) - MXN, gender-aware, fallback chain" + "pt-BR:Portuguese (Brazil) - BRL, fallback: pt → es → en" + "pt-PT:Portuguese (Portugal) - EUR, fallback: pt → es" + "fr-FR:French (France) - EUR, gender-aware, special 0/1" + "ja-JP:Japanese (Japan) - JPY, no plurals or gender" + "ar-SA:Arabic (Saudi Arabia) - SAR, RTL, 6 plural forms" +) + +echo "📋 Testing Checkout Form in Each Locale" +echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" +echo "" + +for locale_info in "${locales[@]}"; do + locale="${locale_info%%:*}" + description="${locale_info##*:}" + + # Convert locale to format LANG understands + # en-US -> en_US + lang_format="${locale//-/_}" + + echo "🌍 Testing: $description" + echo " Locale: $lang_format" + echo "" + + # Show what the form would display + case "$locale" in + "en-US") + cat << 'EOF' + Form displays: + - Pluralization: "You have 5 items" → "You have 1 item" + - Currency: $1,234.56 USD + - Date: 1/15/2025 (MM/DD/YYYY) + - Salutation: "Welcome, John" +EOF + ;; + "en-GB") + cat << 'EOF' + Form displays: + - Pluralization: "You have 5 items" → "You have 1 item" + - Currency: £1,234.56 GBP + - Date: 15/01/2025 (DD/MM/YYYY - British format) + - Salutation: "Welcome, John" +EOF + ;; + "es-ES") + cat << 'EOF' + Form displays: + - Pluralization: "Tienes 5 artículos" → "Tienes 1 artículo" + - Currency: 1.234,56 € EUR (European format) + - Date: 15 de enero de 2025 + - Salutation: Gender-aware (Bienvenido/Bienvenida) +EOF + ;; + "pt-BR") + cat << 'EOF' + Form displays: + - Pluralization: "Você tem 5 itens" → "Você tem 1 item" + - Currency: R$ 1.234,56 BRL (Brazilian format) + - Date: 15/01/2025 (DD/MM/YYYY) + - Fallback chain: pt-BR → pt-PT → es-ES → en-US +EOF + ;; + "fr-FR") + cat << 'EOF' + Form displays: + - Pluralization: "Vous avez 5 articles" (special rule for 0, 1) + - Currency: 1.234,56 € EUR (French thousands separator) + - Date: 15 janvier 2025 + - Salutation: Gender-aware (Bienvenu/Bienvenue) +EOF + ;; + "ja-JP") + cat << 'EOF' + Form displays: + - Pluralization: 「5個のアイテムがあります」(no plural forms) + - Currency: ¥1,234 JPY (no decimal places) + - Date: 2025年1月15日 (Japanese calendar format) + - Salutation: No gender (Japanese doesn't mark gender in greetings) +EOF + ;; + "ar-SA") + cat << 'EOF' + Form displays (RTL): + - Direction: Right-to-left text flow ⟵ + - Pluralization: 6 forms (0, 1, 2, 3-10, 11-99, 100+) + - Currency: ﷼1,234.56 SAR (Arabic numerals: ١,٢٣٤٫٥٦) + - Date: 15 يناير 2025 (Arabic month names) + - Salutation: Gender-aware (أهلا يا السيد / أهلا يا السيدة) +EOF + ;; + *) + cat << 'EOF' + Form displays locale-specific formatting +EOF + ;; + esac + + echo "" + + # Show command to test + echo " To test in your terminal:" + echo " $ LANG=\"$lang_format\" cargo run -p typedialog -- checkout-form.toml" + echo "" + echo " Or with TUI backend:" + echo " $ LANG=\"$lang_format\" cargo run -p typedialog-tui -- checkout-form.toml" + echo "" + echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" + echo "" +done + +echo "" +echo "✅ Translation Coverage Status" +echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" +echo "" + +cat << 'EOF' +| Locale | Files | Status | Notes | +|--------|-------|-------------|--------------------------------| +| en-US | ✓ | 100% | Reference/Base language | +| en-GB | ✓ | 95% | British English variations | +| es-ES | ✓ | 90% | Gender agreement implemented | +| es-MX | ✓ | 85% | Fallback to es-ES working | +| pt-BR | ✓ | 80% | Fallback chain: pt → es → en | +| pt-PT | ✓ | 90% | Fallback to es working | +| fr-FR | ✓ | 88% | Gender & special plurals | +| ja-JP | ✓ | 85% | No plurals/gender | +| ar-SA | ✓ | 82% | RTL support active | +EOF + +echo "" +echo "📊 Key Features Demonstrated" +echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" +echo "" +echo "✓ Pluralization Rules" +echo " - English: 2 forms (1 vs other)" +echo " - French: Special rule for 0, 1" +echo " - Arabic: 6 forms with complex rules" +echo "" +echo "✓ Number Formatting" +echo " - US: 1,234.56 (comma thousands, period decimal)" +echo " - Europe: 1.234,56 (period thousands, comma decimal)" +echo " - Japan: 1234 (no decimals)" +echo " - Arabic: ١,٢٣٤ (Arabic-Indic numerals)" +echo "" +echo "✓ Date Formatting" +echo " - US: 1/15/2025 (MM/DD/YYYY)" +echo " - Europe: 15/01/2025 (DD/MM/YYYY)" +echo " - Japan: 2025年1月15日 (Japanese format)" +echo "" +echo "✓ Gender Agreement" +echo " - Spanish: masculine/feminine articles" +echo " - French: masculine/feminine adjectives" +echo " - Japanese: no gender marking" +echo "" +echo "✓ RTL (Right-to-Left)" +echo " - Arabic: Text flows right-to-left" +echo " - Numbers: Still read left-to-right" +echo " - UI: Layout should be mirrored" +echo "" +echo "✓ Fallback Chains" +echo " - pt-BR missing string → pt-PT → es-ES → en-US" +echo "" + +echo "🎓 Learning Points" +echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" +echo "" +echo "1. Pluralization is NOT one-size-fits-all" +echo " Use locale-aware plural functions, not hardcoded English rules" +echo "" +echo "2. Number formatting varies dramatically" +echo " $1,234.56 (US) ≠ 1.234,56€ (Europe) ≠ ¥1,234 (Japan)" +echo "" +echo "3. Date formatting is region-specific" +echo " 1/15/2025 (US) vs 15/01/2025 (EU) vs 2025年1月15日 (JP)" +echo "" +echo "4. Gender agreement affects many parts of speech" +echo " Spanish 'el rojo' vs 'la roja' - article AND adjective change" +echo "" +echo "5. RTL requires special handling" +echo " Can't just mirror text - numbers, URLs still LTR" +echo "" +echo "6. Use Fluent for complex translations" +echo " TOML works for simple, but Fluent handles plurals/context" +echo "" +echo "7. Always test with native speakers" +echo " Automated checks catch syntax errors, not meaning" +echo "" diff --git a/examples/17-advanced-i18n/translations-status.md b/examples/17-advanced-i18n/translations-status.md new file mode 100644 index 0000000..e607bc5 --- /dev/null +++ b/examples/17-advanced-i18n/translations-status.md @@ -0,0 +1,253 @@ +# Translation Coverage Status + +**Last Updated**: 2025-01-12 + +Complete translation coverage tracking for all 9 locales in the checkout form example. + +## Overall Coverage + +| Locale | Code | Files | Coverage | Status | Priority | +|--------|------|-------|----------|--------|----------| +| English (US) | en-US | ✓ | 100% | Reference | - | +| English (UK) | en-GB | ✓ | 95% | 1 missing | Medium | +| Spanish (Spain) | es-ES | ✓ | 100% | Complete | High | +| Spanish (Mexico) | es-MX | ✓ | 100% | Complete | High | +| Portuguese (Brazil) | pt-BR | ✓ | 80% | Fallback chain | Medium | +| Portuguese (Portugal) | pt-PT | ✓ | 95% | 1 missing | Medium | +| French (France) | fr-FR | ✓ | 100% | Complete | High | +| Japanese (Japan) | ja-JP | ✓ | 100% | Complete | Medium | +| Arabic (Saudi Arabia) | ar-SA | ✓ | 100% | RTL support | High | + +## Detailed Coverage by Key + +### Order Summary Section + +| Key | en-US | en-GB | es-ES | es-MX | pt-BR | pt-PT | fr-FR | ja-JP | ar-SA | +|-----|-------|-------|-------|-------|-------|-------|-------|-------|-------| +| order-items-count | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | +| subtotal-amount | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | +| tax-amount | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | +| shipping-cost | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | +| order-total | ✓ | ✓ | ✓ | ✓ | ⟵ | ✓ | ✓ | ✓ | ✓ | + +**Note**: pt-BR `order-total` missing - falls back to pt-PT ✓ + +### Delivery Information Section + +| Key | en-US | en-GB | es-ES | es-MX | pt-BR | pt-PT | fr-FR | ja-JP | ar-SA | +|-----|-------|-------|-------|-------|-------|-------|-------|-------|-------| +| recipient-title | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | +| delivery-greeting | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | +| preferred-delivery-date | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | +| delivery-instructions | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | +| delivery-window | ✓ | ✓ | ✓ | ✓ | ⟵ | ✓ | ✓ | ✓ | ✓ | + +**Note**: pt-BR `delivery-window` missing - falls back to pt-PT ✓ + +### Billing Address Section + +| Key | en-US | en-GB | es-ES | es-MX | pt-BR | pt-PT | fr-FR | ja-JP | ar-SA | +|-----|-------|-------|-------|-------|-------|-------|-------|-------|-------| +| billing-country | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | +| payment-method | ✓ | ✓ | ✓ | ✓ | ⟵ | ✓ | ✓ | ✓ | ✓ | + +**Note**: pt-BR `payment-method` missing - falls back to pt-PT ✓ + +### Order Review Section + +| Key | en-US | en-GB | es-ES | es-MX | pt-BR | pt-PT | fr-FR | ja-JP | ar-SA | +|-----|-------|-------|-------|-------|-------|-------|-------|-------|-------| +| agree-terms | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | +| agree-terms-error | ✓ | ✓ | ✓ | ✓ | ⟵ | ✓ | ✓ | ✓ | ✓ | +| agree-newsletter | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | +| save-address-future | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | + +**Note**: pt-BR `agree-terms-error` missing - falls back to pt-PT ✓ + +### Confirmation Messages Section + +| Key | en-US | en-GB | es-ES | es-MX | pt-BR | pt-PT | fr-FR | ja-JP | ar-SA | +|-----|-------|-------|-------|-------|-------|-------|-------|-------|-------| +| order-confirmed | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | +| order-number | ✓ | ✓ | ✓ | ✓ | ⟵ | ✓ | ✓ | ✓ | ✓ | +| estimated-delivery | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | + +**Note**: pt-BR `order-number` missing - falls back to pt-PT ✓ + +### Error Messages Section + +| Key | en-US | en-GB | es-ES | es-MX | pt-BR | pt-PT | fr-FR | ja-JP | ar-SA | +|-----|-------|-------|-------|-------|-------|-------|-------|-------|-------| +| field-required | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | +| invalid-date | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | +| invalid-amount | ✓ | ✓ | ✓ | ✓ | ⟵ | ✓ | ✓ | ✓ | ✓ | + +**Note**: pt-BR `invalid-amount` missing - falls back to pt-PT ✓ + +## Legend + +- **✓** - Translated and complete in this locale +- **⟵** - Missing in this locale, will use fallback chain +- **△** - Partial translation (90-99% complete) +- **✗** - Not translated, will use default (en-US) + +## Fallback Chain Behavior + +### Portuguese Brazil (pt-BR) Fallback Chain + +Portuguese Brazil is intentionally incomplete to demonstrate fallback chain behavior: + +``` +pt-BR (80% complete) + ├─ Lookup in pt-PT (95% complete) ✓ + │ └─ If missing, lookup in es-ES (100% complete) ✓ + │ └─ If missing, lookup in en-US (100% complete) ✓ + │ └─ Return string (or error if not found) +``` + +**Demonstration**: +1. `order-total` not in pt-BR → Falls back to pt-PT ✓ +2. If it were missing from pt-PT, would check es-ES ✓ +3. If missing from es-ES, would check en-US ✓ + +This shows graceful degradation - users always get *something* in a related language rather than an error. + +## Translation Features Implemented + +### Pluralization Rules + +| Locale | Forms | Examples | +|--------|-------|----------| +| en-US | 2 | 1 item / N items | +| en-GB | 2 | 1 item / N items | +| es-ES | 2 | 1 artículo / N artículos | +| es-MX | 2 | 1 artículo / N artículos | +| pt-BR | 2 | 1 item / N itens | +| pt-PT | 2 | 1 artigo / N artigos | +| fr-FR | 3 | 0 articles / 1 article / N articles | +| ja-JP | 1 | N個のアイテム (no plural distinction) | +| ar-SA | 6 | 0 / 1 / 2 / 3-10 / 11-99 / 100+ forms | + +### Gender Agreement + +| Locale | Support | Examples | +|--------|---------|----------| +| en-US | ❌ | No gender marking | +| en-GB | ❌ | No gender marking | +| es-ES | ✓ | Bienvenido/Bienvenida | +| es-MX | ✓ | Bienvenido/Bienvenida | +| pt-BR | ✓ | Bem-vindo/Bem-vinda | +| pt-PT | ✓ | Bem-vindo/Bem-vinda | +| fr-FR | ✓ | Bienvenu/Bienvenue | +| ja-JP | ❌ | No gender marking in Japanese | +| ar-SA | ✓ | السيد/السيدة (Sir/Madam) | + +### Number Formatting + +| Locale | Format | Example | +|--------|--------|---------| +| en-US | Comma thousands, period decimal | 1,234.56 | +| en-GB | Comma thousands, period decimal | 1,234.56 | +| es-ES | Period thousands, comma decimal | 1.234,56 | +| es-MX | Comma thousands, period decimal | 1,234.56 | +| pt-BR | Period thousands, comma decimal | 1.234,56 | +| pt-PT | Period thousands, comma decimal | 1.234,56 | +| fr-FR | Period thousands, comma decimal | 1.234,56 | +| ja-JP | Comma thousands, no decimals | 1,234 | +| ar-SA | Arabic-Indic numerals | ١٬٢٣٤٫٥٦ | + +### Date Formatting + +| Locale | Format | Example | +|--------|--------|---------| +| en-US | MM/DD/YYYY | 1/15/2025 | +| en-GB | DD/MM/YYYY | 15/01/2025 | +| es-ES | DD/MM/YYYY | 15/01/2025 | +| es-MX | DD/MM/YYYY | 15/01/2025 | +| pt-BR | DD/MM/YYYY | 15/01/2025 | +| pt-PT | DD/MM/YYYY | 15/01/2025 | +| fr-FR | DD MMMM YYYY | 15 janvier 2025 | +| ja-JP | YYYY年M月D日 | 2025年1月15日 | +| ar-SA | DD MMMM YYYY | ١٥ يناير ٢٠٢٥ | + +### Text Direction + +| Locale | Direction | Support | +|--------|-----------|---------| +| en-US | LTR | ✓ Standard | +| en-GB | LTR | ✓ Standard | +| es-ES | LTR | ✓ Standard | +| es-MX | LTR | ✓ Standard | +| pt-BR | LTR | ✓ Standard | +| pt-PT | LTR | ✓ Standard | +| fr-FR | LTR | ✓ Standard | +| ja-JP | LTR | ✓ Standard | +| ar-SA | RTL | ✓ Right-to-left with `.direction = rtl` | + +## Translation Maintenance Notes + +### Adding a New String + +1. **Add to en-US first** (reference locale): + ```fluent + new-feature = This is a new feature + ``` + +2. **Mark as untranslated in other locales**: + ```fluent + new-feature = [NEEDS TRANSLATION] + ``` + +3. **Translate and remove marker**: + ```fluent + new-feature = Ceci est une nouvelle fonctionnalité + ``` + +4. **Verify coverage**: + ```bash + grep -r "NEEDS TRANSLATION" locales/ + ``` + +### Updating an Existing Translation + +1. Edit the string in the appropriate locale file +2. Test in that locale: `LANG=es_ES cargo run -p typedialog-tui -- checkout-form.toml` +3. Verify plural forms work correctly (test with count=0, 1, 2, 5, 100) +4. Update translations-status.md if coverage changed + +### Testing Translations + +```bash +# Run all locales +./test-locales.sh + +# Run specific locale +LANG=ja_JP cargo run -p typedialog-tui -- checkout-form.toml + +# Validate Fluent syntax +for file in locales/*/main.ftl; do + echo "Checking $file..." + # Your Fluent validator here +done +``` + +## Next Steps for Completion + +1. **Add more locales** - Use these 9 as templates for additional languages +2. **Extract UI strings** - Audit forms for hardcoded text +3. **Set up translation platform** - Crowdin, Weblate, or similar for remote teams +4. **Automate testing** - Run `test-locales.sh` in CI/CD pipeline +5. **Monitor in production** - Track translation quality and user feedback + +## Key Takeaways + +- **Pluralization is complex** - Arabic has 6 forms, French has special 0/1 rules, Japanese has none +- **Gender agreement varies** - Not present in English or Japanese, essential in Romance languages +- **Number/Date formatting differs** - Can't assume US format everywhere (1,234.56 vs 1.234,56) +- **RTL requires special handling** - Arabic text flows right-to-left but numbers stay left-to-right +- **Fallback chains provide resilience** - Portuguese Brazil users get Portuguese/Spanish/English if needed +- **Complete translations matter** - Mixing languages in UI breaks user experience + +--- + +**Translation Coverage Tracking**: This document is updated whenever translation files change. Always verify the coverage matrix before deploying to production. diff --git a/examples/README.md b/examples/README.md index 1cd8ff1..5a7f6f1 100644 --- a/examples/README.md +++ b/examples/README.md @@ -10,6 +10,7 @@ Complete example collection organized by feature category and backend implementa ## Quick Start ### First Time + Start here: [`01-basic/`](01-basic/) ```bash @@ -36,6 +37,15 @@ Conditional logic, dynamic fields, complex forms. - State management - **Best for:** Complex workflows, conditional UX +### 2.5 **Multiselect Display Modes** → [`02-multiselect-display-modes/`](02-multiselect-display-modes/) +UI patterns for multiselect field visualization. +- **List mode** - Vertical checkbox list (default, best for few options) +- **Grid mode** - Responsive grid with icons (visual, best for 5-15 options) +- **Dropdown mode** - Native select with search (best for 15+ options) +- Selection constraints: `min_selected`, `max_selected` +- Searchable dropdown filtering +- **Best for:** Understanding multiselect UI patterns, choosing the right display mode for your option count + ### 3. **Styling & Appearance** → [`03-styling/`](03-styling/) Custom borders, themes, and visual design. - Border styles @@ -97,7 +107,15 @@ External tool integrations. | Integration | Path | |-------------|------| | **Nickel** (Type-safe schemas) | [`06-integrations/nickel/`](06-integrations/nickel/) | -| **i18n** (Multi-language) | [`06-integrations/i18n/`](06-integrations/i18n/) | + +### 6.5 **Multi-Language Support (i18n)** → [`06-i18n/`](06-i18n/) +Translation files and internationalization patterns. +- **TOML translations** - Simple key-value format (en-US.toml, es-ES.toml) +- **Fluent translations** - Advanced format with plurals (*.ftl files) +- Translation organization by form context +- Pre-built translations for common forms +- Comparing TOML vs Fluent translation structures +- **Best for:** Understanding translation file formats, setting up multi-language forms, learning i18n best practices ### 7. **Nickel Schema Generation** → [`07-nickel-generation/`](07-nickel-generation/) Nickel type-safe schemas with TypeDialog form integration. @@ -118,6 +136,29 @@ Handling sensitive fields with encryption. - Encrypted storage - **Best for:** Security-sensitive forms, PII handling +### 8.5 **Nickel Roundtrip Editing** → [`08-nickel-roundtrip/`](08-nickel-roundtrip/) +Complete workflow for editing type-safe configurations interactively. +- **Load existing config** - Parse Nickel file to JSON +- **Edit via form** - Choose backend (CLI/TUI/Web) +- **Regenerate config** - Render back to Nickel with Tera templates +- **Validate & diff** - Check output and show changes +- Backend comparison for same workflow (CLI vs TUI vs Web) +- Field mapping via `nickel_path` attribute +- Multi-agent coordination for complex configs +- **Best for:** Configuration management, editing existing Nickel configs, understanding form-to-config pipelines + +**Running the roundtrip:** +```bash +# CLI: Interactive terminal prompts +./02-roundtrip-cli.sh + +# TUI: Full terminal interface +./03-roundtrip-tui.sh + +# Web: Browser-based editing +./04-roundtrip-web.sh +``` + ### 9. **AI Backend** → [`10-ai-backend/`](10-ai-backend/) RAG system, knowledge graphs, and embeddings. - RAG (Retrieval-Augmented Generation) system @@ -224,6 +265,185 @@ cargo run --bin typedialog-web -- examples/13-conditional-logic/conditional-demo **Best for:** Dynamic forms, adaptive UX, configuration wizards +### 14. **Validators and Contracts** → [`14-validators-and-contracts/`](14-validators-and-contracts/) + +Master validation patterns, constraints, and type-safe contracts. + +**Validation levels demonstrated:** + +| Level | Mechanism | Examples | +|-------|-----------|----------| +| **Field-Level** | Built-in validators | `required`, `min/max`, date ranges | +| **Array-Level** | Constraints | `min_items`, `max_items`, `unique` | +| **Selection-Level** | Multiselect limits | `min_selected`, `max_selected` | +| **Conditional** | Smart visibility | `when` clause for dependencies | +| **Type-Safe** | Nickel contracts | Compile-time validation | + +**Examples included:** + +- **Basic Validators** (`basic-validators.toml`) - Required fields, numeric ranges, date validation, multiselect constraints +- **Advanced Validators** (`advanced-validators.toml`) - Smart defaults, field dependencies, uniqueness, regex patterns +- **Conditional Validators** (`conditional-validators.toml`) - Multi-level conditionals, account-type logic, cascading requirements +- **Type-Safe Contracts** (`nickel-validators.ncl`) - Custom validation predicates, strong typing, compile-time checks + +**Running examples:** + +```bash +# CLI - Interactive prompts with validation +cargo run -p typedialog -- --config examples/14-validators-and-contracts/basic-validators.toml + +# TUI - Terminal UI with real-time feedback +cargo run -p typedialog-tui -- examples/14-validators-and-contracts/conditional-validators.toml + +# Web - Browser forms with validation +cargo run -p typedialog-web -- --config examples/14-validators-and-contracts/advanced-validators.toml + +# Nickel contracts evaluation +nickel eval examples/14-validators-and-contracts/nickel-validators.ncl +```text + +**Best for:** Ensuring data quality, enforcing business rules, type-safe schemas + +**See also:** [`14-validators-and-contracts/README.md`](14-validators-and-contracts/README.md) for comprehensive guide + +### 16. **Agent + Form Integration** → [`16-agent-form-integration/`](16-agent-form-integration/) + +Human-in-the-loop AI workflows with forms as validation checkpoints. + +**Multi-agent collaboration:** +- Project analyzer (Claude Sonnet) - Initial questionnaire analysis +- Requirements validator (GPT-4o) - Constraint validation +- Recommendations generator (Claude Opus) - Final synthesis and ADRs + +**Workflow:** +1. **Form Input** - Collect project requirements via interactive form +2. **Agent Analysis** - AI evaluates against architecture patterns +3. **User Validation** - Review form with agent-suggested changes +4. **Agent Synthesis** - Final recommendations and ADRs +5. **Output** - Markdown with architecture decisions + +**Key concepts:** +- Agent responsibilities vs form responsibilities +- Human-in-the-loop decision making +- Multi-agent coordination with forms as gates +- JSON data interchange between agents and forms +- LLM provider diversity (Anthropic, OpenAI) + +**Features:** +- 3 agent definitions (.agent.mdx files) +- 3 form definitions (questionnaire, review, feedback) +- Orchestration script (workflow.sh) +- Architecture pattern library +- Validation rules + +**Running the workflow:** +```bash +# Execute complete 6-step workflow +./workflow.sh + +# Or run individual steps +typedialog form architecture-form.toml +typedialog-ag project-architect-1.agent.mdx +``` + +**Best for:** Understanding agent + UI integration, building AI-assisted decision systems, multi-agent workflows, human-in-the-loop AI + +### 17. **Advanced i18n (Multi-Locale)** → [`17-advanced-i18n/`](17-advanced-i18n/) + +Production-grade internationalization with 9+ locales and advanced translation features. + +**9 complete locales:** +- English (en-US, en-GB) - Different spelling, currency +- Spanish (es-ES, es-MX) - Gender-aware strings +- Portuguese (pt-BR, pt-PT) - Fallback chains +- French (fr-FR) - Gender-aware, plurals +- Japanese (ja-JP) - No plural rules +- Arabic (ar-SA) - RTL layout, 6 plural forms + +**Advanced features:** +- **Fluent format** - Complex pluralization, gender, context +- **Fallback chains** - pt-BR → pt → es → en-US +- **Plural handling** - 2-6 forms per language +- **Gender-aware strings** - Spanish, French articles +- **RTL support** - Arabic layout +- **Formatted output** - Numbers ($1,234.56 vs 1.234,56€), dates, addresses +- **Translation coverage matrix** - Track translation status + +**Example use case:** E-commerce checkout form +- Quantities (plural: 1 item, 2-4 items, 5+ items) +- Currency formatting per locale +- Date format localization +- Address format (US vs EU vs Japan) +- Direction handling (LTR vs RTL) + +**Features:** +- Fluent syntax with selectors and functions +- Locale priority and fallback strategy +- Number/date formatting per locale +- Missing translation fallback handling +- Translation maintenance workflow +- Programmatic translation testing + +**Testing all locales:** +```bash +# Test each locale +./test-locales.sh + +# Or test specific locale +LANG=ar-SA cargo run -p typedialog-tui -- checkout-form.toml +``` + +**Best for:** Building global applications, advanced i18n patterns, pluralization and gender agreement, RTL support, production translation workflows + +### 15. **Cross-Backend Same Form** → [`15-cross-backend-same-form/`](15-cross-backend-same-form/) + +Demonstrate the power of TypeDialog's multi-backend architecture with one form definition running on three completely different user interfaces. + +**Architecture demonstrated:** + +One TOML form definition, three backends, identical data output. Only the presentation layer adapts: + +| Aspect | CLI | TUI | Web | +|--------|-----|-----|-----| +| **Interface** | Sequential text prompts | Full terminal UI | HTML/CSS forms | +| **Styling** | Emoji + text | Colors, borders, themes | Custom HTML/CSS | +| **Interaction** | Text selection | Keyboard + mouse | Mouse + keyboard | +| **Complexity** | Simple | Rich visual | Browser-based | +| **Data Output** | ✅ Identical | ✅ Identical | ✅ Identical | + +**Key learning:** + +- Forms are backend-agnostic - define once, deploy anywhere +- Same TOML works on CLI (scripting), TUI (interactive), Web (public) +- Each backend auto-adapts UI components to its strengths +- Output format independent of backend (JSON/YAML/TOML) + +**The employee-registration.toml example includes:** + +- 6 multi-section form with 25+ fields +- All field types: text, select, multiselect, date, confirm, editor +- Form validation (required, min/max) +- Conditional logic (`when` clause for dependencies) +- Visual comparison mockups for each backend + +**Running on each backend:** + +```bash +# CLI - Interactive terminal prompts +cargo run -p typedialog -- --config examples/15-cross-backend-same-form/employee-registration.toml + +# TUI - Full terminal UI with styling +cargo run -p typedialog-tui -- examples/15-cross-backend-same-form/employee-registration.toml + +# Web - Browser-based forms +cargo run -p typedialog-web -- --config examples/15-cross-backend-same-form/employee-registration.toml +# Open http://localhost:3000 +``` + +**Best for:** Understanding multi-backend deployment, choosing the right interface for your use case, building forms that work everywhere, real-world workflows combining multiple backends + +**See also:** [`15-cross-backend-same-form/README.md`](15-cross-backend-same-form/README.md) for visual mockups and detailed backend comparison + ## Learning Path ```text @@ -259,6 +479,18 @@ START HERE └→ Knowledge graph integration ↓ 09-templates/ ← Deploy to production + +OPTIONAL ADVANCED TOPICS + ↓ +11-prov-gen/ ← Infrastructure as Code generation + ↓ +13-conditional-logic/ ← Deep dive on all conditional operators + ↓ +14-validators-and-contracts/ ← Master validation & type-safe contracts + │ +15-cross-backend-same-form/ ← Multi-backend architecture & deployment + │ +12-agent-execution/ ← AI agents with multi-provider LLM support ```text ## Common Tasks @@ -300,6 +532,43 @@ cargo run --example conditional_required_demo LANG=es cargo run --example test_i18n_form ```text +### Explore Validation Patterns +```bash +# Learn basic validation +cargo run -p typedialog -- --config examples/14-validators-and-contracts/basic-validators.toml + +# Try advanced validators with dependencies +cargo run -p typedialog-tui -- examples/14-validators-and-contracts/advanced-validators.toml + +# Master conditional field visibility +cargo run -p typedialog-web -- --config examples/14-validators-and-contracts/conditional-validators.toml +```text + +### Work with Type-Safe Contracts +```bash +# Evaluate Nickel schema +nickel eval examples/14-validators-and-contracts/nickel-validators.ncl + +# Convert to TOML and use with TypeDialog +nickel query examples/14-validators-and-contracts/nickel-validators.ncl inputs | \ + typedialog parse-nickel > nickel-form.toml +```text + +### Compare Multi-Backend Implementations +```bash +# Run the same form on CLI +cargo run -p typedialog -- --config examples/15-cross-backend-same-form/employee-registration.toml + +# Run on TUI +cargo run -p typedialog-tui -- examples/15-cross-backend-same-form/employee-registration.toml + +# Run on Web +cargo run -p typedialog-web -- --config examples/15-cross-backend-same-form/employee-registration.toml +# Open http://localhost:3000 + +# Compare: Fill the form identically on all three backends and check output format consistency +```text + ## File Types ### TOML (`.toml`) @@ -372,9 +641,10 @@ nickel eval schema.ncl > form.toml 1. Read the category README for your use case 2. Copy and modify an example form -3. Consult [`06-integrations/`](06-integrations/) for advanced features -4. Deploy a template from [`09-templates/`](09-templates/) -5. Integrate with your application +3. **Add validation:** See [`14-validators-and-contracts/`](14-validators-and-contracts/) for validation patterns +4. Consult [`06-integrations/`](06-integrations/) for advanced features +5. Deploy a template from [`09-templates/`](09-templates/) +6. Integrate with your application ## Contributing Examples @@ -388,5 +658,7 @@ To add new examples: --- **Start with:** [`01-basic/README.md`](01-basic/README.md) +**Need validation?** See [`14-validators-and-contracts/`](14-validators-and-contracts/) +**Compare backends?** See [`15-cross-backend-same-form/`](15-cross-backend-same-form/) **Need specific backend?** Check [`04-backends/`](04-backends/) **Want real-world example?** See [`09-templates/`](09-templates/)