X Enterprises
nuxt-x-affiliate

Locale Provider

Multi-language support wrapper. Provides locale state to descendant components, persists choice in a cookie, dispatches a window event on switch, and renders an optional built-in footer switcher.

Locale Provider

The XAFLocaleProvider component sets up multi-language support for the whole app. Wrap your app's root layout with it, then use useXafLocale() from any descendant to read or change the locale.

Components

<XAFLocaleProvider />

<!-- app.vue -->
<template>
  <XAFLocaleProvider v-model="locale" :locales="supportedLocales">
    <NuxtLayout>
      <NuxtPage />
    </NuxtLayout>
  </XAFLocaleProvider>
</template>

<script setup lang="ts">
const locale = ref("en")
const supportedLocales = [
  { code: "en", label: "English", flag: "🇺🇸" },
  { code: "es", label: "Español", flag: "🇪🇸" },
  { code: "fr", label: "Français", flag: "🇫🇷" },
  { code: "ja", label: "日本語", flag: "🇯🇵" },
]
</script>

Props

PropTypeDefaultDescription
modelValuestringrequiredTwo-way bound current locale code
localesXafLocaleOption[]9 common locales (en, es, fr, de, pt, it, ja, zh, ar)Available locales
defaultLocalestringfirst locale's codeLocale to use when no cookie or browser match exists
persistbooleantruePersist choice in a cookie
cookieNamestring'xaf_locale'Cookie name for persistence
cookieDaysnumber365Cookie lifetime in days
detectFromBrowserbooleantrueAuto-detect from navigator.language on first visit (no cookie set)
broadcastChangebooleantrueDispatch xaf:locale:changed window event on switch
switcherPosition'footer' | 'none''footer'Built-in switcher position (or hide it)

Slots

SlotDescription
defaultApp content. Receives { locale, locales, setLocale } via slot props.
switcherCustom switcher UI. Receives { locale, locales, setLocale } via slot props. Use this when switcherPosition: 'none'.
switcher-labelOverride the label text shown next to the built-in footer switcher

Locale option shape

interface XafLocaleOption {
  code: string           // BCP 47 / ISO 639-1 (e.g. "en", "es", "fr-CA")
  label?: string         // Display label (e.g. "English", "Español")
  flag?: string          // Flag emoji (e.g. "🇺🇸") or image URL
  dir?: "ltr" | "rtl"    // Text direction. Defaults to "ltr"
  hreflangUrl?: string   // Per-locale URL — emits <link rel="alternate" hreflang="...">
}

Behavior

On mount (client)

  1. Read xaf_locale cookie. If set and the code exists in locales, use it.
  2. Else, if detectFromBrowser, try navigator.languages[0] and match against the locales list (with prefix fallback, e.g. fr-CAfr).
  3. Else, fall back to defaultLocale (or the first locale's code).
  4. Update <html lang="..."> and <html dir="..."> to match the resolved locale.

On switch

  1. Update internal locale ref.
  2. Emit update:modelValue.
  3. Write the cookie.
  4. Dispatch xaf:locale:changed window event with { code }.
  5. Update <html lang> + dir.

Listening to locale changes

window.addEventListener('xaf:locale:changed', (e) => {
  const { code } = (e as CustomEvent<{ code: string }>).detail
  // Refetch data with new locale, re-format prices, etc.
})

Reading locale state from a component

<script setup lang="ts">
const { locale, resolved, setLocale, t } = useXafLocale()

// `locale` is reactive — react to it in computed/effects:
const welcomeMessage = computed(() =>
  t({ en: "Welcome", es: "Bienvenido", fr: "Bienvenue" }, "Welcome")
)

// Switch programmatically:
function switchToSpanish() {
  setLocale("es")
}
</script>

For full i18n (translation files, pluralization, ICU message format), use vue-i18n on top. The t() helper in useXafLocale() is only for tiny strings the layer renders itself.

Tips

  • The default locale list includes 9 common languages — extend it per site based on your audience. Don't ship locales you don't actually have content for.
  • For RTL locales (Arabic, Hebrew), set dir: "rtl". The provider will set <html dir="rtl"> so your CSS can scope RTL-specific rules.
  • Pair with <XAFSearchFilters> and <XAFPagination> — they don't need locale awareness, but if you swap query params per locale (/en/search?q=foo vs /es/buscar?q=foo), pair with a route middleware.

AI Context

component: XAFLocaleProvider
package: "@xenterprises/nuxt-x-affiliate"
use-when: Multi-language site that needs locale state shared across the whole app
Copyright © 2026