# Internationalization (i18n)

Complete multilingual support for Ackify frontend.

## Supported Languages

- 🇫🇷 **Français** (default)
- 🇬🇧 **English** (fallback)
- 🇪🇸 **Español**
- 🇩🇪 **Deutsch**
- 🇮🇹 **Italiano**

## Frontend (Vue.js)

### Language Selection

The frontend automatically detects language via:

1. **localStorage** - Saved user choice
2. **navigator.language** - Browser language
3. **Fallback** - English if not supported

### Language Switcher

User interface with Unicode flags:

```
🇫🇷 FR | 🇬🇧 EN | 🇪🇸 ES | 🇩🇪 DE | 🇮🇹 IT
```

Click → Language changes + saves to localStorage

### Translation Files

Located in `/webapp/src/locales/`:

```
locales/
├── fr.json    # Français
├── en.json    # English
├── es.json    # Español
├── de.json    # Deutsch
└── it.json    # Italiano
```

### JSON Structure

```json
{
  "home": {
    "title": "Ackify - Proof of Read",
    "subtitle": "Cryptographic read signatures"
  },
  "document": {
    "sign": "Sign this document",
    "signed": "Document signed",
    "signatures": "{count} confirmation | {count} confirmations"
  }
}
```

**Pluralization**:
```json
"signatures": "{count} confirmation | {count} confirmations"
```

Usage:
```vue
{{ $t('document.signatures', { count: 42 }) }}
// → "42 confirmations"
```

## Backend (Go)

### Email Templates

Emails use multilingual templates in `/backend/templates/emails/`:

```
templates/emails/
├── fr/
│   ├── reminder.html
│   └── reminder.txt
├── en/
│   ├── reminder.html
│   └── reminder.txt
├── es/...
├── de/...
└── it/...
```

### Sending with Locale

```http
POST /api/v1/admin/documents/doc_id/reminders
Content-Type: application/json

{
  "emails": ["user@company.com"],
  "locale": "fr"
}
```

Backend loads template `fr/reminder.html`.

### Configuration

```bash
# Default language for emails (default: en)
ACKIFY_MAIL_DEFAULT_LOCALE=fr
```

## Adding a Language

### Frontend

1. **Create translation file**:

```bash
cd webapp/src/locales
cp en.json pt.json  # Portuguese
```

2. **Translate**:

```json
{
  "home": {
    "title": "Ackify - Prova de Leitura",
    "subtitle": "Assinaturas criptográficas de leitura"
  }
}
```

3. **Register in i18n**:

```typescript
// webapp/src/i18n.ts
import pt from './locales/pt.json'

const i18n = createI18n({
  locale: 'fr',
  fallbackLocale: 'en',
  messages: {
    fr, en, es, de, it,
    pt  // Add here
  }
})
```

4. **Add to selector**:

```vue
<!-- components/LanguageSwitcher.vue -->
<button @click="changeLocale('pt')">🇵🇹 PT</button>
```

### Backend

1. **Create directory**:

```bash
mkdir -p backend/templates/emails/pt
```

2. **Create templates**:

```bash
cp backend/templates/emails/en/reminder.html backend/templates/emails/pt/
cp backend/templates/emails/en/reminder.txt backend/templates/emails/pt/
```

3. **Translate templates**

4. **Rebuild**:

```bash
docker compose up -d --force-recreate ackify-ce --build
```

## i18n Verification

### Validation Script

Project includes a script to verify translation completeness:

```bash
cd webapp
npm run lint:i18n
```

**Output**:
```
✅ fr.json - 156 keys
✅ en.json - 156 keys
✅ es.json - 156 keys
✅ de.json - 156 keys
✅ it.json - 156 keys

All translations are complete!
```

### CI/CD

Script automatically runs in GitHub Actions to block PRs with missing translations.

## Best Practices

### Translation Keys

- ✅ Use structured keys: `feature.action.label`
- ✅ Group by page/component
- ✅ Avoid too generic keys (`button`, `title`)
- ✅ Use placeholders: `{count}`, `{name}`

**Example**:
```json
{
  "admin": {
    "documents": {
      "list": {
        "title": "Document list",
        "count": "{count} document | {count} documents"
      }
    }
  }
}
```

### Synchronization

When adding new keys in French:

```bash
# Sync script (to create)
node scripts/sync-i18n-from-fr.js
```

Automatically copies new keys to other languages with `[TODO]`.

### Long Texts

For long texts, use arrays:

```json
{
  "help": {
    "intro": [
      "Ackify allows creating cryptographic signatures.",
      "Each signature is timestamped and non-repudiable.",
      "Data is stored immutably."
    ]
  }
}
```

Usage:
```vue
<p v-for="line in $tm('help.intro')" :key="line">
  {{ line }}
</p>
```

## Specific Formats

### Dates

```typescript
// Format with current locale
import { useI18n } from 'vue-i18n'

const { locale } = useI18n()
const formatted = new Date().toLocaleDateString(locale.value, {
  year: 'numeric',
  month: 'long',
  day: 'numeric'
})
// fr: "15 janvier 2025"
// en: "January 15, 2025"
```

### Numbers

```typescript
const formatted = (42000).toLocaleString(locale.value)
// fr: "42 000"
// en: "42,000"
```

## SEO & Meta Tags

Meta tags are dynamically translated:

```vue
<script setup>
import { useI18n } from 'vue-i18n'
import { useHead } from '@vueuse/head'

const { t } = useI18n()

useHead({
  title: t('home.title'),
  meta: [
    { name: 'description', content: t('home.description') }
  ]
})
</script>
```

## Complete Documentation

For more details on frontend i18n implementation, see:

**[webapp/I18N.md](../../webapp/I18N.md)**

This file contains:
- Complete vue-i18n architecture
- Contribution guide
- Synchronization scripts
- Advanced examples
