181 lines
4.6 KiB
Markdown
181 lines
4.6 KiB
Markdown
# Phase 10: i18n (Internationalization)
|
|
|
|
**Status:** ⏳ Todo
|
|
**Progress:** 0/8 tasks (0%)
|
|
**Started:** -
|
|
**Completed:** -
|
|
**Assigned to:** -
|
|
|
|
---
|
|
|
|
## Overview
|
|
|
|
Implement internationalization (i18n) with @nuxtjs/i18n: support German (default) and English, translate all UI strings, and create language switcher.
|
|
|
|
**Goal:** App is fully bilingual (German + English) with proper routing and formatting.
|
|
|
|
---
|
|
|
|
## Dependencies
|
|
|
|
- ✅ Phase 1-9: Most UI components should be created by now
|
|
|
|
---
|
|
|
|
## Tasks
|
|
|
|
### Setup
|
|
|
|
- [ ] Install @nuxtjs/i18n
|
|
|
|
```bash
|
|
pnpm add @nuxtjs/i18n
|
|
```
|
|
|
|
- [ ] Configure i18n module
|
|
- File: `nuxt.config.ts`
|
|
```typescript
|
|
export default defineNuxtConfig({
|
|
modules: ['@nuxtjs/i18n'],
|
|
i18n: {
|
|
locales: [
|
|
{ code: 'de', iso: 'de-DE', name: 'Deutsch', file: 'de-DE.json' },
|
|
{ code: 'en', iso: 'en-US', name: 'English', file: 'en-US.json' },
|
|
],
|
|
defaultLocale: 'de',
|
|
strategy: 'prefix_except_default',
|
|
langDir: 'locales',
|
|
lazy: true,
|
|
detectBrowserLanguage: {
|
|
useCookie: true,
|
|
cookieKey: 'i18n_redirected',
|
|
redirectOn: 'root',
|
|
},
|
|
},
|
|
})
|
|
```
|
|
|
|
### Translation Files
|
|
|
|
- [ ] Create locale files (de-DE.json, en-US.json)
|
|
- Create: `locales/de-DE.json` (German)
|
|
- Create: `locales/en-US.json` (English)
|
|
- Structure:
|
|
|
|
```json
|
|
{
|
|
"common": {
|
|
"header": { "home": "Startseite", "products": "Produkte", ... },
|
|
"footer": { ... },
|
|
"buttons": { "submit": "Absenden", "cancel": "Abbrechen", ... }
|
|
},
|
|
"auth": {
|
|
"login": { "title": "Anmelden", "email": "E-Mail", ... },
|
|
"register": { ... }
|
|
},
|
|
"products": { ... },
|
|
"cart": { ... },
|
|
"checkout": { ... },
|
|
"errors": { ... }
|
|
}
|
|
```
|
|
|
|
- [ ] Translate all UI strings
|
|
- Go through all components and pages
|
|
- Replace hardcoded German strings with `$t('key')` or `t('key')`
|
|
- Add translations to both de-DE.json and en-US.json
|
|
- Components to translate:
|
|
- Header, Footer
|
|
- Auth forms (Login, Register)
|
|
- Product list, Product detail
|
|
- Cart, CartItem, CartSummary
|
|
- Checkout form
|
|
- PayPal button texts
|
|
- Error messages
|
|
- Success messages
|
|
- Validation messages (VeeValidate)
|
|
|
|
### UI Components
|
|
|
|
- [ ] Create language switcher component
|
|
- File: `components/Common/LanguageSwitcher.vue`
|
|
- Dropdown or toggle: 🇩🇪 Deutsch | 🇬🇧 English
|
|
- Uses: `$i18n.locale` and `$switchLocalePath()`
|
|
- Place in header
|
|
- Styling: shadcn-nuxt DropdownMenu or simple buttons
|
|
|
|
### Testing
|
|
|
|
- [ ] Test route localization
|
|
- Visit /produkte (German)
|
|
- Switch to English → should redirect to /en/products
|
|
- Test all main routes:
|
|
- / → /en/ (homepage)
|
|
- /produkte → /en/products
|
|
- /warenkorb → /en/cart
|
|
- /kasse → /en/checkout
|
|
- Verify route parameters preserved (/produkte/[id] → /en/products/[id])
|
|
|
|
- [ ] Test currency/date formatting
|
|
- Use Intl.NumberFormat for currency (EUR)
|
|
- Use Intl.DateTimeFormat for dates
|
|
- Example in component:
|
|
|
|
```typescript
|
|
const { locale } = useI18n()
|
|
const formatPrice = (price: number) => {
|
|
return new Intl.NumberFormat(locale.value, {
|
|
style: 'currency',
|
|
currency: 'EUR',
|
|
}).format(price)
|
|
}
|
|
```
|
|
|
|
- Test: German → "19,99 €", English → "€19.99"
|
|
|
|
- [ ] Document i18n structure
|
|
- Document translation file structure
|
|
- Document how to add new translations
|
|
- Document naming conventions for translation keys
|
|
- Document how language switcher works
|
|
- Document how to format currency/dates per locale
|
|
|
|
---
|
|
|
|
## Acceptance Criteria
|
|
|
|
- [x] @nuxtjs/i18n is installed and configured
|
|
- [x] Locale files exist for German and English
|
|
- [x] All UI strings are translated (no hardcoded German text)
|
|
- [x] Language switcher component is functional
|
|
- [x] Can switch between German and English
|
|
- [x] Routes change with language (/produkte ↔ /en/products)
|
|
- [x] Currency formatting respects locale
|
|
- [x] Date formatting respects locale
|
|
- [x] i18n structure is documented
|
|
|
|
---
|
|
|
|
## Notes
|
|
|
|
- **Default Language:** German (de)
|
|
- **Route Strategy:** prefix_except_default (German has no prefix, English has /en/)
|
|
- **SEO:** Automatic hreflang tags for SEO
|
|
- **Lazy Loading:** Translation files loaded on demand
|
|
- **Browser Detection:** Redirects to browser language on first visit (if supported)
|
|
|
|
---
|
|
|
|
## Blockers
|
|
|
|
- None currently
|
|
|
|
---
|
|
|
|
## Related Documentation
|
|
|
|
- [docs/PRD.md: Bilingual Support](../docs/PRD.md#bilingual-support)
|
|
- [docs/TECH_STACK.md: i18n](../docs/TECH_STACK.md#9-internationalization-i18n)
|
|
- [CLAUDE.md: Important Constraints](../CLAUDE.md#important-constraints)
|
|
- [@nuxtjs/i18n Docs](https://i18n.nuxtjs.org/)
|