# Internationalization (i18n) in Fabric

Fabric supports multiple languages through its internationalization system. The system automatically detects your preferred language from environment variables and provides localized messages.

## How Locale Detection Works

Fabric follows POSIX standards for locale detection with the following priority order:

1. **Explicit language flag**: `--language` or `-g` (highest priority)
2. **LC_ALL**: Complete locale override environment variable
3. **LC_MESSAGES**: Messages-specific locale environment variable
4. **LANG**: General locale environment variable
5. **Default fallback**: English (`en`) if none are set or valid

### Examples

```bash
# Use explicit language flag
fabric --language es --pattern summarize

# Use LC_ALL environment variable
LC_ALL=fr_FR.UTF-8 fabric --pattern summarize

# Use LANG environment variable
LANG=de_DE.UTF-8 fabric --pattern summarize

# Multiple environment variables (LC_ALL takes priority)
LC_ALL=es_ES.UTF-8 LANG=fr_FR.UTF-8 fabric --pattern summarize
# Uses Spanish (es_ES) because LC_ALL has higher priority
```

## Supported Locale Formats

The system automatically normalizes various locale formats:

- `en_US.UTF-8` → `en-US`
- `fr_FR@euro` → `fr-FR`
- `zh_CN.GB2312` → `zh-CN`
- `de_DE.UTF-8@traditional` → `de-DE`

Special cases:

- `C` or `POSIX` → treated as invalid, falls back to English

## Translation File Locations

Translations are loaded from multiple sources in this order:

1. **Embedded files** (highest priority): Compiled into the binary
   - Location: `internal/i18n/locales/*.json`
   - Always available, no download required

2. **User config directory**: Downloaded on demand
   - Location: `~/.config/fabric/locales/`
   - Downloaded from GitHub when needed

3. **GitHub repository**: Source for downloads
   - URL: `https://raw.githubusercontent.com/danielmiessler/Fabric/main/internal/i18n/locales/`

## Currently Supported Languages

- **English** (`en`): Default language, always available
- **Spanish** (`es`): Available in embedded files

## Adding New Languages

To add support for a new language:

1. Create a new JSON file: `internal/i18n/locales/{lang}.json`
2. Add translations in the format:

   ```json
   {
     "message_id": "localized message text"
   }
   ```

3. Rebuild Fabric to embed the new translations

### Translation File Format

Translation files use JSON format with message IDs as keys:

```json
{
  "html_readability_error": "use original input, because can't apply html readability"
}
```

Spanish example:

```json
{
  "html_readability_error": "usa la entrada original, porque no se puede aplicar la legibilidad de html"
}
```

## Error Handling

The i18n system is designed to be robust:

- **Download failures**: Non-fatal, falls back to embedded translations
- **Invalid locales**: Skipped, next priority locale used
- **Missing translations**: Falls back to English
- **Missing files**: Uses embedded defaults

Error messages are logged to stderr but don't prevent operation.

## Environment Variable Examples

### Common Unix Locale Settings

```bash
# Set system-wide locale
export LANG=en_US.UTF-8

# Override all locale categories
export LC_ALL=fr_FR.UTF-8

# Set only message locale (for this session)
LC_MESSAGES=es_ES.UTF-8 fabric --pattern summarize

# Check current locale settings
locale
```

### Testing Locale Detection

You can test locale detection without changing your system settings:

```bash
# Test with French
LC_ALL=fr_FR.UTF-8 fabric --version

# Test with Spanish (if available)
LC_ALL=es_ES.UTF-8 fabric --version

# Test with German (will download if available)
LC_ALL=de_DE.UTF-8 fabric --version
```

## Troubleshooting

### "i18n download failed" messages

This is normal when requesting a language not yet available. The system will fall back to English.

### Locale not detected

Check your environment variables:

```bash
echo $LC_ALL
echo $LC_MESSAGES
echo $LANG
```

Ensure they're in a valid format like `en_US.UTF-8` or `fr_FR`.

### Wrong language used

Remember the priority order:

1. `--language` flag overrides everything
2. `LC_ALL` overrides `LC_MESSAGES` and `LANG`
3. `LC_MESSAGES` overrides `LANG`

## Implementation Details

The locale detection system:

- Uses `golang.org/x/text/language` for parsing and validation
- Follows BCP 47 language tag standards
- Implements POSIX locale environment variable precedence
- Provides comprehensive test coverage
- Handles edge cases gracefully

For developers working on the codebase, see the implementation in:

- `internal/i18n/locale.go`: Locale detection logic
- `internal/i18n/i18n.go`: Main i18n initialization
- `internal/i18n/locale_test.go`: Test suite
