ResilientLang docsDeveloper documentation (draft, product name is a placeholder)

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>
AttributeRequiredMeaning
data-site-keyyesPublic site key rl_site_{live|test}_...
data-public-keyyesOne 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-basenoExtra 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-timeoutnoPer-origin timeout in milliseconds (default 2500)
data-suggestnotrue 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#

  1. Reads its configuration from the tag.
  2. Picks the language: URL prefix, then the visitor's stored choice, then (only if data-suggest is on) a suggestion from the browser language.
  3. Loads the manifest from the first working origin, else the cached manifest, else does nothing. It verifies the signature and refuses a lower version.
  4. Loads the language file, verifies its SHA-256, caches both keyed by version.
  5. Translates the DOM, then watches for changes.

JavaScript API#

After the script runs, window.ResilientLang exposes:

MemberPurpose
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/loader before 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.