The loader
The loader is a small, dependency-free script. It never blocks rendering and never redirects automatically.
Script tag#
<script async src="https://cdn.example/loader/v1/loader.js"
data-site-key="rl_site_live_abcdefghijklmnopqrstuv"
data-public-key="EXAMPLEPUBLICKEYEXAMPLEPUBLICKEYEXAMPLEPUBL"
data-base="https://cdn-a.example/ https://cdn-b.example/"
data-timeout="2500"
data-suggest="true"></script>
| Attribute | Required | Meaning |
|---|---|---|
data-site-key | yes | Public site key rl_site_{live|test}_... |
data-public-key | yes | One or more Ed25519 public keys (base64url), space or comma separated, oldest first. kid=KEY labels an entry that only matches manifests with that kid; a bare key matches any kid. See Signing and key epochs |
data-base | no | Extra bundle locations, whitespace or comma separated, tried in order after the script's own origin. https only (plain http is accepted only for localhost, 127.0.0.1 and [::1]). An entry keeps its path, so https://site.example/uploads/rl/ works (this is how the WordPress copy is addressed) |
data-timeout | no | Per-origin timeout in milliseconds (default 2500) |
data-suggest | no | true dispatches a suggestion event for the browser language; never redirects |
No other data- names exist. Server-rendered pages can mark themselves with <html data-rl-ssr="fr">; the loader then does not re-translate when its current language is fr.
What it does#
- Reads its configuration from the tag.
- Picks the language: URL prefix, then the visitor's stored choice, then (only if
data-suggestis on) a suggestion from the browser language. - Loads the manifest from the first working origin, else the cached manifest, else does nothing. It verifies the signature and refuses a lower version.
- Loads the language file, verifies its SHA-256, caches both keyed by version.
- Translates the DOM, then watches for changes.
JavaScript API#
After the script runs, window.ResilientLang exposes:
| Member | Purpose |
|---|---|
setLanguage(code) | Switch language; the source language code restores the original page. Resolves true when the language is active |
getLanguage() | Current language code |
getSourceLanguage() | The site's source language |
getLanguages() | Languages from the manifest (code, nativeName, dir, urlPrefix?) |
on(event, handler) | Subscribe; returns an unsubscribe function |
destroy() | Stop observing the page |
Events: ready ({sourceLanguage, languages}), languagechange ({lang}), suggest ({lang}). The loader has no error event: a failure leaves the page in its source language and the visitor sees nothing different (removed in 2026-11 to stay inside the size budget). A page-level resilientlang:ready CustomEvent is dispatched on document for code that loads before the loader.
getLanguages() and the ready payload return copies of the manifest's language entries; only code, name, nativeName, dir and urlPrefix are API, extra manifest fields may come along. The browser language used for suggest is navigator.language (exact match first, then the primary subtag).
The API surface above is read from the loader source in the repository (in development, size budget about 6 KB gzipped). It is not frozen; check
packages/loaderbefore relying on exact event payload names.
Requirements#
Fetch, Promise, MutationObserver, TextEncoder, and Ed25519 in Web Crypto. The build targets ES2022. A browser without them leaves the page in the source language.