# Internationalization (i18n) Guide

## Overview

mpp-ui supports internationalization with English and Chinese (Simplified) languages across all platforms (JVM Desktop, Android, Node.js CLI).

## Architecture

The i18n implementation is split into two parts:

### 1. TypeScript/React (CLI)

Located in `src/jsMain/typescript/i18n/`:

- **`index.ts`**: Main i18n module with `t()` function
- **`types.ts`**: TypeScript type definitions
- **`locales/en.ts`**: English translations
- **`locales/zh.ts`**: Chinese translations

**Features:**
- Simple `t()` function for translations
- String interpolation support: `t('key', { param: 'value' })`
- Automatic system language detection
- Persistent language preference in `~/.autodev/config.yaml`
- No external dependencies

**Usage:**
```typescript
import { t } from '../i18n/index.js';

// Simple translation
<Text>{t('common.save')}</Text>

// With parameters
<Text>{t('modelConfig.defaultHint', { default: 'gpt-4' })}</Text>
```

### 2. Kotlin Multiplatform (Compose)

Located in `src/commonMain/kotlin/cc/unitmesh/devins/ui/i18n/`:

- **`I18n.kt`**: Translation strings and language enum
- **`LanguageManager.kt`**: Language preference management
- **`LanguageSwitcher.kt`**: UI component for language switching

**Features:**
- Object-based string access (`Strings.save`)
- Type-safe language selection
- StateFlow for reactive language changes
- Persistent language preference

**Usage:**
```kotlin
import cc.unitmesh.devins.ui.i18n.Strings

// Simple usage
Text(Strings.save)

// With parameters
Text(Strings.failedToLoadConfigs("File not found"))

// Language switching
LanguageManager.setLanguage(Language.CHINESE)
```

## Supported Languages

| Language | Code | Display Name |
|----------|------|--------------|
| English | `en` | English |
| Chinese (Simplified) | `zh` | 中文 |

## Adding New Languages

### TypeScript (CLI)

1. Create new locale file: `src/jsMain/typescript/i18n/locales/[lang].ts`

```typescript
import type { TranslationKeys } from '../types.js';

export const fr: TranslationKeys = {
  common: {
    save: 'Enregistrer',
    cancel: 'Annuler',
    // ...
  },
  // ...
};
```

2. Update `index.ts`:

```typescript
import { fr } from './locales/fr.js';

const translations: Record<SupportedLanguage, TranslationKeys> = {
  en,
  zh,
  fr,  // Add new language
};
```

3. Update `types.ts`:

```typescript
export type SupportedLanguage = 'en' | 'zh' | 'fr';
```

### Kotlin (Compose)

1. Add new language to enum in `I18n.kt`:

```kotlin
enum class Language(val code: String, val displayName: String) {
    ENGLISH("en", "English"),
    CHINESE("zh", "中文"),
    FRENCH("fr", "Français"),  // Add new language
}
```

2. Create translation object:

```kotlin
private object FrenchStrings : Map<String, String> by mapOf(
    "common.save" to "Enregistrer",
    "common.cancel" to "Annuler",
    // ...
)
```

3. Register in translations map:

```kotlin
private val translations = mapOf(
    Language.ENGLISH to EnglishStrings,
    Language.CHINESE to ChineseStrings,
    Language.FRENCH to FrenchStrings,  // Add new language
)
```

## Adding New Translation Keys

### TypeScript

1. Update `types.ts` with new keys:

```typescript
export interface TranslationKeys {
  common: {
    save: string;
    newKey: string;  // Add new key
  };
  // ...
}
```

2. Add translations in `locales/en.ts` and `locales/zh.ts`:

```typescript
export const en: TranslationKeys = {
  common: {
    save: 'Save',
    newKey: 'New Feature',  // English translation
  },
};
```

### Kotlin

1. Add property to `Strings` object in `I18n.kt`:

```kotlin
object Strings {
    // ...
    val newKey: String get() = get("common.newKey")
}
```

2. Add translations to both language objects:

```kotlin
private object EnglishStrings : Map<String, String> by mapOf(
    // ...
    "common.newKey" to "New Feature",
)

private object ChineseStrings : Map<String, String> by mapOf(
    // ...
    "common.newKey" to "新功能",
)
```

## Language Switching

### CLI (TypeScript)

Users can switch language by:

1. Setting `language` field in `~/.autodev/config.yaml`:
```yaml
language: zh
```

2. Using the language switcher component (if integrated):
```typescript
import { LanguageSwitcher } from './ui/LanguageSwitcher.js';

<LanguageSwitcher onLanguageChange={(lang) => console.log('Language changed to:', lang)} />
```

### Desktop/Android (Kotlin)

Add the `LanguageSwitcher` component to your UI:

```kotlin
import cc.unitmesh.devins.ui.compose.settings.LanguageSwitcher

LanguageSwitcher()
```

The language preference is automatically persisted and restored on app restart.

## Language Detection

### CLI
- Reads from `~/.autodev/config.yaml`
- Falls back to system locale (`LANG` environment variable)
- Defaults to English if detection fails

### Desktop/Android
- Reads from config file
- Falls back to system locale (platform-specific)
- Defaults to English if detection fails

## Best Practices

1. **Always use translation functions**: Never hardcode user-facing strings
   ```typescript
   // ✅ Good
   <Text>{t('common.save')}</Text>
   
   // ❌ Bad
   <Text>Save</Text>
   ```

2. **Use descriptive keys**: Make keys self-documenting
   ```typescript
   // ✅ Good
   t('modelConfig.enterApiKey')
   
   // ❌ Bad
   t('field3')
   ```

3. **Group related keys**: Organize keys by feature/component
   ```typescript
   common.save
   common.cancel
   modelConfig.title
   modelConfig.provider
   ```

4. **Provide context for translators**: Use parameters for dynamic content
   ```typescript
   t('messages.failedToLoad', { error: errorMessage })
   ```

5. **Test all languages**: Ensure UI layout works with different text lengths

## Translation Coverage

Current translation coverage:

### ✅ Fully Translated
- Welcome screen
- Model configuration form
- Chat interface
- Command processor messages
- Model selector
- Model configuration dialog
- Chat top bar

### 🚧 Partially Translated
- Error messages (some still hardcoded)
- Debug dialogs
- File chooser messages

### ⏳ Not Yet Translated
- Code editor syntax
- Markdown rendering
- System-generated messages

## Testing

### TypeScript
```bash
cd mpp-ui
npm run build:ts
node dist/index.js
```

Set language in config:
```bash
echo "language: zh" >> ~/.autodev/config.yaml
```

### Kotlin
```bash
./gradlew :mpp-ui:run
```

Language will be detected from system locale or can be changed via UI.

## Performance

- Translations are loaded at startup
- No runtime overhead for translation lookups
- Language switching requires UI re-render but no data reload

## Future Enhancements

- [ ] Add more languages (Japanese, Korean, Spanish, French, German)
- [ ] Support RTL languages (Arabic, Hebrew)
- [ ] Pluralization support
- [ ] Date/time formatting
- [ ] Number formatting
- [ ] Translation management UI
- [ ] Automatic translation validation
- [ ] Translation completion checker

## Resources

- [Translation Keys Reference](./I18N_KEYS.md)
- [Language Detection Logic](./I18N_DETECTION.md)
- [Contributing Translations](../CONTRIBUTING.md#translations)

