Skip to content
All Guides
How-To Guide30 min read

How to Localize App Store Screenshots Across 30+ Languages

A practical playbook for shipping localized App Store and Google Play screenshots without forking templates per language. Covers translation key structure, multi-locale fan-out, RTL handling, font fallbacks, and automated layout QA.

Eric Isensee
Eric IsenseeFounder · Last updated May 5, 2026

TL;DR

Externalize every caption into a translation key, translate the keys (not the artwork), then send one API request with a list of locales. Screenshots.live renders every locale in parallel from the same template — RTL, CJK, and per-locale overrides handled by the renderer.

Why localize screenshots at all?

Apple's own developer research finds users are significantly more likely to install an app when the App Store listing is in their native language. The same is documented in Google's localization checklist: localized listings convert higher and rank better in search. Translating only metadata strings — title, subtitle, keywords — without translating screenshots is the most common half-measure, and it leaves real conversion on the table because the hero asset is still in English.

The blocker for most teams is operational, not strategic. Translating a five-screenshot set into 30 languages by hand means 150 design files, 150 review cycles, and 150 chances for a typo. The fix is to treat screenshots like any other localized UI: keys in code, copy in a TMS, layout rendered by a build step.

How should you structure translation keys?

Use the same key structure as your in-app translations. Group keys by screenshot ID, then by element role:

translations/en.json
json
{
  "screenshots": {
    "01_home": {
      "headline": "Build faster.",
      "subhead": "Ship every store size in one API call.",
      "badge": "New"
    },
    "02_pricing": {
      "headline": "Plans for every team.",
      "cta": "Start free"
    },
    "03_api": {
      "headline": "Built for developers.",
      "subhead": "REST, Fastlane, and GitHub Actions out of the box."
    }
  }
}

Then the corresponding German file:

translations/de.json
json
{
  "screenshots": {
    "01_home": {
      "headline": "Schneller bauen.",
      "subhead": "Alle Store-Formate mit einem API-Call.",
      "badge": "Neu"
    },
    "02_pricing": {
      "headline": "Pläne für jedes Team.",
      "cta": "Kostenlos starten"
    }
  }
}

The keys never change. Only the values change. Translators work on the value column in their TMS without touching the Screenshots.live template.

Which locale codes should you use?

Use BCP-47 consistently. Use only the language subtag when there is no regional variation (de, fr, ja) and add the region only when the variants diverge meaningfully (en-GB vs en-US, pt-BR vs pt-PT, zh-Hans vs zh-Hant). Both Apple and Google accept BCP-47, though their internal codes differ slightly — see the App Store Connect locale list and Google Play's supported languages. Map them once in your CI script.

How do you fan out renders across locales?

The API takes a template ID, a translation catalog, and an array of locales. It returns one rendered PNG per locale per device:

render.sh
bash
curl -X POST https://api.screenshots.live/v1/renders \
  -H "Authorization: Bearer $SCREENSHOTSLIVE_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "templateId": "tpl_app_release_v3",
    "locales": ["en", "de", "es", "fr", "pt-BR", "it", "nl", "ja", "ko", "zh-Hans", "ar", "he"],
    "devices": ["iphone-6.7", "iphone-6.1", "ipad-12.9", "phone-android"],
    "translations": {
      "en": "@translations/en.json",
      "de": "@translations/de.json",
      "es": "@translations/es.json"
    }
  }'

Behind the scenes the renderer parallelizes by locale and by device. A 12-locale × 4-device render — 48 PNG files — typically completes in under 90 seconds. See the API rendering docs for the full request shape.

How do you handle right-to-left languages?

Arabic (ar), Hebrew (he), Persian (fa), and Urdu (ur) need the entire layout mirrored — text alignment, image positions, arrow icons, even the order of multi-element groups. Half-mirroring (only flipping the text but not the layout) looks wrong to native readers and damages credibility.

In Screenshots.live, mark the template with direction: "auto" and the renderer flips layout, text alignment, and decorative chevrons automatically when rendering RTL locales. Override individual elements with direction: "ltr" when something must stay left-to-right (a phone number, a URL, a code block).

What about per-locale text overrides?

Some languages just do not fit the same caption box. German compound nouns can be 40% longer than English; Japanese and Chinese can be 50% shorter. Allow per-locale text overrides without forking the template:

translations/overrides.json
json
{
  "screenshots.01_home.headline": {
    "en": "Build faster.",
    "de": "Schneller bauen.",
    "fi": "Rakenna nopeammin.",
    "ja": "もっと速く。"
  },
  "screenshots.01_home.subhead": {
    "en": "Ship every store size in one API call.",
    "de": "Alle Formate mit einem Aufruf.",
    "ja": "ワンコールで全サイズ対応。"
  }
}

What about fonts and CJK glyphs?

Latin script fonts (Inter, SF Pro, Roboto) often lack CJK, Cyrillic, Devanagari, or Arabic glyphs — text renders as tofu boxes. Configure font fallbacks per script:

  • Latin / Cyrillic / Greek: Inter, SF Pro, Roboto
  • CJK (Japanese / Korean / Chinese): Noto Sans CJK
  • Arabic / Persian / Urdu: Noto Sans Arabic, IBM Plex Sans Arabic
  • Devanagari (Hindi): Noto Sans Devanagari
  • Thai: Noto Sans Thai, Sarabun

The Noto family covers every script Apple and Google support. Set it as a fallback chain in the template — the renderer picks the right font per code point, no manual intervention.

How do you QA layouts at scale?

Manual review of 30 locales does not scale. Automate the obvious failure modes:

  • Text overflow: render at quarter resolution, OCR the result, diff against the source string. Mismatches mean text was clipped.
  • Missing glyphs: count tofu boxes in the rendered PNG via a vision model or pixel histogram on the Unicode replacement character.
  • Empty translations: fail the build if any locale has more than 5% missing keys vs. English.
  • Length budgets: set a hard length cap per key. If the German translation exceeds it, fail the build instead of letting overflow ship.

How do you upload per-locale screenshots?

App Store Connect and Google Play both accept screenshots per locale. Fastlane deliver reads from fastlane/screenshots/<locale>/ and Fastlane supply reads from fastlane/metadata/android/<locale>/images/phoneScreenshots/. Map your renderer output to those paths and the rest is just fastlane deliver / fastlane supply --skip_upload_apk.

What should you do next?

Combine this with our CI/CD automation guide so localization runs on every release. Use the multi-platform support feature to fan out to iOS, Android, and web stores from the same catalog.

30+ locales, one template

Generate All These Sizes Automatically

Stop resizing screenshots manually. Design one template and render every size, device, and locale with a single API call.

Start Free — Try Screenshots.live