Skip to content

String tables for game localization, checked before they ship.

One row per key, with context and a maximum length for your translators, and one column per language. Each translation carries its state, strings that run too long or lose a placeholder are flagged as you type, and the table exports to CSV, JSON, .po and XLIFF for Unity, Unreal and Godot.

Saltmarrow’s string table in Nodary: keys, context and maximum lengths beside English, French, German, Japanese and Brazilian Portuguese columns, a coloured bar for each translation’s state, and above the grid the progress of each language with the strings left to fix in German and Brazilian Portuguese.
Saltmarrow is a sample project: its studio, team and game are fictional.

The string table lives in the project

Turn any spreadsheet into a string table, or start from a ready one. Nodary reads the column roles from your headers, such as Key, Context, Max length, English, or Godot’s keys, en, fr, and adds a language as a new column in one click. The table is a document on the same map as the dialogue, characters and systems its text comes from, and links to them like any other document.

  • Type / and pick String table, or turn an existing sheet into one
  • Column roles guessed from the headers, then checked by you
  • Co-editing cell by cell: two reviewers on different cells never overwrite each other
  • Right-to-left languages such as Arabic and Hebrew written right to left

What it does not do Dialogue lines do not reach the table by themselves: keys are typed, pasted, imported from a spreadsheet or added by an agent. A table holds up to 50,000 cells, so a large game splits its text across several tables.

The Saltmarrow project on Nodary’s constellation map: documents grouped around hubs for Vision, World and story, Characters, Systems, Production, Localisation, Audio and Art direction, joined by hierarchy lines, with two teammates’ cursors and the list of who is live.
The string table sits under the Localisation hub, one link away from the documents its text comes from.

Every translation has a state and a check

A translation is missing, draft, reviewed, final, or source changed once its source text moves after it was written. Nothing is rewritten when the source changes: each translation remembers the text it was made for. As you type, Nodary flags a string longer than its limit in characters a player sees, a placeholder lost or added, text left in the source language, and stray spaces at either end.

  • Progress for each language, filtered to what needs work or has problems
  • A translator panel: source, context, character count and placeholders to keep
  • Mark a selection reviewed or final, or keep states after a minor source change
  • Placeholders read in ICU, i18next, Unity, Unreal and printf forms, and markup tags

What it does not do There is no translation memory, terminology base or built-in machine translation. Translations come from your translators, or from an AI agent you ask, and an agent’s work arrives as drafts.

Context
Banner when a storm forms. {seconds} counts down
Source (English)
Storm in {seconds} s. Get to the stilts.Keep {seconds}

38 of 44 characters

  • Placeholders: missing {seconds}
Pseudo-localised (to test the interface)[Šţóŕɱ íñ {seconds} š. Ĝéţ ţó ţĥé šţíĺţš. ~~~~~~~~~~~~]

Files for engines and translators, and a feed for your build

Export CSV with every language for Godot and Unity, JSON for i18next and engines, gettext .po with the key as context for Unreal and Godot, and XLIFF 1.2 for translation tools, which carries each string’s state, limit and context. A pseudo-localised language shows untranslated or clipped text in your UI before any translation exists. And when a build should not wait for anyone, it fetches the table itself from a stable address with a read-only data key.

  • Import XLIFF 1.2 or 2.0, .po, JSON or CSV, matched by key, with a preview
  • An empty translation in a file never erases one in the table
  • One language as JSON, .po or XLIFF, or all as CSV; final=1 keeps final strings only
  • An unchanged table answers 304, up to 120 requests a minute per key

What it does not do Plural forms live as ICU messages inside one cell: plural entries in a .po file are skipped on import. The feed only reads; nothing is written back to Nodary through it.

Saltmarrow’s string table in Nodary with its Export menu open: CSV for Godot and Unity with every language, a CSV with a pseudo-localised language, then, for one chosen language, JSON for i18next and engines, gettext .po and XLIFF 1.2.
Every format is in the string table’s Export menu. The Data feed button, in the same toolbar, serves the table to a build by its address.

Agents fill the table without rewriting it

Connected over MCP, an agent reads the table with get_localization: each language’s progress and the strings that still need work, with their context, limit and problems. set_translations writes by key, as drafts unless you ask it to approve, adds keys or a language column, and reports which strings came out too long or lost a placeholder. People editing the table at the same time keep their cells.

Connect an agent

You askFill in the missing German strings in the Saltmarrow string table as drafts. Keep every placeholder, stay under each max length, and tell me which ones still have a problem.

Tools it calls
  • search_documents
  • get_localization
  • set_translations

Questions

How do I export game strings to Unity, Unreal or Godot?

Open the string table’s Export menu. CSV carries every language, a keys column then one column per language, as Godot and Unity read it; gettext .po carries one language with the key as context, for Unreal and Godot; JSON gives one language as a flat key-to-text file for i18next and engines. The import itself happens in your engine, with its own localization tools.

Does Nodary translate the text for me?

No. There is no translation memory and no machine translation service built in. Your translators work in the table, or in their own tool through XLIFF, and an AI agent you connect can write translations too, which arrive as drafts for someone to review.

What happens to a translation when the source text changes?

Each translation keeps a fingerprint of the source it was written for. When the source changes, its translations show as source changed and nothing is rewritten. If the edit was minor, Source change is minor keeps their states as they were.

Can our build download the strings automatically?

Yes. Any member can create a read-only data key in their profile, for the whole workspace or one project, and the table’s Data feed button lists its addresses. A build fetches one language as JSON, .po or XLIFF, or every language as CSV, and final=1 leaves out anything not yet final.

Which placeholders and tags does the check understand?

ICU messages, including plural and select, {name} and {0} as Unity and Unreal write them, {{name}} from i18next, printf forms such as %s, %d and %1$s, and markup tags such as <b> or <color=#f00>. Length counts the characters a player sees: an accented letter or an emoji counts once, and tags do not count.

Can translators send their files back?

Yes. Import XLIFF 1.2 or 2.0, gettext .po, JSON or CSV, up to 8 MB. Translations are matched by key, keys the table does not have are listed rather than added, a preview shows each change before you apply it, and a translation made from an older source comes in as source changed.

Put your strings next to your game.

Start free, type / and pick String table, and paste your first keys. No card, nothing to install.

Free for two members and ten documents. No card.