Getting Started
CDN-powered i18n for Remix & Shopify Hydrogen
Overview
@better-i18n/remix brings CDN-powered translations to Remix and Shopify Hydrogen apps. Unlike client-side solutions, translations are loaded on the server before rendering — no loading spinners, no layout shift.
The SDK is built on top of @better-i18n/core and adds Remix-specific utilities:
- Server-side data loading — Translations are fetched in
server.tsor loaders, not on the client - Provider-optional — Raw messages accessible as loader data; add
I18nextProviderorRemixI18nProviderfor hook-based translations - TtlCache singleton — A single module-scoped instance shares cache across all requests
- Accept-Language detection — Built-in locale detection from request headers
Prerequisite: Before starting, create a project at dash.better-i18n.com and publish your translations. Your project identifier will be in the format org/project (e.g., acme/web-app).
Integrating with AI? Run npx skills add better-i18n/skills first — your agent (Cursor, Claude Code, or Windsurf) will already know the SDK patterns, CDN behavior, and key conventions. Then just ask it to set up the integration for you. Learn more →
Features
CDN Delivery
Translations served from the edge via Better i18n CDN. Sub-50ms response times globally.
Server-Side Loading
Fetch translations before render. No client-side loading states or hydration mismatches.
Locale Detection
Built-in Accept-Language header parsing with quality-factor sorting and smart fallbacks.
Hydrogen Support
First-class Shopify Hydrogen integration with Storefront API locale bridging.
Quick Start
import { createRemixI18n } from "@better-i18n/remix";
export const i18n = createRemixI18n({
project: "my-company/web-app",
defaultLocale: "en",
}); import { i18n } from "~/i18n.server";
export async function loader({ request }: LoaderFunctionArgs) {
const locale = await i18n.detectLocale(request);
const messages = await i18n.getMessages(locale);
return { locale, messages };
}
export default function App() {
const { locale, messages } = useLoaderData<typeof loader>();
return (
<html lang={locale} translate="no">
<head><Meta /><Links /></head>
<body>
<Outlet />
<Scripts />
</body>
</html>
);
}This Quick Start loads translations in the root loader. For production apps, load translations in server.ts via getLoadContext() instead — see the full setup guide. For hook-based translations with ICU support, wrap <Outlet /> with a provider — see the Setup guide.
Guide
Setup
Step-by-step installation and configuration.
Locale Detection
Accept-Language detection, URL-based detection, and custom strategies.
Routing
Locale-prefixed URLs, LocaleLink, and LocaleSwitcher components.
Hydrogen
Shopify Hydrogen integration with Storefront API locale bridging.
API Reference
Complete API documentation for all exports.
Comparison
| Feature | Remix | Next.js | TanStack Start | Vite |
|---|---|---|---|---|
| Rendering | SSR | SSR + ISR | SSR | CSR only |
| Data loading | Loaders | Server Components | Server Functions | Client fetch |
| Provider needed | Optional | Optional | Yes | Yes |
| Hydrogen support | Yes | No | No | No |
| Middleware | Manual | Built-in | Built-in | N/A |
Choose @better-i18n/remix for Remix or Shopify Hydrogen apps. For Next.js, see @better-i18n/next. For Vite SPAs, see Vite.
AI Tooling
Now that you've integrated the SDK, your AI agent can check coverage, translate keys, and publish — all without leaving your editor.