Remix API Reference
En esta página
Complete API reference for the Remix & Hydrogen SDK.
Architecture #
@better-i18n/remix is a thin wrapper around @better-i18n/core that adds:
- Request-based locale detection via
Accept-Languageheader parsing - Singleton pattern with
TtlCachefor efficient CDN fetching across requests - Server-side translation loading — translations are loaded server-side and passed as loader data, with optional
react-i18nextintegration foruseTranslation()hooks
createRemixI18n #
The main entry point. Creates a singleton i18n instance for server-side use.
import { createRemixI18n } from "@better-i18n/remix";
const i18n = createRemixI18n({
projectId: "my-company/web-app",
defaultLocale: "en",
});RemixI18nConfig extends I18nCoreConfig from @better-i18n/core:
| Option | Type | Default | Description |
|---|---|---|---|
project | string | Required | Project identifier in org/project format |
defaultLocale | string | Required | Fallback locale when detection fails |
logLevel | "debug" | "info" | "warn" | "error" | "silent" | "warn" | Logging verbosity |
cdnBaseUrl | string | "https://cdn.better-i18n.com" | CDN base URL (for self-hosted setups) |
manifestCacheTtlMs | number | 300000 | Cache TTL in milliseconds for CDN manifest (5 min) |
fetchTimeout | number | 10000 | CDN fetch timeout in milliseconds |
retryCount | number | 1 | Number of retry attempts on CDN fetch failure |
The returned object exposes these methods:
| Property | Type | Description |
|---|---|---|
config | I18nCoreConfig | Resolved configuration object |
detectLocale(request) | (request: Request) => Promise<string> | Detect locale from Accept-Language header |
getMessages(locale) | (locale: string) => Promise<Messages> | Get all messages for a locale from CDN |
getLocales() | () => Promise<string[]> | Get available locale codes from manifest |
getLanguages() | () => Promise<LanguageOption[]> | Get language options with metadata |
const locale = await i18n.detectLocale(request);
// "tr" (if Accept-Language contains Turkish)How it works:
- Fetches available locales from CDN manifest via
getLocales() - Parses
Accept-Languageheader withparseAcceptLanguage() - Matches against available locales with
matchLocale() - Falls back to
defaultLocaleif no match
| Parameter | Type | Description |
|---|---|---|
request | Request | Standard Web API Request object |
Returns: Promise<string> — The matched locale code
Fetch all translation messages for a locale. Returns namespaced messages from the CDN, cached via TtlCache.
const messages = await i18n.getMessages("tr");
// {
// common: { welcome: "Hos geldiniz", shop_now: "Alisverise Basla" },
// products: { from: "Baslayan fiyat" },
// footer: { about: "Hakkimizda" }
// }| Parameter | Type | Description |
|---|---|---|
locale | string | Locale code (e.g., "en", "tr") |
Returns: Promise<Messages> — Namespaced translation messages
Get available locale codes from the CDN manifest.
const locales = await i18n.getLocales();
// ["en", "tr", "es", "fr", "de"]Returns: Promise<string[]> — Array of available locale codes
Get language options with full metadata, useful for building language switcher UIs.
const languages = await i18n.getLanguages();
// [
// { code: "en", name: "English", nativeName: "English", flagUrl: "..." },
// { code: "tr", name: "Turkish", nativeName: "Turkce", flagUrl: "..." },
// ]Returns: Promise<LanguageOption[]> — Array of language metadata objects
Utility Functions #
Parse an RFC 5646 Accept-Language header into a priority-sorted list of language tags.
import { parseAcceptLanguage } from "@better-i18n/remix";
const languages = parseAcceptLanguage("tr-TR,tr;q=0.9,en-US;q=0.8,en;q=0.7");
// ["tr-TR", "tr", "en-US", "en"]
// Handles null/undefined gracefully
parseAcceptLanguage(null);
// []| Parameter | Type | Description |
|---|---|---|
header | string | null | undefined | Raw Accept-Language header value |
Returns: string[] — Language tags sorted by quality factor (highest first)
Parsing rules:
- Splits on commas, extracts language tag and quality factor
- Quality factor defaults to
1.0if not specified - Wildcard
*entries are ignored - Invalid quality values are treated as
1.0
Find the best matching locale from a parsed language list against available locales.
import { matchLocale } from "@better-i18n/remix";
matchLocale(["tr-TR", "tr", "en-US"], ["en", "tr", "es"]);
// "tr" (base language match: "tr-TR" → "tr")
matchLocale(["ja", "ko"], ["en", "tr", "es"]);
// null (no match)| Parameter | Type | Description |
|---|---|---|
languages | string[] | Priority-sorted language tags (from parseAcceptLanguage) |
availableLocales | string[] | Available locale codes in your project |
Returns: string | null — Best matching locale, or null if none found
Matching strategy (in priority order):
| Priority | Strategy | Example |
|---|---|---|
| 1 | Exact match | "tr-TR" matches "tr-TR" |
| 2 | Base language | "tr-TR" matches "tr" (strips region subtag) |
| 3 | Region expansion | "tr" matches "tr-TR" (first available variant) |
import type { Messages } from "@better-i18n/remix";
const messages: Messages = {
common: {
welcome: "Welcome",
goodbye: "Goodbye",
},
errors: {
notFound: "Page not found",
},
};Type: Record<string, unknown>
Language metadata from the CDN manifest.
import type { LanguageOption } from "@better-i18n/remix";
// {
// code: "tr",
// name: "Turkish",
// nativeName: "Turkce",
// flagUrl: "https://cdn.better-i18n.com/flags/tr.svg"
// }| Property | Type | Description |
|---|---|---|
code | string | Locale code (e.g., "en", "tr") |
name | string | undefined | English language name |
nativeName | string | undefined | Native language name |
flagUrl | string | null | undefined | URL to flag image |
isDefault | boolean | undefined | Whether this is the default/source language |
Configuration type for createRemixI18n(). Alias for I18nCoreConfig.
import type { RemixI18nConfig } from "@better-i18n/remix";Extends I18nCoreConfig — see config options table in the createRemixI18n section above.
Instance type returned by createRemixI18n().
import type { RemixI18n } from "@better-i18n/remix";Exposes detectLocale(), getMessages(), getLocales(), and getLanguages() — see return type table in the createRemixI18n section above.
The following types are re-exported for convenience:
import type {
I18nCoreConfig,
LanguageOption,
Messages,
Locale,
LogLevel,
ManifestLanguage,
ManifestResponse,
} from "@better-i18n/remix";msg() #
String extractor for non-hook contexts — meta() functions, loaders, and utility modules where React hooks cannot be called. For component translations, use useTranslation() (i18next) or useTranslations() (use-intl) instead.
import { msg } from "@better-i18n/remix";
const common = messages.common;
msg(common, "welcome", "Welcome"); // → "Hoş geldiniz" or "Welcome"
msg(common, "missing_key"); // → ""
msg(undefined, "key", "fallback"); // → "fallback"| Parameter | Type | Default | Description |
|---|---|---|---|
ns | Record<string, unknown> | undefined | Required | Namespace object from messages |
key | string | Required | Translation key |
fallback | string | "" | Fallback value if key is missing or not a string |
Returns: string — The translation value, or fallback
React Entrypoint (@better-i18n/remix/react) #
Optional entrypoint for projects that want a use-intl-based React provider instead of i18next. Provides a RemixI18nProvider, translation hooks, and a built-in LanguageSwitcher component.
Wraps your app with use-intl's IntlProvider and a context for locale/languages state.
import { RemixI18nProvider } from "@better-i18n/remix/react";
<RemixI18nProvider
locale={locale}
messages={messages}
languages={languages}
timeZone="Europe/Istanbul"
>
<Outlet />
</RemixI18nProvider>| Prop | Type | Default | Description |
|---|---|---|---|
locale | string | Required | Current locale code |
messages | Messages | Required | Translation messages from CDN |
languages | LanguageOption[] | [] | Available languages for switcher |
timeZone | string | — | IANA timezone for date/time formatting |
now | Date | — | Fixed "now" for SSR consistency |
onError | (error: Error) => void | no-op | Error handler for missing translations |
children | ReactNode | Required | Child components |
All hooks must be used within a RemixI18nProvider.
| Hook | Return Type | Description |
|---|---|---|
useTranslations(namespace?) | (key: string) => string | Get a translation function (from use-intl) |
useFormatter() | IntlFormatter | Date, number, and list formatting (from use-intl) |
useMessages() | Messages | Access all messages in context |
useNow() | Date | Current "now" value (for SSR hydration) |
useTimeZone() | string | Current timezone |
useLocale() | string | Current locale code |
useLanguages() | LanguageOption[] | Available language list |
useRemixI18n() | { locale, languages } | Raw context value |
import { useTranslations, useLocale } from "@better-i18n/remix/react";
export default function Header() {
const t = useTranslations("common");
const locale = useLocale();
return <h1>{t("welcome")}</h1>;
}Pre-built <select> component for switching languages. Navigates to the locale-prefixed URL automatically.
import { LanguageSwitcher } from "@better-i18n/remix/react";
<LanguageSwitcher locale={locale} defaultLocale="en" />| Prop | Type | Default | Description |
|---|---|---|---|
locale | string | Required | Current locale code |
defaultLocale | string | "en" | Default locale (no URL prefix) |
renderOption | (lang) => ReactNode | — | Custom option renderer |
Accepts all standard <select> props (className, aria-label, etc.).
Accessible dropdown component with flag emojis, native language names, and keyboard navigation. A more feature-rich alternative to LanguageSwitcher.
import { LocaleDropdown } from "@better-i18n/remix/react";
<LocaleDropdown />Reads locale and languages from RemixI18nProvider context. Selecting a locale navigates to the locale-prefixed URL using useNavigate().
| Prop | Type | Default | Description |
|---|---|---|---|
defaultLocale | string | "en" | Default locale (no URL prefix) |
variant | "styled" | "unstyled" | "styled" | Styled or unstyled mode |
showFlag | boolean | true | Show flag emoji/image |
showNativeName | boolean | true | Show native language name |
showLocaleCode | boolean | true | Show locale code |
renderTrigger | (ctx) => ReactNode | — | Custom trigger renderer |
renderItem | (ctx) => ReactNode | — | Custom item renderer |
For full props reference, CSS custom properties, and custom rendering — see LocaleDropdown.
i18next Entrypoint (@better-i18n/remix/i18next) #
Optional entrypoint for projects using i18next / react-i18next. Converts CDN translations to i18next resource format.
Builds a complete i18next-compatible configuration from CDN translations and manifest. Fetches all locales and returns resources, supported languages, and i18next init options.
import { createRemixI18n } from "@better-i18n/remix";
import { buildI18nextConfig } from "@better-i18n/remix/i18next";
const i18n = createRemixI18n({ projectId: "acme/store", defaultLocale: "en" });
const config = await buildI18nextConfig({ i18n });
// config.resources — { en: { common: {...}, nav: {...} }, tr: {...} }
// config.supportedLanguages — ["en", "tr", "es"]
// config.fallbackLanguage — "en"
// config.languages — [{ code: "en", name: "English", ... }, ...]
// config.i18nextOptions — { lowerCaseLng: true, defaultNS: "translation", ... }| Parameter | Type | Description |
|---|---|---|
options.i18n | RemixI18n | Instance from createRemixI18n() |
options.i18nextOptions | Record<string, unknown> | Additional i18next init options (merged with defaults) |
Returns: Promise<{ resources, supportedLanguages, fallbackLanguage, languages, i18nextOptions }>
Converts Better i18n CDN format to i18next resources format. Optionally accepts a locale list (defaults to all locales from CDN manifest).
import { loadResources } from "@better-i18n/remix/i18next";
const resources = await loadResources(i18n);
// { en: { common: { welcome: "Welcome" }, translation: { common: {...} } } }CDN format: { "namespace": { "key": "value" } }
i18next format: { "locale": { "namespace": { "key": "value" } } }
| Parameter | Type | Description |
|---|---|---|
i18n | RemixI18n | Instance from createRemixI18n() |
locales | string[] | Optional locale list (defaults to all from manifest) |
Returns: Promise<Record<string, Record<string, Record<string, unknown>>>> — i18next-compatible resources
Better I18N