# 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.
