Das Problem
Sie haben eine schöne Vue-App gebaut. Jetzt sagt Ihr Produktteam "wir müssen Spanisch, Französisch und Deutsch unterstützen."
Wo fangen Sie überhaupt an? Wie macht man:
- Alle hardcoded Strings extrahieren?
- Sprachen wechseln ohne Seitenreload?
- Plurale in jeder Sprache unterschiedlich behandeln?
Dieser Guide führt durch alles mit vue-i18n, der offiziellen Vue-Lokalisierungsbibliothek.
Schritt 1: vue-i18n installieren
Terminalnpm install vue-i18n@9
Schritt 2: Übersetzungsdateien erstellen
src/
├── locales/
│ ├── de.json
│ ├── en.json
│ └── es.json
└── i18n.ts
de.json:
JSON1{ 2 "nav": { 3 "home": "Startseite", 4 "about": "Über uns", 5 "pricing": "Preise" 6 }, 7 "hero": { 8 "title": "Apps schneller bauen", 9 "subtitle": "Features liefern die Ihre Nutzer lieben", 10 "cta": "Jetzt starten" 11 }, 12 "product": { 13 "addToCart": "In den Warenkorb", 14 "itemCount": "Keine Artikel | {n} Artikel | {n} Artikel", 15 "price": "{amount} pro Monat" 16 } 17}
Schritt 3: vue-i18n konfigurieren
TypeScript1import { createI18n } from 'vue-i18n'; 2import de from './locales/de.json'; 3import en from './locales/en.json'; 4 5export const i18n = createI18n({ 6 legacy: false, // Composition API Modus 7 locale: 'de', 8 fallbackLocale: 'en', 9 messages: { de, en }, 10});
Schritt 4: In Komponenten verwenden
VUE1<script setup> 2import { useI18n } from 'vue-i18n'; 3const { t } = useI18n(); 4</script> 5 6<template> 7 <nav> 8 <a href="/">{{ $t('nav.home') }}</a> 9 <a href="/about">{{ $t('nav.about') }}</a> 10 </nav> 11 12 <section> 13 <h1>{{ $t('hero.title') }}</h1> 14 <button>{{ $t('hero.cta') }}</button> 15 </section> 16</template>
Pluralisierung
JSON1{ 2 "product": { 3 "itemCount": "Keine Artikel | {n} Artikel | {n} Artikel" 4 } 5}
VUE1<template> 2 <p>{{ $t('product.itemCount', count) }}</p> 3 <!-- count=0: "Keine Artikel" --> 4 <!-- count=1: "1 Artikel" --> 5 <!-- count=5: "5 Artikel" --> 6</template>
Datum, Zahlen, Währungen formatieren
VUE1<script setup> 2import { useI18n } from 'vue-i18n'; 3const { n, d } = useI18n(); 4const price = 1299.99; 5const date = new Date('2026-01-15'); 6</script> 7 8<template> 9 <!-- Zahlenformatierung --> 10 <p>{{ n(price, 'currency') }}</p> 11 <!-- de: "1.299,99 €" --> 12 13 <!-- Datumsformatierung --> 14 <p>{{ d(date, 'long') }}</p> 15 <!-- de: "15. Januar 2026" --> 16</template>
Sprache wechseln
VUE1<script setup> 2import { useI18n } from 'vue-i18n'; 3const { locale, availableLocales } = useI18n(); 4 5const changeLanguage = (lang: string) => { 6 locale.value = lang; 7 localStorage.setItem('user-locale', lang); 8}; 9</script> 10 11<template> 12 <div class="language-switcher"> 13 <button 14 v-for="lang in availableLocales" 15 :key="lang" 16 @click="changeLanguage(lang)" 17 > 18 {{ lang.toUpperCase() }} 19 </button> 20 </div> 21</template>
Lazy Loading
TypeScript1export async function loadLocale(locale: string) { 2 const messages = await import(`./locales/${locale}.json`); 3 i18n.global.setLocaleMessage(locale, messages.default); 4} 5 6export async function setLocale(locale: string) { 7 await loadLocale(locale); 8 i18n.global.locale.value = locale; 9}
SEO-freundliche URLs mit Vue Router
TypeScript1const routes = [ 2 { 3 path: '/:locale', 4 component: () => import('./layouts/LocaleLayout.vue'), 5 children: [ 6 { path: '', name: 'home', component: () => import('./views/Home.vue') }, 7 { path: 'products', name: 'products', component: () => import('./views/Products.vue') }, 8 ], 9 }, 10 { path: '/', redirect: '/de' }, 11];
Mit IntlPull verbinden
Terminalnpm install -D @intlpullhq/cli
Terminalnpx @intlpullhq/cli upload npx @intlpullhq/cli download
Vorteile:
- ✅ Übersetzer arbeiten in einer UI, nicht JSON
- ✅ Translation Memory spart Kosten
- ✅ KI Pre-Übersetzung für neue Keys
