Skip to content
better-i18n.com
本页内容

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.

TypeScript
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.

TypeScript
// 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: {...} }
ParameterTypeDescription
localestringLocale code (e.g., "en", "tr", "de")
options.namespacesstring[]?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.

TypeScript
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.

TypeScript
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

PropertyTypeDescription
codestringLanguage code (e.g., "en", "tr")
namestring?English name (e.g., "Turkish")
nativeNamestring?Native name (e.g., "Türkçe")
flagUrlstring | nullURL to flag icon
isDefaultboolean?Whether this is the source/default language

Fetches the project manifest from CDN. The manifest contains all project metadata including languages, files, and timestamps.

TypeScript
// Use cached manifest (default)
const manifest = await i18n.getManifest();

// Force a fresh fetch (bypass cache)
const fresh = await i18n.getManifest({ forceRefresh: true });
OptionTypeDefaultDescription
forceRefreshbooleanfalseSkip cache and fetch fresh

Returns: Promise<ManifestResponse>

TypeScript
interface ManifestResponse {
  projectSlug?: string;
  sourceLanguage?: string;
  languages: ManifestLanguage[];
  files?: Record<string, ManifestFile>;
  updatedAt?: string;
}

The resolved configuration with all defaults applied.

TypeScript
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.

TypeScript
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.

TypeScript
import { extractLanguages } from "@better-i18n/core";

const manifest = await i18n.getManifest();
const languages = extractLanguages(manifest);
// [{ code: "en", name: "English", nativeName: "English", isDefault: true }, ...]
ParameterTypeDescription
manifestManifestResponseRaw 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.

TypeScript
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 #

MethodSignatureDescription
get(key: string) => T | undefinedGet value (auto-deletes if expired)
set(key: string, value: T, ttlMs: number) => voidStore with TTL in ms
has(key: string) => booleanCheck if key exists and is not expired
delete(key: string) => booleanRemove a key
clear() => voidClear all entries

detectLocale #

Framework-agnostic locale detection with priority-based selection. Detects the best locale from path, cookie, and header sources.

TypeScript
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); // true

Detection Priority #

  1. Path — Locale from URL (e.g., /tr/about)
  2. Cookie — Stored user preference
  3. Header — Browser's Accept-Language header
  4. Default — Fallback to defaultLocale

Options #

OptionTypeDescription
projectstringProject identifier
defaultLocalestringFallback locale
pathLocalestring | nullLocale from URL path
cookieLocalestring | nullLocale from cookie
headerLocalestring | nullLocale from Accept-Language
availableLocalesstring[]Supported locale codes

Result #

PropertyTypeDescription
localestringDetected locale code
detectedFrom"path" | "cookie" | "header" | "default"Detection source
shouldSetCookiebooleanWhether to update the locale cookie

Configuration Utilities #

Normalizes user configuration by applying defaults and validating required fields.

TypeScript
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.

TypeScript
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.

TypeScript
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.

TypeScript
import { buildCacheKey } from "@better-i18n/core";

const key = buildCacheKey("https://cdn.better-i18n.com", "acme/dashboard");
// "https://cdn.better-i18n.com|acme/dashboard"

createLogger #

Creates a namespaced logger instance with level filtering.

TypeScript
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 failed

Log Levels #

LevelValueDescription
"debug"0All messages
"info"1Info and above
"warn"2Warnings and above (default)
"error"3Errors only
"silent"4No output

Types #

All types are exported from @better-i18n/core:

TypeScript
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.

TypeScript
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.

TypeScript
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.

TypeScript
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.

TypeScript
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().

TypeScript
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().

TypeScript
interface LocaleDetectionResult {
  locale: string;
  detectedFrom: "path" | "cookie" | "header" | "default";
  shouldSetCookie: boolean;
}