Better I18NBetter I18N

Provider

Configure the BetterI18nProvider for your application

Basic Usage

With Vite Plugin (zero config)

When using @better-i18n/vite, the provider reads everything from the injected <script> tag — no props needed:

import { BetterI18nProvider } from '@better-i18n/use-intl'

function App() {
  return (
    <BetterI18nProvider>
      <YourApp />
    </BetterI18nProvider>
  )
}

Without Plugin (manual config)

import { BetterI18nProvider } from '@better-i18n/use-intl'

function App() {
  return (
    <BetterI18nProvider
      project="your-org/your-project"
      locale="en"
    >
      <YourApp />
    </BetterI18nProvider>
  )
}

Props

PropTypeRequiredDescription
projectstringWith plugin: autoProject identifier in org/project format
localestringWith plugin: autoCurrent locale code (e.g., "en", "tr")
messagesMessagesPre-loaded messages (for SSR)
localePrefix"always" | "as-needed"URL prefix strategy (default: "as-needed")
timeZonestringTimezone for date formatting
nowDateCurrent time (for SSR hydration)
localeCookieboolean | stringPersist locale to cookie. true = "locale", string = custom name
onLocaleChange(locale: string) => voidCallback when locale changes
onError(error: IntlError) => voidError handler for missing translations
cdnBaseUrlstringCustom CDN URL
debugbooleanEnable debug logging
logLevelLogLevelLogging verbosity

When using the @better-i18n/vite plugin, project, locale, messages, and languages are all injected automatically via a <script> tag. You only need to pass props that you want to override.

Client-Side Rendering

For CSR apps, messages are fetched automatically:

function App() {
  const [locale, setLocale] = useState('en')

  return (
    <BetterI18nProvider
      project="org/project"
      locale={locale}
      onLocaleChange={setLocale}
    >
      <YourApp />
    </BetterI18nProvider>
  )
}

Without pre-loaded messages, children won't render until messages are fetched from the CDN.

Server-Side Rendering

For SSR, pre-load messages to prevent flash of untranslated content:

import { getMessages } from '@better-i18n/use-intl/server'

// In your loader
const messages = await getMessages({
  project: 'org/project',
  locale: 'en',
})

// In your component
<BetterI18nProvider
  project="org/project"
  locale="en"
  messages={messages} 
  timeZone="UTC"
>
  <YourApp />
</BetterI18nProvider>

Timezone Requirement: For SSR, always set timeZone to prevent hydration mismatches. Use "UTC" as a safe default.

Locale Persistence

Use the localeCookie prop to persist the user's language choice across page refreshes:

<BetterI18nProvider
  project="org/project"
  localeCookie
>
  <App />
</BetterI18nProvider>

This does two things:

  1. Writes a cookie on every locale change (including initial mount)
  2. Reads the cookie on initialization as a fallback (for SPA/static builds)

Options

ValueCookie NameUse Case
true"locale"Most apps — simple default
"preferred-locale""preferred-locale"Custom name to match your server
false (default)SSR apps with middleware (cookie handled server-side)

Server-side pairing

Use the same cookie name on both client and server:

Client
<BetterI18nProvider localeCookie="preferred-locale" />
Server (Better Auth)
createBetterAuthProvider(i18n, { localeCookie: "preferred-locale" })
Server (Vite plugin)
betterI18n({ localeCookie: "preferred-locale" })

The cookie name must match across client and server. When using localeCookie (boolean true), the default name is "locale".

Non-React contexts

Read the cookie outside React (auth clients, analytics, fetch wrappers):

import { getLocaleCookie } from "@better-i18n/core";

const locale = getLocaleCookie("locale"); // → "tr" | null

See Better Auth integration for the full pattern.


## Error Handling

Handle missing translations gracefully:

```tsx
<BetterI18nProvider
  project="org/project"
  locale="en"
  onError={(error) => {
    if (process.env.NODE_ENV === 'development') {
      console.warn(`Missing translation: ${error.message}`)
    }
    // In production, you might want to report to error tracking
  }}
>
  <YourApp />
</BetterI18nProvider>

Debug Mode

Enable debug logging during development:

<BetterI18nProvider
  project="org/project"
  locale="en"
  debug={process.env.NODE_ENV === 'development'}
  logLevel="debug"
>
  <YourApp />
</BetterI18nProvider>

This logs:

  • CDN requests and responses
  • Cache hits and misses
  • Locale changes
  • Message loading states

Custom CDN

For enterprise or self-hosted deployments:

<BetterI18nProvider
  project="org/project"
  locale="en"
  cdnBaseUrl="https://cdn.your-company.com"
>
  <YourApp />
</BetterI18nProvider>

Types

interface BetterI18nProviderConfig {
  project: string
  locale: string
  messages?: Messages
  timeZone?: string
  now?: Date
  onLocaleChange?: (locale: string) => void
  onError?: (error: IntlError) => void
  cdnBaseUrl?: string
  debug?: boolean
  logLevel?: 'debug' | 'info' | 'warn' | 'error' | 'silent'
}

type Messages = {
  [namespace: string]: {
    [key: string]: string | Messages
  }
}

On this page