Server Utilities
Bu sayfada
Import from @better-i18n/use-intl/server:
TypeScript
import {
getMessages,
getLocales,
getLanguages,
createServerTranslator,
createServerFormatter,
} from '@better-i18n/use-intl/server'Quick Reference #
| Function | Description |
|---|---|
getMessages | Fetch messages for a locale |
getLocales | Get available locale codes |
getLanguages | Get languages with metadata |
createServerTranslator | Create a translator for server use |
createServerFormatter | Create a formatter for server use |
getMessages #
Fetch translation messages for a locale from the CDN. Use this in server loaders to pre-load messages for SSR.
Basic Usage #
TypeScript
import { getMessages } from '@better-i18n/use-intl/server'
const messages = await getMessages({
projectId: 'org/project',
locale: 'en',
})Options #
| Option | Type | Required | Description |
|---|---|---|---|
projectId | string | ✅ | Project ID — org/project slug or canonical UUID |
locale | string | ✅ | Locale to fetch messages for |
cdnBaseUrl | string | Custom CDN URL | |
debug | boolean | Enable debug logging |
TanStack Start Integration #
Pre-load messages in your root loader:
app/routes/__root.tsx
import { createRootRouteWithContext, Outlet } from '@tanstack/react-router'
import { BetterI18nProvider } from '@better-i18n/use-intl'
import { getMessages } from '@better-i18n/use-intl/server' // [!code highlight]
export const Route = createRootRouteWithContext<{ locale: string }>()({
loader: async ({ context }) => {
const messages = await getMessages({ // [!code highlight]
projectId: 'org/project',
locale: context.locale || 'en',
}) // [!code highlight]
return { messages, locale: context.locale }
},
component: function RootComponent() {
const { messages, locale } = Route.useLoaderData()
return (
<BetterI18nProvider
projectId="org/project"
locale={locale}
messages={messages} // [!code highlight]
timeZone="UTC" // [!code highlight]
>
<Outlet />
</BetterI18nProvider>
)
},
})Path-Based Locale Detection #
TSX
loader: async ({ context, location }) => {
// Extract locale from path
const pathParts = location.pathname.split('/')
const pathLocale = pathParts[1]
// Validate it's a 2-letter code
const locale = pathLocale?.length === 2
? pathLocale
: context.locale || 'en'
const messages = await getMessages({
projectId: 'org/project',
locale,
})
return { messages, locale }
}Error Handling #
Handle fetch failures gracefully:
TypeScript
try {
const messages = await getMessages({
projectId: 'org/project',
locale,
})
return { messages, locale }
} catch (error) {
console.error(`Failed to load messages for ${locale}:`, error)
// Fallback to default locale
const fallbackMessages = await getMessages({
projectId: 'org/project',
locale: 'en',
})
return { messages: fallbackMessages, locale: 'en' }
}TypeScript
import { getLocales } from '@better-i18n/use-intl/server'
const locales = await getLocales({
projectId: 'org/project',
})
// ['en', 'tr', 'de', 'es']TypeScript
import { getLanguages } from '@better-i18n/use-intl/server'
const languages = await getLanguages({
projectId: 'org/project',
})
// [
// { code: 'en', name: 'English', nativeName: 'English', flagUrl: '...' },
// { code: 'tr', name: 'Turkish', nativeName: 'Türkçe', flagUrl: '...' },
// ]createServerTranslator #
Create a translator function for use outside React components. Perfect for route loaders, API routes, and email templates.
Basic Usage #
TypeScript
import { getMessages, createServerTranslator } from '@better-i18n/use-intl/server'
const messages = await getMessages({
projectId: 'org/project',
locale: 'en',
})
const t = createServerTranslator({
locale: 'en',
messages,
namespace: 'emails',
})
const subject = t('welcomeEmail.subject')
const body = t('welcomeEmail.body', { name: 'John' })Options #
| Option | Type | Required | Description |
|---|---|---|---|
locale | string | ✅ | Locale for the translator |
messages | Messages | ✅ | Pre-loaded messages |
namespace | string | Default namespace to use | |
timeZone | string | Timezone for date formatting |
app/routes/about.tsx
import { createFileRoute } from '@tanstack/react-router'
import { getMessages, createServerTranslator } from '@better-i18n/use-intl/server'
export const Route = createFileRoute('/about')({
loader: async ({ context }) => {
const messages = await getMessages({
projectId: 'org/project',
locale: context.locale,
})
const t = createServerTranslator({
locale: context.locale,
messages,
namespace: 'about',
})
return {
messages,
meta: {
title: t('meta.title'),
description: t('meta.description'),
},
}
},
head: ({ loaderData }) => ({
meta: [
{ title: loaderData.meta.title },
{ name: 'description', content: loaderData.meta.description },
],
}),
component: AboutPage,
})API Routes
Return translated responses:
app/routes/api/welcome.ts
import { json } from '@tanstack/react-start'
import { getMessages, createServerTranslator } from '@better-i18n/use-intl/server'
export async function loader({ request }) {
const locale = request.headers.get('accept-language')?.split(',')[0] || 'en'
const messages = await getMessages({
projectId: 'org/project',
locale,
})
const t = createServerTranslator({
locale,
messages,
namespace: 'api',
})
return json({
message: t('welcome'),
status: t('status.ok'),
})
}Email Templates
Generate translated emails:
lib/emails/welcome.ts
import { getMessages, createServerTranslator } from '@better-i18n/use-intl/server'
export async function generateWelcomeEmail(user: User) {
const messages = await getMessages({
projectId: 'org/project',
locale: user.locale,
})
const t = createServerTranslator({
locale: user.locale,
messages,
namespace: 'emails',
})
return {
subject: t('welcome.subject'),
body: t('welcome.body', {
name: user.name,
company: 'Acme Inc',
}),
cta: t('welcome.cta'),
}
}Background Workers
workers/notifications.ts
import { getMessages, createServerTranslator } from '@better-i18n/use-intl/server'
export async function sendDailyDigest(users: User[]) {
for (const user of users) {
const messages = await getMessages({
projectId: 'org/project',
locale: user.locale,
})
const t = createServerTranslator({
locale: user.locale,
messages,
namespace: 'notifications',
})
await sendNotification(user, {
title: t('dailyDigest.title'),
body: t('dailyDigest.body', { count: user.unreadCount }),
})
}
}TypeScript
import { createServerFormatter } from '@better-i18n/use-intl/server'
const format = createServerFormatter({
locale: 'en',
timeZone: 'America/New_York',
})
const date = format.dateTime(new Date(), { dateStyle: 'full' })
const price = format.number(99.99, { style: 'currency', currency: 'USD' })| Resource | CDN Cache | Browser Cache |
|---|---|---|
| Messages | 1 hour | 5 minutes |
For additional caching, you can wrap getMessages:
TypeScript
const messageCache = new Map<string, Promise<Messages>>()
async function getCachedMessages(locale: string) {
const key = `${locale}`
if (!messageCache.has(key)) {
messageCache.set(key, getMessages({
projectId: 'org/project',
locale,
}))
}
return messageCache.get(key)!
}Related #
- Provider - Pass messages to provider
- Translations - Client-side translation
- TanStack SSR - Complete SSR guide
Better I18N