Skip to main content
Internationalization with message translation, token resolution, and locale selection.

Features

  • Locale selection with createSingle
  • Token-based message storage with useTokens
  • Numbered and named placeholder support
  • Number formatting with Intl.NumberFormat
  • Nested message structures
  • Cross-locale references

Installation

import { createLocalePlugin } from '@vuetify/v0'

const app = createApp(App)
app.use(createLocalePlugin({
  default: 'en',
  messages: {
    en: {
      hello: 'Hello',
      greeting: 'Hello {name}',
    },
    es: {
      hello: 'Hola',
      greeting: 'Hola {name}',
    },
  },
}))

Basic Usage

<script setup lang="ts">
import { useLocale } from '@vuetify/v0'

const locale = useLocale()
</script>

<template>
  <div>
    <p>{{ locale.t('hello') }}</p>
    <p>{{ locale.t('greeting', { name: 'World' }) }}</p>
    
    <button @click="locale.select('es')">Español</button>
  </div>
</template>

API Reference

createLocalePlugin()

Creates a locale plugin.
options
LocalePluginOptions
Plugin configuration
default
ID
Default locale ID to select on initialization
messages
Record<ID, LocaleRecord>
Record of locale messagesExample:
{
  en: {
    hello: 'Hello',
    goodbye: 'Goodbye',
  },
  es: {
    hello: 'Hola',
    goodbye: 'Adiós',
  },
}
adapter
LocaleAdapter
Custom locale adapter (defaults to Vuetify0LocaleAdapter)
namespace
string
default:"'v0:locale'"
The namespace for the locale context

LocaleContext

size
number
Number of registered locales
selectedId
Ref<ID | undefined>
Currently selected locale ID
select
(id: ID) => void
Select a localeExample:
locale.select('es')
t
(key: string, params?: Record<string, unknown>, fallback?: string) => string
Translate a message key with optional parameters and fallbackParameters:
  • key: Message key to look up (e.g., ‘hello’, ‘Pagination.goToPage’)
  • params: Object with named parameters for interpolation
  • fallback: Fallback string if key not found
Examples:
locale.t('hello') // 'Hello'
locale.t('greeting', { name: 'World' }) // 'Hello World'
locale.t('missing.key', {}, 'Default text') // 'Default text'
n
(value: number) => string
Format a number according to current localeExample:
locale.n(1234.56) // '1,234.56' (en-US)
locale.n(1234.56) // '1.234,56' (de-DE)
register
(registration: Partial<LocaleTicketInput>) => LocaleTicket
Register a new localeExample:
locale.register({
  id: 'fr',
})
get
(id: ID) => LocaleTicket | undefined
Get a locale by ID
has
(id: ID) => boolean
Check if a locale exists

Message Formats

Simple Messages

app.use(createLocalePlugin({
  default: 'en',
  messages: {
    en: {
      hello: 'Hello',
      goodbye: 'Goodbye',
    },
  },
}))

// Usage
const locale = useLocale()
locale.t('hello') // 'Hello'

Named Placeholders

messages: {
  en: {
    greeting: 'Hello {name}',
    info: 'You have {count} messages',
  },
}

// Usage
locale.t('greeting', { name: 'John' }) // 'Hello John'
locale.t('info', { count: 5 }) // 'You have 5 messages'

Nested Messages

messages: {
  en: {
    Pagination: {
      goToPage: 'Go to page {page}',
      currentPage: 'Page {page}, current',
    },
  },
}

// Usage
locale.t('Pagination.goToPage', { page: 5 }) // 'Go to page 5'
locale.t('Pagination.currentPage', { page: 3 }) // 'Page 3, current'

Token References

messages: {
  en: {
    app: 'My App',
    version: '1.0',
    title: '{app} v{version}',
    welcome: 'Welcome to {title}',
  },
}

// Usage
locale.t('title') // 'My App v1.0'
locale.t('welcome') // 'Welcome to My App v1.0'

Locale Switching

<script setup lang="ts">
import { useLocale } from '@vuetify/v0'

const locale = useLocale()

const languages = [
  { id: 'en', name: 'English' },
  { id: 'es', name: 'Español' },
  { id: 'fr', name: 'Français' },
]
</script>

<template>
  <div>
    <select @change="locale.select($event.target.value)">
      <option 
        v-for="lang in languages" 
        :key="lang.id"
        :value="lang.id"
        :selected="locale.selectedId.value === lang.id"
      >
        {{ lang.name }}
      </option>
    </select>
    
    <p>{{ locale.t('hello') }}</p>
  </div>
</template>

Fallback Messages

const locale = useLocale()

// With fallback
locale.t('missing.key', {}, 'Default text') // 'Default text'

// Without fallback (returns key)
locale.t('missing.key') // 'missing.key'

Number Formatting

<script setup lang="ts">
import { useLocale } from '@vuetify/v0'

const locale = useLocale()

const price = 1234.56
</script>

<template>
  <div>
    <p>Price: {{ locale.n(price) }}</p>
  </div>
</template>

Advanced Usage

Custom Adapter

import { Vuetify0LocaleAdapter } from '@vuetify/v0'
import type { LocaleAdapter } from '@vuetify/v0'

class MyLocaleAdapter extends Vuetify0LocaleAdapter implements LocaleAdapter {
  t(str: string, ...params: unknown[]): string {
    // Custom translation logic
    return super.t(str, ...params)
  }
}

app.use(createLocalePlugin({
  adapter: new MyLocaleAdapter(),
  messages: { /* ... */ },
}))

Dynamic Message Loading

const locale = useLocale()

// Load messages dynamically
const loadMessages = async (localeId: string) => {
  const messages = await import(`./locales/${localeId}.json`)
  locale.register({ id: localeId })
  // Messages are loaded via the plugin
}

await loadMessages('fr')
locale.select('fr')

Integration with useDate

import { useLocale, useDate } from '@vuetify/v0'

const locale = useLocale()
const { adapter: dateAdapter } = useDate()

// Both will use the same locale
locale.select('de')

const date = dateAdapter.date()
const formatted = dateAdapter.format(date, 'fullDate')
// Formatted in German

Build docs developers (and LLMs) love