Skip to content
fluenti

Custom Locale Detection

By default, @fluenti/nuxt detects the user’s locale from the URL path, a cookie, or the Accept-Language header. But in real apps you may need to read locale from a database, JWT token, session, query parameter, or even an external API.

Fluenti provides two mechanisms for this:

  1. detectOrder — reorder or replace the built-in detection chain
  2. fluenti:detect-locale hook — inject locale from any runtime source

Detectors run in order. The first one to call ctx.setLocale() wins — all subsequent detectors are skipped.

detectOrder: ['path', 'cookie', 'header']
│ │ │
▼ ▼ ▼
/ja/about? cookie? Accept-Language?
setLocale setLocale setLocale
✓ │ │
├───────────┘ │
└── skip remaining ───┘
fluenti:detect-locale hook
(runs only if no detector matched)
fallback locale

Use detectOrder to change the priority of built-in detectors:

nuxt.config.ts
export default defineNuxtConfig({
modules: ['@fluenti/nuxt'],
fluenti: {
locales: ['en', 'ja', 'zh'],
defaultLocale: 'en',
// Cookie takes priority over path
detectOrder: ['cookie', 'path', 'header'],
},
})

The built-in query detector reads ?locale=ja from the URL:

nuxt.config.ts
export default defineNuxtConfig({
fluenti: {
locales: ['en', 'ja', 'zh'],
defaultLocale: 'en',
// Query param → path → cookie → header
detectOrder: ['query', 'path', 'cookie', 'header'],
},
})

Now https://example.com/about?locale=ja will set locale to ja regardless of the URL path.

Only include the detectors you want:

// Only detect from URL path — nothing else
detectOrder: ['path'],
// Only detect from cookie and header — ignore path
detectOrder: ['cookie', 'header'],

For sources that require runtime logic (database queries, JWT decoding, API calls), use the fluenti:detect-locale hook:

plugins/db-locale.ts
export default defineNuxtPlugin((nuxtApp) => {
nuxtApp.hook('fluenti:detect-locale', async (ctx) => {
if (!ctx.isServer || ctx.detectedLocale) return
const event = nuxtApp.ssrContext?.event
const user = event?.context.user // from your auth middleware
if (user?.preferredLocale) {
ctx.setLocale(user.preferredLocale)
}
})
})
plugins/jwt-locale.ts
export default defineNuxtPlugin((nuxtApp) => {
nuxtApp.hook('fluenti:detect-locale', (ctx) => {
if (ctx.detectedLocale) return
const event = nuxtApp.ssrContext?.event
const token = event?.context.auth?.token
if (token?.locale) {
ctx.setLocale(token.locale)
}
})
})
plugins/geo-locale.ts
export default defineNuxtPlugin((nuxtApp) => {
nuxtApp.hook('fluenti:detect-locale', async (ctx) => {
if (!ctx.isServer || ctx.detectedLocale) return
const event = nuxtApp.ssrContext?.event
const ip = event?.node.req.socket.remoteAddress
if (ip) {
const geo = await lookupGeoIP(ip) // your GeoIP service
if (geo?.locale) {
ctx.setLocale(geo.locale)
}
}
})
})
plugins/localstorage-locale.ts
export default defineNuxtPlugin((nuxtApp) => {
nuxtApp.hook('fluenti:detect-locale', (ctx) => {
if (ctx.isServer || ctx.detectedLocale) return
const stored = localStorage.getItem('user-locale')
if (stored) {
ctx.setLocale(stored)
}
})
})

Use detectOrder to control built-in priority and the hook for custom sources:

nuxt.config.ts
export default defineNuxtConfig({
fluenti: {
locales: ['en', 'ja', 'zh'],
defaultLocale: 'en',
detectBrowserLanguage: { useCookie: true },
// Path wins first, then cookie
detectOrder: ['path', 'cookie'],
// header is removed — we'll use a DB lookup instead
},
})
// plugins/db-locale.ts — runs after detectOrder chain
export default defineNuxtPlugin((nuxtApp) => {
nuxtApp.hook('fluenti:detect-locale', async (ctx) => {
// Only if path and cookie didn't match
if (ctx.detectedLocale) return
const user = nuxtApp.ssrContext?.event?.context.user
if (user?.preferredLocale) {
ctx.setLocale(user.preferredLocale)
}
})
})

With this setup the detection order becomes: URL path → Cookie → User DB record → fallback.

Every detector and hook receives a context object:

PropertyTypeDescription
pathstringRequest path (e.g. '/ja/about')
localesstring[]Available locale codes
defaultLocalestringDefault locale code
strategyStrategyCurrent routing strategy
detectedLocalestring | nullLocale detected so far
setLocale(locale)functionClaim a locale and stop the chain
isServerbooleanWhether running on the server

If you don’t configure detectOrder, the default chain is:

['path', 'cookie', 'header']

This matches the behavior of @nuxtjs/i18n and requires no configuration for most apps.