Vue I18n
vue-i18n
Composable leggero per internazionalizzazione Vue 3 con lazy loading e cache.
Panoramica
@pzeta/vue-i18n è un sistema i18n leggero per Vue 3 senza dipendenze da vue-i18n. Supporta:
- Lazy loading delle traduzioni per lingua
- Dizionario pre-caricato per la lingua di default (bundle iniziale)
- Cache automatica delle lingue già caricate
- Interpolazione con parametri
{name} - Fallback locale configurabile
- Pattern latest-wins per cambio lingua concorrente
Installazione
npm install @pzeta/vue-i18n
Configurazione
Chiamare configureI18n() una sola volta prima di montare l'app:
// main.ts
import { configureI18n } from '@pzeta/vue-i18n'
import itLocale from './locales/it'
configureI18n({
defaultLocale: 'it',
fallbackLocale: 'it',
locales: {
it: {
// Preloaded: incluso nel bundle, nessun fetch aggiuntivo
loader: () => Promise.resolve({ default: itLocale }),
preloaded: itLocale,
},
en: {
// Lazy: caricato solo quando richiesto
loader: () => import('./locales/en'),
},
de: {
loader: () => import('./locales/de'),
},
},
onLocaleChange: (locale) => {
document.documentElement.lang = locale
localStorage.setItem('locale', locale)
},
warnPrefix: '[my-app]',
})
I18nConfig
| Campo | Tipo | Default | Descrizione |
|---|---|---|---|
defaultLocale | string | — | Lingua iniziale |
fallbackLocale | string | — | Fallback se traduzione mancante |
locales | Record<locale, LocaleConfig> | — | Configurazione per ogni lingua |
onLocaleChange | (locale) => void | — | Callback al cambio lingua |
warnPrefix | string | '[i18n]' | Prefisso warning console |
useI18n
import { useI18n } from '@pzeta/vue-i18n'
const { t, locale, isLoading, setLocale, translations } = useI18n()
Traduzione semplice
t('pages.home.title')
// → "Home"
Traduzione con parametri
I parametri usano la sintassi {nomeparametro}:
t('common.greeting', { name: 'Mario' })
// locale: { common: { greeting: 'Ciao {name}!' } }
// → "Ciao Mario!"
t('common.counter', { count: 3, total: 10 })
// locale: { common: { counter: '{count} di {total} elementi' } }
// → "3 di 10 elementi"
Cambio lingua
// Lazy load + cache automatica
await setLocale('en')
// isLoading.value = true durante il fetch
// Al secondo cambio alla stessa lingua: cache hit, sincrono
Traduzione mancante
Se la chiave non esiste, t() restituisce la chiave stessa e lancia un console.warn:
[my-app] Traduzione mancante: "pages.missing.key"
Struttura file traduzioni
// locales/it.ts
export default {
common: {
save: 'Salva',
cancel: 'Annulla',
greeting: 'Ciao {name}!',
},
pages: {
home: { title: 'Home' },
users: { title: 'Utenti', count: '{count} utenti' },
},
}
TypeScript — dizionario tipato
import type { TranslationDictionary } from '@pzeta/vue-i18n'
import itLocale from './locales/it'
type AppDict = typeof itLocale
// useI18n con tipo — t() autocompleta le chiavi
const { t } = useI18n<'it' | 'en', AppDict>()
Utility loader
import { loadLocale, isLocaleLoaded, getLocaleFromCache } from '@pzeta/vue-i18n'
// Precarica una lingua senza cambiarla
await loadLocale('en')
// Controlla se già in cache
if (isLocaleLoaded('en')) { ... }
// Accesso diretto alla cache
const dict = getLocaleFromCache('en')
Testing
import { initI18n, resetI18n } from '@pzeta/vue-i18n'
beforeEach(() => initI18n({ it: { greeting: 'Ciao {name}!' } }))
afterEach(() => resetI18n())
initI18n e resetI18n sono utility specifiche per test — non usarle in produzione.