Skip to main content
Once you’ve published a distribution, consuming it is plain HTTPS. There is no SDK, no authentication and no handshake — just a manifest and the files it points at. This page covers the client side. For the manifest’s exact shape and cache headers, see the Content delivery manifest reference.

Quick start

That’s the whole contract.
Fetch one language, not all of themThe manifest lists every language the distribution publishes, but a screen renders one. Fetching them all costs N requests and N× the bytes to display the same page — on a 12-language project that’s 12× the payload for nothing.Take the language from your app’s locale, not from iterating manifest.files.
You never construct a file URL yourself — take files[].url from the manifest. It’s absolute, so a distribution published to your own bucket or CDN needs no client change.

Web apps

i18next

Register a backend so i18next requests exactly the language it needs, when it needs it. Do not preload every file into resources.

Split by module (i18next namespaces)

If the distribution has Split by module enabled, it publishes one file per (language, module) instead of one per language, laid out as <language>/<module>.json. Match on both:
Then consume a namespace where you need it:
Keys resolve within their namespaceA key stored in TextSetu as checkout.title ships inside checkout.json as title. So it’s t("title") from the checkout namespace, or t("checkout:title") from anywhere else — not t("checkout.title").That’s required for i18next to resolve it at all, which is why the prefix is stripped rather than kept.
To avoid a loading flash on a route transition, warm the namespace first:
Official i18next documentation:

Plain JSON, without a framework

A language picker, with no extra request

languageDetails carries the label, flag and text direction, so the picker renders from the manifest you already fetched:
Always keep that fallback: languageDetails is optional, and releases published before the field existed don’t carry it.

Mobile apps

Packaged resources — strings.xml, Localizable.strings, .arb — are resolved at build time and cannot be replaced at runtime. So the pattern is: fetch, cache to disk, parse yourself, and keep the bundled files as the fallback for a first launch with no network.
The same shape works on iOS and Android. Two things worth doing:
  • Key the disk cache on contentHash. It changes exactly when the content changes, so you never need to guess whether your copy is stale.
  • Load at launch, apply at next launch if your UI can’t re-render mid-session. Fetching in the background and swapping on the next cold start avoids strings changing under the user.

Server-side rendering

Fetch the manifest at boot, then refresh on an interval or on a webhook.
Loading every language is right here — a server renders all of them. This is the one case where the “fetch one language” rule doesn’t apply. Better than polling: subscribe to the distribution.published webhook and call refresh() when it arrives.

Pulling in CI

For interchange formats, or to commit translations into your repo:
To fail a build when a language is missing:

Handling errors

Your client should handle four cases. See the status code reference for the full list.
Always have a local fallback. Ship a baseline copy of your source language with the app and treat the remote files as an upgrade. A network failure then degrades to slightly stale strings instead of an empty screen:

Detecting a new release

Two options, no polling of the file contents required:
  • X-TextSetu-Release — the manifest response carries the release version as a header, so you can detect a change without parsing the body.
  • Webhooks — subscribe to distribution.published for a push the moment a release lands. See the Webhooks guide.