JSON translation

Translate JSON locale files without touching your keys.

Keys stay keys. Nesting stays intact. Only the string values are translated — and only the string values. Every other property type comes back exactly as sent.

View the API docs →
Keys
always preserved
Nested
objects handled recursively
36
output languages per request
100K
free tokens / month

Standard translation tools don't understand JSON.

Generic translation APIs see your JSON as a wall of text. They translate key names alongside values. They flatten nested objects. They concatenate strings they shouldn't. What comes back is structurally broken JSON that requires manual correction before it can be used. If you maintain locale files for a production application, you know that feeding them into a standard translation API creates more work than it saves.

The problem runs deeper than just key names. Standard translation APIs also mangle interpolation variables. A string like "Hello {name}, you have {count} messages" comes back with the variable names translated — "Hola {nombre}, tienes {cuenta} mensajes" — which breaks every runtime that was expecting the original variable name. Hours of debugging follow.

For teams maintaining locale files across multiple languages for a production application, this is not a theoretical concern. It has already happened. The question is how long the manual repair process takes each time.

PolyLingo traverses your JSON before translating.

PolyLingo understands JSON structure. It recursively traverses your object, identifies string values that contain translatable text, and sends only those values to the translation model. Key names are never modified. Numbers, booleans, null values, and non-string types are passed through unchanged. The output is valid JSON with an identical structure — just with translated string values.

Interpolation variables — {name}, {{count}}, %s, and similar patterns — are identified and preserved throughout the translation process. They are replaced with placeholders before translation, and reinstated in their original form in the output. The translation model never sees them as translatable text.

Arrays are handled correctly: each string element is translated, while numeric indices and array structure are unchanged. Mixed arrays containing both strings and non-strings (numbers, objects) are traversed correctly with non-string types passed through unchanged.

Input — flat JSON locale (English)
{
  "nav_home": "Home",
  "nav_pricing": "Pricing",
  "hero_title": "Grow your audience globally",
  "hero_cta": "Get started for free",
  "footer_rights": "All rights reserved."
}
Output — French (keys identical)
{
  "nav_home": "Accueil",
  "nav_pricing": "Tarifs",
  "hero_title": "Développez votre audience mondiale",
  "hero_cta": "Commencer gratuitement",
  "footer_rights": "Tous droits réservés."
}
Input — nested JSON locale (English)
{
  "nav": {
    "home": "Home",
    "pricing": "Pricing",
    "blog": "Blog"
  },
  "hero": {
    "title": "Grow your audience globally",
    "subtitle": "Translate in seconds.",
    "cta": "Get started for free"
  },
  "errors": {
    "notFound": "Page not found",
    "serverError": "Something went wrong"
  }
}
Output — Spanish (structure intact)
{
  "nav": {
    "home": "Inicio",
    "pricing": "Precios",
    "blog": "Blog"
  },
  "hero": {
    "title": "Expande tu audiencia globalmente",
    "subtitle": "Traduce en segundos.",
    "cta": "Comienza gratis"
  },
  "errors": {
    "notFound": "Página no encontrada",
    "serverError": "Algo salió mal"
  }
}
API request — translate to 5 languages in one call
curl -X POST https://api.usepolylingo.com/v1/translate \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "content": "{\"nav_home\": \"Home\", \"hero_title\": \"Get started\"}",
    "format": "json",
    "targets": ["es", "fr", "de", "ja", "zh"],
    "model": "standard"
  }'

# Response:
# {
#   "translations": {
#     "es": "{\"nav_home\": \"Inicio\", \"hero_title\": \"Empezar\"}",
#     "fr": "{\"nav_home\": \"Accueil\", \"hero_title\": \"Commencer\"}",
#     ...
#   }
# }

What PolyLingo guarantees for every JSON translation

  • Key names never modified
  • Nested objects and arrays handled recursively
  • Numbers, booleans, null values passed through unchanged
  • All 36 languages in a single request
  • Auto-detected as JSON — no format flag required
  • Works with flat and deeply nested locale files
  • Interpolation variables ({name}, {{count}}, %s) preserved exactly
  • Output is valid JSON — parseable without modification

Three steps to translated locale files

1

Paste your JSON or call the API

Use the no-code translator for one-off translations: paste your JSON, pick your languages, download the translated files. For automation, call POST /v1/translate with your JSON content and target language codes.

2

Receive all languages in one response

The API returns a JSON object with one entry per target language, each containing the fully translated locale file with identical structure. No per-language calls. No looping. One request for all outputs.

3

Drop the outputs into your messages directory

Write each translated file to messages/es.json, messages/fr.json, messages/de.json — or wherever your i18n library expects them. The structure is identical to your source file, so no further processing is needed.

Where JSON translation matters most

🌐

App i18n with next-intl or i18next

Translate your messages/*.json or locales/*.json files directly. Keys stay intact, nesting is preserved, and interpolation variables come through unmodified. Drop the files into your messages directory and deploy.

🗄️

CMS content exports

Headless CMS platforms often export structured content as JSON. PolyLingo translates the string values while preserving field names, nested content types, and non-string values like dates, booleans, and IDs.

⚙️

API responses and config files

Any JSON structure with translatable string values — product descriptions, notification templates, in-app copy served via API — can be translated without modifying the structure your application depends on.

Frequently asked questions about JSON translation

Are interpolation variables like {name} or {{count}} preserved?

Yes. PolyLingo identifies common interpolation patterns including {variable}, {{variable}}, %(variable)s, and %s before translation. These are replaced with stable placeholders, the surrounding text is translated, and the original variable names are reinstated in the output. The translation model never sees the variable names as translatable content.

What happens to non-string values — numbers, booleans, null?

Non-string values are passed through completely unchanged. PolyLingo only translates string values that contain natural language text. Numbers, booleans, null values, and arrays of non-strings are preserved exactly as they appear in the source.

Can PolyLingo handle deeply nested JSON structures?

Yes. PolyLingo recursively traverses objects of any nesting depth. The translation applies to all string values throughout the structure, regardless of how deeply they are nested.

What if some keys contain non-translatable content like slugs or codes?

PolyLingo translates all string values by default. If you have string fields that should not be translated — slugs, language codes, technical identifiers — the recommended approach is to either exclude them from the JSON you send, or use the explicit format parameter and specify fields to skip (coming soon). For most locale files, all string values are intended to be translated.

Does it work with JSON5 or JSONC (JSON with comments)?

Currently PolyLingo processes standard JSON. JSON5 and JSONC (with comments) should be pre-processed to strip comments and convert to standard JSON before sending. This is a common step in build pipelines and adds minimal overhead.

How many languages can I target in one request?

Up to all 36 supported languages in a single request. The response contains one translated JSON object per language code. Rate limits vary by plan — the free tier allows 10 requests per minute, while Growth and Scale plans allow 200–600 requests per minute.

Translate your locale files in seconds.

Paste your JSON, pick your languages, get back valid locale files for every target language.

Paste your locale JSON and see the output — free, no account required.

Translate JSON locale files without touching your keys — PolyLingo | PolyLingo