JavaScript SDK
@openlocale/sdk is the zero-dependency runtime client for browsers and Node (18+). It handles caching, revalidation, live updates, and graceful failure.
sh
npm install @openlocale/sdkQuick start
ts
import { createClient } from "@openlocale/sdk";
const ol = createClient({
endpoint: "https://locale.example.com",
project: "demo"
});
await ol.load("es"); // fetch (or revalidate) + make current
ol.t("checkout.title"); // "Pagar"
ol.t("missing.key"); // "missing.key" — never throwsOptions
ts
createClient({
endpoint: string, // your openlocale server
project: string, // project slug
apiKey?: string, // read token for private projects
namespace?: string, // default "default"
live?: boolean, // subscribe to updates (default true)
pollInterval?: number, // fallback polling ms (default 60_000)
persist?: boolean, // localStorage cache (default true in browsers)
fetch?: typeof fetch // override for tests/custom runtimes
});API
| Member | Description |
|---|---|
load(locale) | Fetch or revalidate a bundle; sets the current locale. Sends If-None-Match; a 304 reuses the cache. |
t(key, locale?) | Look up a translation in the current (or given) locale. Missing keys return the key. |
getBundle(locale) | The raw Record<string, string> for a loaded locale. |
locale() | Currently active locale. |
on("update", cb) | Fires after a live change is fetched — re-render here. Returns an unsubscribe function. |
on("error", cb) | Background refresh failures (the cache keeps serving). |
close() | Tear down SSE/polling. |
How live updates work
- On first
load, the client opensEventSourceto/api/v1/cdn/:project/events(token passed as a query parameter, since EventSource can't set headers). - A
translations.updatedevent for a loaded locale triggers a bundle re-fetch (the ETag is bypassed), then yourupdatelisteners fire. - If SSE hard-fails — a buffering proxy, restrictive network — the client falls back to polling the manifest at
pollIntervaland diffing version numbers. Same behavior, higher latency.
Startup performance
With persist: true, bundles and their ETags are stored in localStorage. On the next page load, load() renders instantly from the persisted copy and revalidates in the background — typically a single 304.