Skip to content

Recipes

Each recipe takes one concrete integration job and shows the steps end to end, using the features documented in the preceding chapters. All code targets the real package APIs — if you haven’t set up the client yet, start with the Quickstart.

The network repository’s endpoint paths are configuration, not constants. Remap them with options.endpoints and the same client — cache, retries, missing-key sync, events — works against your own translation service or a third-party API. Placeholders :key, :locale, and :namespace are substituted (URL-encoded) at request time:

import { LionRapidBuilder, MemoryRepository, NetworkRepository } from '@lionrapid/core';
const customBackend = new NetworkRepository({
enabled: true,
options: {
baseUrl: 'https://translations.your-company.example',
headers: { 'X-Team': 'storefront' },
endpoints: {
getTranslation: '/v2/strings/:key',
getNamespace: '/v2/bundles/:locale/:namespace',
setBatch: '/v2/strings/bulk',
},
},
});
const lionRapid = await LionRapidBuilder.init({ defaultLocale: 'en' })
.use(new MemoryRepository({ enabled: true }))
.use(customBackend)
.build();

Remap only what you need — unset entries keep their defaults, which target the LionRapid platform’s integration endpoints (they read and sync translations by key, locale, and namespace, plus batch sync — see the Platform API reference). headers lets you add whatever authentication your backend expects; for LionRapid itself use apiKey instead (Authentication).

Goal: a pull request fails when the code disagrees with the translation catalog. Two steps: regenerate the declaration file from the live server, then type-check.

name: types
on: [pull_request]
jobs:
translation-types:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
- run: npm ci
- name: Generate translation types
run: npx lionrapid types generate --strict-icu
- name: Type check
run: npx tsc --noEmit

Notes:

  • --strict-icu makes generation itself fail on ICU messages missing their other arm — catching bad catalog entries before tsc even runs. See strict vs hybrid mode.
  • Generate into the same path the repository uses locally so the type-check exercises the same file the IDE sees.
  • npx lionrapid types check is a cheaper gate when you only want to catch malformed ICU messages without regenerating the declaration file.

Adding a language is a platform-side action first: add the target language to the continuous project and let the translations reach a state you’re willing to ship. Nothing in the app needs redeploying — locales are strings, not build configuration.

In the app, expose the new locale in your switcher:

import { useChangeLanguage } from '@lionrapid/react';
function LanguageSwitcher() {
const changeLanguage = useChangeLanguage();
return <button onClick={() => changeLanguage('sv')}>Svenska</button>;
}

Or without React:

await lionRapid.changeLanguage('sv', { preloadNamespaces: ['app'] });

Keys that are not yet translated in the new language fall back exactly like cache misses: default value (or key) first, real translation when it exists. In the WordPress plugin, the equivalent is adding the language to Enabled languages in settings.

Anything that can send an HTTP request can consume the same translations — useful for backends, cron jobs, or smoke tests. Authenticate with the integration key as a bearer token and read a locale + namespace bundle:

Terminal window
curl -H "Authorization: Bearer $LIONRAPID_INTEGRATION_KEY" \
"https://your-lionrapid-host/api/integrations/translations/en/app"

The response carries the translations (plain strings, or { text, styles } content units for styled text) plus the ICU parameter schema that the types CLI consumes. For the full set of integration endpoints — single-key reads, per-key and per-namespace sync, and batch sync — use the Platform API reference rather than hard-coding paths from examples.

Register coreFormattersPlugin and put ICU MessageFormat in the translation values; the code side only passes parameters:

lionRapid.t('inbox', { count: 3 });
// "{count, plural, =0 {Inbox empty} one {# new message} other {# new messages}}"
lionRapid.t('renewal', { date: new Date('2026-08-01') });
// "Renews on {date, date, long}"

The point of the pattern: pluralization rules, date formats, and gender agreements live in the translation, where translators control them per language — not in your code. The full syntax tour is in SDK: core.

Run translations in a worker (experimental)

Section titled “Run translations in a worker (experimental)”

The core package ships browser bundles (an IIFE build exposed under the package’s browser export) that run outside the main thread. Two patterns have been exercised:

  • Web worker for bulk work. Instantiate the client inside a Worker, send it batches of keys via postMessage, and post results back. Translating catalogs of tens of thousands of strings this way keeps the main thread responsive; the UI thread never touches the translation pipeline.
  • Service worker for network caching. A service worker can intercept the client’s translation requests and serve cached responses when the network is unavailable. Combined with the client’s own cache-first behavior (memory, plus a persistent storage handler if you register one), previously loaded locales keep working through connectivity drops.

Both patterns use the standard client API inside the worker — there is no separate worker build to learn. If you build on these, treat them as your own infrastructure: test across browsers and keep the service worker’s cache versioned.