Skip to content
fluenti

React Router

Fluenti works with React Router v7 as a client-side SPA with full Vite plugin support. See the Quick Start for initial setup.

React Router apps detect locale on the client. A common pattern reads from URL query params first, then falls back to cookies:

function getInitialLocale(): string {
// Check URL query param: ?lang=zh-CN
const urlParams = new URLSearchParams(window.location.search)
const queryLang = urlParams.get('lang')
if (queryLang) {
document.cookie = `locale=${queryLang};path=/;max-age=31536000`
return queryLang
}
// Fall back to cookie
const match = document.cookie.match(/(?:^|;\s*)locale=([^;]*)/)
if (match) return decodeURIComponent(match[1])
return 'en'
}

React Router works well with React.lazy() for route-level code splitting. The Vite plugin tree-shakes messages per chunk:

import { lazy, Suspense } from 'react'
import { BrowserRouter, Routes, Route } from 'react-router-dom'
const About = lazy(() => import('./pages/About'))
const Contact = lazy(() => import('./pages/Contact'))
function App() {
return (
<BrowserRouter>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={
<Suspense fallback={<p>Loading...</p>}>
<About />
</Suspense>
} />
<Route path="/contact" element={
<Suspense fallback={<p>Loading...</p>}>
<Contact />
</Suspense>
} />
</Routes>
</BrowserRouter>
)
}

The t`...` tagged template is the primary translation API. The Vite plugin injects it automatically — no import needed:

function ProductCard({ product }: { product: Product }) {
return (
<div>
<h2>{t`${product.name}`}</h2>
<p>{t`In stock: ${product.quantity} items`}</p>
</div>
)
}

For dynamic keys or non-component contexts, fall back to i18n.t():

import { useI18n } from '@fluenti/react'
function DynamicContent({ messageKey }: { messageKey: string }) {
const { i18n } = useI18n()
return <p>{i18n.t(messageKey)}</p>
}

Use preloadLocale() so the locale catalog is cached before the user clicks:

import { useI18n } from '@fluenti/react'
function LocaleSwitcher({ onLocaleChange }) {
const { locale, preloadLocale } = useI18n()
return (
<div>
{['en', 'zh-CN', 'ja'].map((loc) => (
<button
key={loc}
className={locale === loc ? 'active' : ''}
onMouseEnter={() => preloadLocale(loc)}
onClick={() => onLocaleChange(loc)}
>
{loc}
</button>
))}
</div>
)
}

Update the lang and dir attributes when the locale changes:

import { useEffect } from 'react'
import { getDirection } from '@fluenti/core'
function Root() {
const [locale, setLocale] = useState(getInitialLocale)
useEffect(() => {
document.documentElement.lang = locale
document.documentElement.dir = getDirection(locale)
}, [locale])
// ...
}