Locale Switching
Switching Locales
Section titled “Switching Locales”<script setup>import { useI18n } from '@fluenti/vue'
const { locale, setLocale, getLocales, isLoading, preloadLocale } = useI18n()</script>
<template> <div class="locale-switcher"> <button v-for="l in getLocales()" :key="l" :class="{ active: locale === l }" @click="setLocale(l)" @mouseenter="preloadLocale(l)" > {{ l }} </button> <span v-if="isLoading">Loading...</span> </div></template>function LocaleSwitcher() { const { locale, setLocale, getLocales, isLoading, preloadLocale } = useI18n()
return ( <div> {getLocales().map(l => ( <button key={l} className={locale === l ? 'active' : ''} onClick={() => setLocale(l)} onMouseEnter={() => preloadLocale(l)} > {l} </button> ))} {isLoading && <span>Loading...</span>} </div> )}function LocaleSwitcher() { const { locale, setLocale, getLocales, isLoading, preloadLocale } = useI18n()
return ( <div> {getLocales().map(l => ( <button classList={{ active: locale() === l }} onClick={() => setLocale(l)} onMouseEnter={() => preloadLocale(l)} > {l} </button> ))} {isLoading() && <span>Loading...</span>} </div> )}Persisting the Locale
Section titled “Persisting the Locale”setLocale() updates the in-memory state, but the browser needs a few extra steps to stay in sync:
- Cookie — so the server (SSR) and client agree on the locale
<html lang>— for accessibility and SEO<html dir>— for RTL languages (Arabic, Hebrew, etc.)
These are standard DOM operations that vary by app, so Fluenti provides the building blocks (getDirection, isRTL) and lets you wire them up:
<script setup>import { watch } from 'vue'import { useI18n } from '@fluenti/vue'import { getDirection } from '@fluenti/core'
const { locale, setLocale } = useI18n()
watch(locale, (loc) => { document.cookie = `locale=${loc};path=/;max-age=31536000` document.documentElement.lang = loc document.documentElement.dir = getDirection(loc)})</script>import { useEffect, useCallback } from 'react'import { useI18n } from '@fluenti/react'import { getDirection } from '@fluenti/core'
function useLocaleSync() { const { locale } = useI18n()
useEffect(() => { document.cookie = `locale=${locale};path=/;max-age=31536000` document.documentElement.lang = locale document.documentElement.dir = getDirection(locale) }, [locale])}import { createEffect } from 'solid-js'import { useI18n } from '@fluenti/solid'import { getDirection } from '@fluenti/core'
function useLocaleSync() { const { locale } = useI18n()
createEffect(() => { const loc = locale() document.cookie = `locale=${loc};path=/;max-age=31536000` document.documentElement.lang = loc document.documentElement.dir = getDirection(loc) })}Reactivity
Section titled “Reactivity”When you call setLocale():
- Vue:
v-toutput anduseI18n().t()expressions update aslocale.valuechanges. Direct-importtdoes not create aComputedRefwrapper by itself. - React: The provider creates a new
createFluentiCore()instance, triggering re-renders for all children consuming the context. - Solid: JSX expressions that call
toruseI18n().t()re-run inside Solid’s reactive scopes. Direct-importtdoes not create acreateMemowrapper.
Every $d() and $n() call also updates automatically.
Preloading
Section titled “Preloading”Call preloadLocale() on hover so the catalog is already cached when the user clicks. The switch feels instant:
<button onMouseEnter={() => preloadLocale('ja')} onClick={() => setLocale('ja')}> 日本語</button>Lazy Loading with msg“
Section titled “Lazy Loading with msg“”Use msg for translations that need to be defined outside of components — in constants, stores, or route definitions.
The Problem
Section titled “The Problem”// This won't work — t`` needs a component contextconst ROLES = { admin: t`Administrator`, // Error: no component context}The Solution: msg“
Section titled “The Solution: msg“”import { msg } from '@fluenti/core'
const ROLES = { admin: msg`Administrator`, user: msg`Regular User`,}msg returns a MessageDescriptor — it records the message text without translating it. Resolve it at render time with t():
<template> <span>{{ t(ROLES.admin) }}</span></template>Use Cases
Section titled “Use Cases”- Route meta:
{ meta: { title: msgDashboard} } - Store constants: Error messages, role names, status labels
- Config objects: Menu items, navigation labels
- Enum-like maps: Any mapping where values need translation
Next steps
Section titled “Next steps”- Code Splitting — load locale data on demand
- Fallback Chains — regional variant handling