Core API Reference
On this page
Complete API reference for the core package. All framework SDKs (Next.js, Vite, TanStack Start, Expo) are built on top of these primitives.
createI18nCore #
Creates an i18n core instance for fetching translations, languages, and manifests from the CDN.
import { createI18nCore } from "@better-i18n/core";
const i18n = createI18nCore({
projectId: "org/project",
defaultLocale: "en",
});Instance Methods #
Fetches translation messages for a specific locale from the CDN.
// Full fetch — all namespaces
const messages = await i18n.getMessages("tr");
// { common: { welcome: "Hoş geldiniz" }, auth: { login: "Giriş Yap" } }
// Selective — only fetch these namespaces (namespaced_folders projects)
const subset = await i18n.getMessages("tr", {
namespaces: ["common", "hero"],
});
// { common: {...}, hero: {...} }| Parameter | Type | Description |
|---|---|---|
locale | string | Locale code (e.g., "en", "tr", "de") |
options.namespaces | string[]? | Fetch only these namespaces. Silently ignored for single_file projects. |
Returns: Promise<Messages> — Translation key-value pairs
Returns all available locale codes for the project.
const locales = await i18n.getLocales();
// ["en", "tr", "de", "fr"]Returns: Promise<string[]> — Array of locale codes
Returns available languages with full metadata — ideal for building language switchers and locale pickers.
const languages = await i18n.getLanguages();
// [
// { code: "en", name: "English", nativeName: "English", isDefault: true },
// { code: "tr", name: "Turkish", nativeName: "Türkçe", flagUrl: "https://..." },
// { code: "de", name: "German", nativeName: "Deutsch", flagUrl: "https://..." },
// ]Returns: Promise<LanguageOption[]> — Array of language objects with metadata
| Property | Type | Description |
|---|---|---|
code | string | Language code (e.g., "en", "tr") |
name | string? | English name (e.g., "Turkish") |
nativeName | string? | Native name (e.g., "Türkçe") |
flagUrl | string | null | URL to flag icon |
isDefault | boolean? | Whether this is the source/default language |
Fetches the project manifest from CDN. The manifest contains all project metadata including languages, files, and timestamps.
// Use cached manifest (default)
const manifest = await i18n.getManifest();
// Force a fresh fetch (bypass cache)
const fresh = await i18n.getManifest({ forceRefresh: true });| Option | Type | Default | Description |
|---|---|---|---|
forceRefresh | boolean | false | Skip cache and fetch fresh |
Returns: Promise<ManifestResponse>
interface ManifestResponse {
projectSlug?: string;
sourceLanguage?: string;
languages: ManifestLanguage[];
files?: Record<string, ManifestFile>;
updatedAt?: string;
}The resolved configuration with all defaults applied.
console.log(i18n.config.cdnBaseUrl); // "https://cdn.better-i18n.com"
console.log(i18n.config.manifestCacheTtlMs); // 300000
console.log(i18n.config.workspaceId); // "org"
console.log(i18n.config.projectSlug); // "project"clearManifestCache #
Clears the global manifest cache across all instances. Useful for testing or forcing a fresh fetch.
import { clearManifestCache } from "@better-i18n/core";
clearManifestCache();extractLanguages #
Extracts and normalizes language information from a raw manifest response. Useful when you have a manifest and need to convert it to UI-friendly language options.
import { extractLanguages } from "@better-i18n/core";
const manifest = await i18n.getManifest();
const languages = extractLanguages(manifest);
// [{ code: "en", name: "English", nativeName: "English", isDefault: true }, ...]| Parameter | Type | Description |
|---|---|---|
manifest | ManifestResponse | Raw manifest from CDN |
Returns: LanguageOption[] — Normalized language options
TtlCache #
Generic in-memory cache with automatic TTL expiration. Used internally for manifest caching, but available for custom use.
import { TtlCache } from "@better-i18n/core";
const cache = new TtlCache<string>();
// Store with 60s TTL
cache.set("key", "value", 60_000);
// Retrieve (returns undefined if expired)
const value = cache.get("key"); // "value"
// Check existence
cache.has("key"); // true
// Manual removal
cache.delete("key");
// Clear all entries
cache.clear();Methods #
| Method | Signature | Description |
|---|---|---|
get | (key: string) => T | undefined | Get value (auto-deletes if expired) |
set | (key: string, value: T, ttlMs: number) => void | Store with TTL in ms |
has | (key: string) => boolean | Check if key exists and is not expired |
delete | (key: string) => boolean | Remove a key |
clear | () => void | Clear all entries |
detectLocale #
Framework-agnostic locale detection with priority-based selection. Detects the best locale from path, cookie, and header sources.
import { detectLocale } from "@better-i18n/core";
const result = detectLocale({
pathLocale: "tr",
cookieLocale: "en",
headerLocale: "de",
defaultLocale: "en",
availableLocales: ["en", "tr", "de"],
project: "org/project",
});
console.log(result.locale); // "tr"
console.log(result.detectedFrom); // "path"
console.log(result.shouldSetCookie); // trueDetection Priority #
- Path — Locale from URL (e.g.,
/tr/about) - Cookie — Stored user preference
- Header — Browser's
Accept-Languageheader - Default — Fallback to
defaultLocale
Options #
| Option | Type | Description |
|---|---|---|
project | string | Project identifier |
defaultLocale | string | Fallback locale |
pathLocale | string | null | Locale from URL path |
cookieLocale | string | null | Locale from cookie |
headerLocale | string | null | Locale from Accept-Language |
availableLocales | string[] | Supported locale codes |
Result #
| Property | Type | Description |
|---|---|---|
locale | string | Detected locale code |
detectedFrom | "path" | "cookie" | "header" | "default" | Detection source |
shouldSetCookie | boolean | Whether to update the locale cookie |
Configuration Utilities #
Normalizes user configuration by applying defaults and validating required fields.
import { normalizeConfig } from "@better-i18n/core";
const config = normalizeConfig({
projectId: "org/project",
defaultLocale: "en",
});
console.log(config.cdnBaseUrl); // "https://cdn.better-i18n.com"
console.log(config.manifestCacheTtlMs); // 300000
console.log(config.workspaceId); // "org"
console.log(config.projectSlug); // "project"Throws if projectId or defaultLocale is empty or invalid format.
Parses a project identifier string into its components.
import { parseProject } from "@better-i18n/core";
const parsed = parseProject("acme/dashboard");
// { workspaceId: "acme", projectSlug: "dashboard" }Throws if format is not "org/project".
Builds the full CDN base URL for a project.
import { normalizeConfig, getProjectBaseUrl } from "@better-i18n/core";
const config = normalizeConfig({ projectId: "acme/dashboard", defaultLocale: "en" });
const url = getProjectBaseUrl(config);
// "https://cdn.better-i18n.com/acme/dashboard"Creates a unique cache key for manifest caching.
import { buildCacheKey } from "@better-i18n/core";
const key = buildCacheKey("https://cdn.better-i18n.com", "acme/dashboard");
// "https://cdn.better-i18n.com|acme/dashboard"import { createLogger, normalizeConfig } from "@better-i18n/core";
const config = normalizeConfig({
projectId: "org/project",
defaultLocale: "en",
debug: true,
});
const logger = createLogger(config, "my-module");
logger.debug("loading translations"); // [better-i18n:my-module] loading translations
logger.info("ready"); // [better-i18n:my-module] ready
logger.warn("cache miss"); // [better-i18n:my-module] cache miss
logger.error("fetch failed"); // [better-i18n:my-module] fetch failedLog Levels #
| Level | Value | Description |
|---|---|---|
"debug" | 0 | All messages |
"info" | 1 | Info and above |
"warn" | 2 | Warnings and above (default) |
"error" | 3 | Errors only |
"silent" | 4 | No output |
import type {
// Configuration
I18nCoreConfig,
NormalizedConfig,
ParsedProject,
// Manifest
ManifestResponse,
ManifestLanguage,
ManifestFile,
LanguageOption,
// Messages
Messages,
Locale,
// Instance
I18nCore,
// Cache
CacheEntry,
// Logger
Logger,
LogLevel,
// Locale URL utilities
LocaleConfig,
// Middleware/Detection
I18nMiddlewareConfig,
LocaleDetectionOptions,
LocaleDetectionResult,
LocalePrefix,
} from "@better-i18n/core";User-provided configuration for createI18nCore.
interface I18nCoreConfig {
projectId: string; // "org/project" slug or canonical UUID (required)
project?: string; // @deprecated — use projectId (kept for backward compat)
defaultLocale: string; // Fallback locale (required)
cdnBaseUrl?: string; // Default: "https://cdn.better-i18n.com"
manifestCacheTtlMs?: number; // Default: 300000 (5 min)
debug?: boolean; // Default: false
logLevel?: LogLevel; // Default: "warn"
fetch?: typeof fetch; // Custom fetch function
}projectId accepts either an org/project slug or a canonical UUID (e.g., "2cc52ff1-5eb4-41a5-85d6-34ad6fade788"). Passing the UUID makes CDN URLs stable across slug renames — find it in dashboard Settings → General → Project ID.
CDN manifest response structure.
interface ManifestResponse {
projectSlug?: string;
sourceLanguage?: string;
languages: ManifestLanguage[];
files?: Record<string, ManifestFile>;
updatedAt?: string;
/** CDN supports batch namespace fetching via /{locale}/batch.json?ns=... */
batch?: boolean;
/** Top-level namespace list for namespaced_folders projects */
namespaces?: string[];
}The batch and namespaces fields appear only for namespaced_folders projects served by CDN workers that support batching. See Selective Loading for how the SDK uses them.
Language entry in manifest.
interface ManifestLanguage {
code: string; // "en", "tr", "de"
name?: string; // "Turkish"
nativeName?: string; // "Türkçe"
flagUrl?: string | null; // Flag icon URL
isSource?: boolean; // Source language flag
lastUpdated?: string | null; // Last update timestamp
keyCount?: number; // Number of translation keys
}Simplified language option for UI components.
interface LanguageOption {
code: string; // "tr"
name?: string; // "Turkish"
nativeName?: string; // "Türkçe"
flagUrl?: string | null; // Flag icon URL
isDefault?: boolean; // Source/default language
}Instance returned by createI18nCore().
interface I18nCore {
config: NormalizedConfig;
getManifest(options?: { forceRefresh?: boolean }): Promise<ManifestResponse>;
getMessages(
locale: string,
options?: { namespaces?: string[] },
): Promise<Messages>;
getLocales(): Promise<string[]>;
getLanguages(): Promise<LanguageOption[]>;
}Result from detectLocale().
interface LocaleDetectionResult {
locale: string;
detectedFrom: "path" | "cookie" | "header" | "default";
shouldSetCookie: boolean;
}
Better I18N