Server SDK
On this page
@better-i18n/server is a standalone i18n package for pure API servers. It runs on any JavaScript runtime — Node.js, Bun, Deno, and Cloudflare Workers — with no React or SSR framework dependency.
When to Use This Package #
| Scenario | Runtime | Package |
|---|---|---|
| Next.js / TanStack Start SSR | Node.js | @better-i18n/next or @better-i18n/use-intl |
| Hono API server | Node.js, Bun, Deno, CF Workers | @better-i18n/server + ./hono adapter |
| Express / Fastify / Koa | Node.js only | @better-i18n/server + ./node adapter |
| Background worker / email sender | Any runtime | @better-i18n/server — call getTranslator() directly |
| Cloudflare Worker / Deno script | CF Workers, Deno, Bun | @better-i18n/server — no adapter needed |
| Supabase Edge Function | Deno (Supabase runtime) | @better-i18n/server — Supabase guide |
| tRPC API (edge) | Any runtime | @better-i18n/server — tRPC guide |
| tRPC API (Node.js) | Node.js | @better-i18n/server + ./node — tRPC guide |
Installation #
npm install @better-i18n/serverQuick Start #
Create the i18n singleton #
Instantiate createServerI18n once at module scope — not inside a request handler. The singleton shares a TtlCache across all requests, avoiding redundant CDN fetches.
src/i18n.ts
import { createServerI18n } from "@better-i18n/server";
export const i18n = createServerI18n({
projectId: "my-org/api",
defaultLocale: "en",
});Use the translator #
No middleware needed — call getTranslator directly with a locale string. This works on any runtime.
src/workers/email.ts
import { i18n } from "./i18n";
export async function sendWelcomeEmail(userId: string, locale: string) {
const t = await i18n.getTranslator(locale);
await mailer.send({
to: userId,
subject: t("emails.welcome.subject"),
body: t("emails.welcome.body"),
});
}src/routes/users.ts
import { i18n } from "../i18n";
// With namespace scoping
const t = await i18n.getTranslator("tr", "errors");
t("notFound"); // → "Bulunamadı"Choose an adapter (optional) #
If you use a web framework and want automatic Accept-Language detection injected into the request context, pick the right adapter:
| Framework | Adapter | Guide |
|---|---|---|
| Hono (any runtime) | @better-i18n/server/hono | Hono middleware |
| Express | @better-i18n/server/node | Express & Fastify |
| Fastify / Koa | @better-i18n/server/node | Express & Fastify |
No framework? Skip adapters entirely and call i18n.detectLocaleFromHeaders(request.headers) with any Web Standards Headers object.
Next Steps #
- Hono — Set up the Hono middleware with full TypeScript variable types.
- Express & Fastify — Node.js HTTP adapter — use
betterI18nMiddlewarewith Express orfromNodeHeaderswith Fastify. - Supabase — Detect locale and translate in Supabase Edge Functions (Deno).
- tRPC — Inject locale and t into tRPC context for localized error messages.
- API Reference — Full reference for
createServerI18n,ServerI18n, and all exports.
Better I18N