Skip to content

Localisation

A Patter project is ready to translate from the start: every line, narration, choice prompt, and character name has a stable ID that its translations hang off. Running the translation side of a project is one small loop, and one rule keeps it sane: writers only ever see and edit the source language. Translations live in their own files, never on the writing surface - which is also what makes staleness computable (below).

The translation round-trip: export source strings as JSON, xlsx, or PO; a translator fills them in; import them back into the locale shards. You only ever edit the source language, and stable line ids mean a moved or edited line never orphans its translation. You edit here Source shards export JSON · xlsx · PO Translator import Locale shards You only ever edit the source language. Stable line ids mean a moved or edited line never orphans its translation.

In Project Settings ▸ Language, list the languages you’ll ship and mark the default (the one writers author in). That’s the whole setup.

Production ▸ Export / Import Localisation… (also reachable from the Language tab) runs both halves:

  1. Export writes the source text - and, for a chosen language, its current translations - in the translator’s preferred format (below). Hand the file over.
  2. The translator fills in the Translation column/fields and sends it back.
  3. Import reads the language from the file (or you set it) and reports how many lines landed. Translations go into that language’s own file; the source is untouched, and the writing surface still shows only the source language.

Run the loop as often as you like - it’s incremental, not a one-shot. Which brings us to:

What changed since last time: the Status column

Section titled “What changed since last time: the Status column”

Writers keep writing while translation happens, so the export tracks staleness per line. The Excel export shows it as a Status column:

  • (blank) - not translated yet.
  • translated - has a translation, and the source line hasn’t changed since.
  • stale - has a translation, but the source line was edited after it was translated: it needs re-checking against the new wording.

On import, unflagged rows are accepted as fresh. A row still marked stale has its text imported but stays flagged: the translator confirms a re-check by clearing the “stale” cell, not by re-sending the file - so an old spreadsheet can never silently bless an outdated translation. (PO files carry the same signal as the standard #, fuzzy flag.)

All three carry the same IDs and the same staleness signal; pick by who’s receiving the file:

  • Excel (.xlsx) - for human translators working by hand: one sheet per scene, columns ID / Source / Translation / Comments / Status. The friendliest to non-technical folk.
  • PO / POT - for agencies and gettext-based tooling (Poedit, Weblate, Crowdin, …). Exporting with no language gives a blank POT template; staleness is #, fuzzy.
  • JSON - for pipelines and engines: plain ID → string tables, easy to transform or feed into your game’s own localisation system.

Translator-facing comments come from your documentation notes routed to the loc channel - see Reviewing & feedback.

At publish time (Project Settings ▸ Publish ▸ Localisation) you pick how the built bundle carries text:

  • Embedded (default): every translated language ships inside the bundle. The runtime resolves the right text and can switch language live, mid-game, with no rebuild. Right for self-contained games - nothing else to set up.
  • IDs-only: the bundle ships no text at all; the runtime hands your game each line’s ID and your game’s own localisation system supplies the string. Right when the game already has a loc pipeline (Unity Localization, i18n, a CMS…).
    • Embed source language for debug (sub-option): adds the source text to an IDs-only build just so it’s playable before your loc system is wired up. It warns it’s not for release; leave it off for a real build.

Crucially, the choice doesn’t change the translation loop above: either mode exports and imports the same files. Going IDs-only never cuts you off from Patter’s round-trip - you still hand translators the same spreadsheets and feed the results into whichever pipeline ships them.

The Play window always previews fully translated, whatever the build mode: switch language from its menu and read the script in any locale, even on an IDs-only project. A string missing in a locale plays as the source text flagged <Untranslated: …>, so a half-finished translation is impossible to miss.

The same loop, scriptable (see the CLI):

Terminal window
patter loc-export -o strings.json --format json # a blank template (all source, empty translations)
patter loc-export -o fr.xlsx --format xlsx --locale fr # the fr table as a spreadsheet
patter loc-import fr.xlsx # bring a translated file back

--format is json | xlsx | po; omitting --locale produces a blank template / POT. The build mode is picked per export too: patter export --ids / --source-debug.

How the two modes look from inside the game - setLocale, interpolate, the untranslated fallback, all four runtimes - lives with the rest of the integration docs: Localisation at runtime.

MIT-licensed open source · Made by · patterkit.com