Assume you already return JSON in one language (say English). Product wants fr. You do not want a string catalog or a parallel i18n CMS.
Pattern
- Build the source response as you do today.
- Ensure it under your real route identity + target lang.
- On later requests for that locale, get (or ensure again if you still have the body).
- On GET 404, fall back to source JSON.
Client asks for fr
→ GET translations?endpoint_url=…&lang=fr
→ 200 localized JSON
→ or 404 → serve source / ensure then serveExample shape
Source:
{
"id": "m1",
"title": "Lunch",
"items": [{ "name": "Soup", "sku": "SP01" }]
}Ensure with skips so identifiers stay stable:
{
"endpoint_url": "https://api.acme.com/v1/menus",
"lang": "fr",
"source_lang": "en",
"data": { "...": "..." },
"skip_paths": ["id", "items.*.sku"]
}Same structure comes back; only eligible strings change.
Where to put the call
Common choices:
- Write / publish path — ensure when content changes (menus, CMS publish)
- Read middleware — ensure on first locale miss, get thereafter
- Agent / vibe loop — curl ensure once, then hit your API with
Accept-Language/?lang=
See Quickstart for curl, and Concepts for TTL and siblings when source changes.