Localization

Intermediate Last updated Jul 9, 2026

On this page

Localization is built into the pipeline, not bolted on: each language gets its own text, voice-over and lip-sync animation, produced by the same build.

How it’s organized

  • Author quests in one source language (the quest’s source_culture, e.g. en).
  • Translations are CSV sidecars (Loc/<Quest>.<culture>.csv) keyed by the stable line ids. Untranslated keys fall back to the source text; the source file is never overwritten.
  • The cultures your project builds are listed in Project Settings → Plugins → Questwright Studio → Build Cultures (the Localization tab manages this for you).

The Localization tab

Add languages, see per-quest translation coverage, and machine-translate missing lines with your own Claude or OpenAI key. Machine results are marked “machine, needs review” so a human pass is easy to track. Keys are stored per-user (never in the repo), same as voice keys.

The Localization tab with language coverage and the machine-translate action

Building languages

The Build tab has a checkbox per culture. Each built language gets:

  • its own String Tables (dialogue, choices, journal text);
  • its own voice-over, using the per-language voice cast from the Voice tab;
  • its own lip-sync bake from that language’s audio.

Per-culture assets live under /L10N/<culture>/ and are swapped by the engine’s own localization system.

The one caveat: PIE vs packaged

Unreal applies per-culture asset swapping (audio, face animation) only in packaged/cooked builds; in PIE you always hear the source-culture voice. Text localization works everywhere, including PIE. This is engine behavior, not a setting to fix; test localized VO in a packaged build.

Dynamic text and localization

{PlayerName} and custom {Token} placeholders survive translation. Substitution happens at display time via FText::Format, so translators can reorder tokens freely within a sentence.