BabelizeBabelize
SDK

Core Runtime

API reference for @babelize/sdk, the framework-agnostic translation runtime: initialization, translating strings, locales, the lockfile, caching and batching.

@babelize/sdk is the foundation of the Babelize SDK. It provides the translation function, caching, locale management, and batch API communication.

Initialization

In the browser, initialize without a key and serve translations from the lockfile:

import { babelize } from "@babelize/sdk";
import lockfile from "virtual:babelize-lockfile";

lockfile && babelize.loadLockfile(lockfile);
babelize.init({ locale: "ja", fallbackLocale: "en" });

Without a key, the SDK uses the lockfile only and never makes API calls.

In server-side code only (Node scripts, API routes, server components), you can pass a key to translate strings missing from the lockfile at runtime:

babelize.init({
  apiKey: process.env.BABELIZE_API_KEY,
  locale: "ja",
  fallbackLocale: "en",
  apiUrl: "https://api.babelize.co/api",
});

Your bblz_sk_ key is a secret. Never pass it to babelize.init() in browser code or expose it through VITE_* / NEXT_PUBLIC_* variables — anyone visiting your site could read it and spend your credits.

Translating Strings

Wrap any string with babelize():

babelize("Welcome");                         // "ようこそ" (when it's in the lockfile)
babelize("Hello {name}", { name: "Mohit" });  // "こんにちは Mohit"
babelize("You have {count} messages", { count: 5 }); // "5件のメッセージがあります"

{key} placeholders are interpolated with the provided variables. The SDK checks memory cache first, then the lockfile, then — only if an API key was passed to init() — queues a batched API request. With no key, a string missing from the lockfile is returned unchanged.

Locale Management

Set and get the active locale:

babelize.setLocale("fr");
const current = babelize.getLocale(); // "fr"

Locale is auto-detected from the browser (navigator.language) when not specified. All subsequent babelize() calls use the active locale.

Loading the Lockfile

In production, translations are pre-built into a lockfile. Load it at startup:

import lockfile from "virtual:babelize-lockfile";

lockfile && babelize.loadLockfile(lockfile);

The lockfile is generated by the build plugin (@babelize/vite or @babelize/next). Once loaded, all translations are served from it with zero API calls.

Cache Strategy

The SDK uses a multi-tier cache for maximum performance:

Memory Cache      < 0.1ms    — fastest, cleared on page reload
    ↓ (miss)
Lockfile Cache    < 1ms      — loaded from build-time lockfile
    ↓ (miss, and an API key is configured — server-side only)
Babelize API      < 100ms    — fetched and cached for subsequent calls
    ↓ (miss)
Original string              — fallback, never fails

When the API returns a translation, it's stored in memory cache so subsequent calls for the same string are instant.

Batch Requests

Multiple babelize() calls within the same render cycle are automatically batched into a single API request (when an API key is configured). The SDK collects all missing strings and sends them together, reducing latency and API usage.

// These three calls are batched into one API request
<h1>{babelize("Welcome")}</h1>
<p>{babelize("Get Started")}</p>
<button>{babelize("Learn More")}</button>

Lockfile Format

The lockfile stores all pre-translated strings per locale:

{
  "version": 1,
  "meta": {
    "generatedAt": "2026-07-30T12:00:00Z",
    "locales": ["ja", "fr", "de"],
    "totalStrings": 42
  },
  "strings": {
    "Welcome": {
      "ja": "ようこそ",
      "fr": "Bienvenue",
      "de": "Willkommen"
    },
    "Hello {name}": {
      "ja": "こんにちは {name}",
      "fr": "Bonjour {name}",
      "de": "Hallo {name}"
    }
  },
  "plurals": {
    "{count} item": {
      "forms": ["one", "other"],
      "ja": { "other": "{count} 項目" },
      "fr": { "one": "{count} élément", "other": "{count} éléments" }
    }
  }
}

Reactivity

Subscribe to state changes for custom reactivity:

const unsubscribe = babelize.subscribe(() => {
  console.log("Locale or cache updated");
});

// Later, clean up
unsubscribe();

babelize.getVersion() returns a number that increments on locale switches and translation-cache updates. This is used internally by the React bindings to trigger re-renders via useSyncExternalStore.

Testing

Reset all state between tests:

babelize.reset();

This clears the cache, locale, subscribers, and API client — giving you a clean slate for each test case.

TypeScript

import type { BabelizeConfig, LockfileData, PluralForms, TagResult } from "@babelize/sdk";

interface BabelizeConfig {
  apiKey?: string;
  locale?: string;
  fallbackLocale?: string;
  apiUrl?: string;
  /** The user's language, tried before the built-in detection (see React Native & Expo). */
  detectLocale?: () => string | null;
}

interface LockfileData {
  version: number;
  strings: Record<string, Record<string, string>>;
  plurals?: Record<string, {
    forms: string[];
    [locale: string]: Record<string, string> | string[];
  }>;
}

type PluralForms = {
  zero?: string;
  one?: string;
  two?: string;
  few?: string;
  many?: string;
  other: string;
};

Last updated: 2026-10-16

How is this guide?

On this page