@polingo/web
v0.0.3
Published
Browser adapter for Polingo with fetch loader and localStorage caching
Maintainers
Readme
@polingo/web
Browser-oriented loader and cache for the Polingo translation engine.
@polingo/web bundles a Fetch-based loader and a resilient localStorage cache so you can use @polingo/core inside traditional SPAs, server-rendered apps that hydrate on the client, or edge runtimes with a compatible fetch implementation.
Contents
- What it does
- Installation
- Quick start
- Loader options
- Caching behaviour
- Usage patterns
- Catalog format
- Tips & gotchas
- Related packages
- License
What it does
- Downloads catalogs via the Fetch API with sensible defaults (
/locales/<locale>/<domain>.json). - Lets you provide a custom
buildUrl,fetch, andRequestInitfor CDNs or authenticated endpoints. - Ships a storage-backed cache that transparently falls back to memory when
localStorageis unavailable. - Works together with
@polingo/coreto provide synchronous translations after the initial preload. - Fully typed TypeScript API—great for Next.js, Remix, Astro, Vite, and more.
Installation
npm install @polingo/core @polingo/web
# or
pnpm add @polingo/core @polingo/web
# or
yarn add @polingo/core @polingo/webQuick start
import { createPolingo } from '@polingo/web';
const polingo = await createPolingo({
locale: 'en',
locales: ['en', 'es'],
loader: { baseUrl: '/i18n' }, // fetches /i18n/en/messages.json, etc.
cache: true,
cacheOptions: { prefix: 'my-app', ttlMs: 86_400_000 }, // 24h
});
polingo.t('Welcome');
polingo.tn('{n} item', '{n} items', 3, { n: 3 });Loader options
WebLoader powers createPolingo under the hood. You can customise it through the loader key or instantiate it yourself.
interface WebLoaderOptions {
baseUrl?: string; // defaults to '/locales'
buildUrl?: (locale: string, domain: string) => string; // overrides baseUrl
fetch?: typeof fetch; // provide for older browsers, React Native, SSR, or tests
requestInit?: RequestInit; // extra options (credentials, headers, cache directives, ...)
transformResponse?: (payload: unknown) => TranslationCatalog; // adapt bespoke formats
}Example: streaming from a CDN with authentication.
const polingo = await createPolingo({
locale: 'en',
locales: ['en', 'fr'],
loader: {
buildUrl: (locale, domain) => `https://cdn.example.com/static/i18n/${locale}/${domain}.json`,
requestInit: {
credentials: 'include',
cache: 'reload',
},
},
});Caching behaviour
createPolingo enables caching by default (cache: true). Behind the scenes it uses LocalStorageCache, which offers:
prefixto namespace entries (defaults topolingo).ttlMsto automatically expire catalogs (unset means persist indefinitely).storageto swap the backing store (useful for testing).
When localStorage is unavailable (SSR, Safari private mode, locked-down WebViews), the cache drops down to an in-memory MemoryCache so translations continue to work, albeit without persistence between reloads.
Disable caching with cache: false if your catalogs are short-lived or you control caching via HTTP headers.
Usage patterns
Single Page Applications
- Preload the locales you need during app bootstrap to keep translations synchronous.
- Combine with client-side routing to lazily switch locales via
await polingo.setLocale(locale).
Server-Side Rendering / Hydration
- Run
createPolingoonly on the client iflocalStorageis required. - For SSR-only environments, manually construct a
TranslatorwithWebLoaderandNoCache, then hydrate withcreatePolingoon the client for persistence.
Edge runtimes or React Native
- Pass an explicit
fetchimplementation (e.g., fromundici,cross-fetch, or the platform) throughloader.fetch. - Swap the cache for an in-memory implementation if the target does not support
localStorage.
Catalog format
By default the loader expects JSON that matches TranslationCatalog from @polingo/core:
{
"charset": "utf-8",
"headers": {
"Plural-Forms": "nplurals=2; plural=(n != 1);"
},
"translations": {
"": {
"Welcome": {
"msgid": "Welcome",
"msgstr": "Bienvenido"
}
},
"menu": {
"File": {
"msgid": "File",
"msgctxt": "menu",
"msgstr": "Archivo"
}
}
}
}If your backend returns a different shape, use transformResponse to convert it before it reaches the translator.
Tips & gotchas
- Serve catalogs with far-future cache headers and rely on
ttlMsto refresh them periodically. - Handle fetch failures gracefully by catching
createPolingoerrors during startup and surfacing a user-friendly fallback. - When bundling with Vite or Webpack, you can import static catalogs and feed them to a custom loader for fully offline behaviour.
- Use the same domain names (
messages,errors, etc.) clients expect—catalog URLs are derived from the domain.
Related packages
@polingo/core– translation runtime (Translator, caches, helpers).@polingo/node– filesystem loader, middleware, and watcher for Node.js.@polingo/react– React hooks, context provider, and Trans component.@polingo/cli– command line tooling for extraction, compilation, and validation.
License
MIT © Reinier Hernández Avila
