Localization string table template
A string table that translators can work from: one row per key, with its context, its length limit, the English source and four translations, plus a glossary and a style guide for each language. Download it as a .zip: the table is a CSV file (UTF-8, comma-separated), the rest is Markdown, and the whole set imports into Nodary, where the CSV becomes a sheet you can use as a string table.
4 files in a .zip (Markdown and CSV), 5 kB
Free, no account, no email. Use it, change it, share it.
Read every file before you download
The overview explains the columns, how to name keys, placeholders and translation states. The table holds 13 sample strings from Saltmarrow, the sample game this site uses everywhere; two cells are wrong on purpose, to show what the checks catch.
Documents
File Localization string table template/Localization string table.md
Localization string table
How to use this template: italic lines are guidance. Replace them with your own words, then delete them. Values in square brackets are yours to fill in. The table itself is the CSV file next to this page.
The files
- Strings: the table itself, one row per string, one column per language
- Glossary: the words translated the same way everywhere, and the names never translated
- Style guide: how the game speaks in each language
Columns
| Column | What it holds |
|---|---|
| key | A unique name for the string, never shown to players |
| context | Where the text appears and who says it: what a translator cannot guess |
| max_length | The most characters the text may take on screen |
| en | The source text |
| fr, de, es, pl | One column per language, named with its code |
Naming keys
Name keys by where the text lives, from the general to the particular, so related strings sort together.
- Pattern: [screen].[element].[detail], such as menu.play or hud.tide.warning
- Lowercase, with dots between the parts and no spaces
- Never reuse a key for a different text: add a new one
Placeholders and markup
Values the game fills in stay in braces, such as {count}; every translation keeps every placeholder of its source. Markup tags, such as the bold tag in item.crystal.desc, stay around the words they mark.
Translation states
- MissingDraft
- DraftReviewed
- ReviewedFinal
- FinalOutdated
- OutdatedDraft
Mermaid
flowchart LR n0["Missing"] n1["Draft"] n2["Reviewed"] n3["Final"] n4["Outdated"] n0 --> n1 n1 --> n2 n2 --> n3 n3 --> n4 n4 --> n1
Example (Saltmarrow, a sample game): Two cells of the sample are wrong on purpose. menu.settings in German, Einstellungen, has 13 characters where the button holds 10, so the length check flags it; the Archivist’s greeting has no Polish yet, so it counts as missing.
This template is free to use, change and share. It comes from Nodary, where these files import as a map of linked documents and the CSV as a sheet.
File Localization string table template/Localization string table/Strings.csv
Strings
| key | context | max_length | en | fr | de | es | pl |
|---|---|---|---|---|---|---|---|
| menu.play | Main menu button | 12 | Play | Jouer | Spielen | Jugar | Graj |
| menu.settings | Main menu button; the button holds 10 characters | 10 | Settings | Paramètres | Einstellungen | Ajustes | Ustawienia |
| menu.quit | Main menu button | 12 | Quit | Quitter | Beenden | Salir | Wyjdź |
| hud.tide.warning | Shown on the HUD two minutes before the tide turns; {minutes} is a number | 40 | The tide turns in {minutes} min | La marée tourne dans {minutes} min | Gezeitenwechsel in {minutes} Min. | La marea cambia en {minutes} min | Zmiana pływu za {minutes} min |
| hud.salt.count | HUD counter; {count} is a number | 20 | Salt: {count} | Sel : {count} | Salz: {count} | Sal: {count} | Sól: {count} |
| dialogue.archivist.greet | The Drowned Archivist, first meeting. Calm and formal: addresses the player formally | 120 | You came down with the tide. Most who do, stay. | Vous êtes descendu avec la marée. La plupart de ceux qui le font restent. | Sie sind mit der Flut herabgestiegen. Die meisten, die das tun, bleiben. | Ha bajado con la marea. La mayoría de quienes lo hacen se quedan. | |
| item.crystal.name | Item name, in the inventory and the shop | 24 | Memory crystal | Cristal de mémoire | Erinnerungskristall | Cristal de memoria | Kryształ pamięci |
| item.crystal.desc | Item description; <b> marks the word to highlight | 140 | Holds one <b>memory</b> of the drowned city. Sells well in the village. | Contient un <b>souvenir</b> de la cité engloutie. Se vend bien au village. | Enthält eine <b>Erinnerung</b> an die versunkene Stadt. Verkauft sich gut im Dorf. | Guarda un <b>recuerdo</b> de la ciudad sumergida. Se vende bien en el pueblo. | Zawiera jedno <b>wspomnienie</b> zatopionego miasta. Dobrze się sprzedaje w wiosce. |
| quest.horn.title | Quest title in the journal | 32 | Before the horn | Avant la corne | Vor dem Horn | Antes del cuerno | Zanim zabrzmi róg |
| quest.horn.goal | Quest objective in the journal; {count} is a number | 60 | Crystals to bring up before the horn: {count} | Cristaux à remonter avant la corne : {count} | Kristalle, die vor dem Horn nach oben müssen: {count} | Cristales que subir antes del cuerno: {count} | Kryształy do wyniesienia, zanim zabrzmi róg: {count} |
| ui.save.done | Message after saving, shown for two seconds | 40 | Game saved | Partie sauvegardée | Spiel gespeichert | Partida guardada | Gra zapisana |
| ui.tide.low | Label of the tide indicator | 16 | Low tide | Marée basse | Ebbe | Marea baja | Odpływ |
| ui.tide.high | Label of the tide indicator | 16 | High tide | Marée haute | Flut | Marea alta | Przypływ |
File Localization string table template/Localization string table/01 Glossary.md
Glossary
Add a term the first time a translator asks about it. A word translated two ways confuses players and doubles the support questions.
Terms
| Term (en) | fr | de | es | pl | Notes |
|---|---|---|---|---|---|
| tide | marée | Gezeiten | marea | pływ | The water level that drives every system |
| salt | sel | Salz | sal | sól | The common resource |
| memory crystal | cristal de mémoire | Erinnerungskristall | cristal de memoria | kryształ pamięci | Always the full name, never “crystal” alone in the shop |
| horn | corne | Horn | cuerno | róg | The signal two minutes before the tide turns |
| [term] | [...] | [...] | [...] | [...] | [...] |
Never translate
- Saltmarrow, the game’s name
- [Character and place names that stay as they are]
- [Platform and brand names]
File Localization string table template/Localization string table/02 Style guide.md
Style guide
Voice
Three words for the game’s voice, and what it never sounds like.
- Voice: [...]
- Never: [...]
Example (Saltmarrow, a sample game): Calm and a little old-fashioned, like the keeper of an archive. Short sentences. No modern slang.
Language by language
| Language | Addressing the player | Typography | Notes |
|---|---|---|---|
| French (fr) | [tu or vous] | A no-break space before : ; ! ? and inside « » | [...] |
| German (de) | [du or Sie] | „Quotes“, nouns capitalised | Often longer than English: check max_length first |
| Spanish (es) | [tú or usted] | Opening ¿ and ¡ | [...] |
| Polish (pl) | [ty, or Pan and Pani] | „Quotes”, three plural forms | Words around the player’s name change with gender |
| [Language] | [...] | [...] | [...] |
Length
Leave room: translations from English often run longer, up to a third in some languages. Set max_length from the space on screen, not from the English.
Plurals and numbers
Languages count differently: Polish has three plural forms where English has two. Put the number after a label (Salt: {count}) or use your engine’s plural system, and format numbers and dates for each language.
How to use it
Replace the sample strings
Keep the columns and the key naming, and put your own strings in. Give every string a context and a length limit before it goes to a translator.
Write the glossary early
Add each term the first time a translator asks about it, with its translation in every language. A word translated two ways confuses players and doubles support questions.
Agree on the style per language
Decide how each language addresses the player and its typography rules before translation starts. Changing it later means rereading every string.
Freeze the source before you send it
Send strings for translation once their English is final. When a source changes afterwards, its translations need checking again.
Import it into Nodary and use it as a string table
Nodary is an AI-native workspace where a team’s documents link instead of piling up. Import the .zip and the CSV arrives as a sheet under the overview, with the glossary and the style guide beside it. On the sheet, String table reads the roles from the headers (key, context, max_length and one column per language), then checks every translation for length and placeholders, gives each one a state, marks a translation outdated when its source changes, and exports files for Unity, Unreal and Godot: CSV, JSON, gettext .po and XLIFF.
- Open a project’s map and choose Import.
- Choose the Folder or ZIP tab, then Choose a ZIP, pick the file and import.
- Open Strings, choose String table, check the roles read from the headers, then Use as a string table.
The Free plan holds ten documents per workspace, the project’s own page included: the template’s four fit with room to spare. The source column is English: if your game is written in another language, make that column the source when Nodary shows the roles.
How Nodary handles game localization
Keeping a string table translators can work from
A string table fails when translators have to guess what a line means or how much room it has, or when text changes after it was translated and nobody notices. These habits prevent all three.
Give every string a context
Who says it, where it appears, what it answers. “Open” is a verb on a door and an adjective on a shop: only the context tells.
Set the length from the screen
Measure how many characters the button, the line or the bubble can hold, and write that limit, not the length of the English.
Never build sentences from pieces
Joining “You found” and “3 crystals” in code breaks word order and grammar in most languages. Give each sentence its own key, with placeholders.
Keep placeholders whole
Every translation keeps every {placeholder} and every tag of its source. A lost {count} shows players a blank, or crashes the game.
One key, one meaning
Never reuse a key for a different text. Add a new key; remove the old one once nothing uses it.
Freeze the source before you send it
Translate text that is final. When a source changes anyway, mark its translations as outdated so they are checked again.
Questions about localization string tables
What is a localization string table?
A string table holds every piece of text a game shows, one row per string: a key the code uses, the source text, notes for translators, a length limit, and one column per language. The game loads the text by key in the player’s language, so text can change and be translated without touching the code.
Which columns should a string table have?
At least a key and the source text, then one column per language. A context column and a maximum length column save most of the questions translators would otherwise ask. This template has all five kinds, with English as the source and French, German, Spanish and Polish.
How should I name string keys?
By where the text lives, from the general to the particular, such as menu.play or hud.tide.warning: lowercase, with dots between the parts. Related strings then sort together, and a key says where to look in the game.
How do I handle plurals?
Languages count differently: Polish has three plural forms where English has two. Either put the number after a label, such as “Salt: {count}”, or use your engine’s plural system with one text per form.
How do I open the CSV in Excel?
Google Sheets, LibreOffice Calc, Numbers and Nodary open it as is. Excel opens it with a double-click only where the computer’s list separator is a comma; where it is a semicolon, as in French, German, Spanish or Polish settings, each row lands in one column. Then import it instead: on the Data tab, choose From Text/CSV, pick the file, set the file origin to UTF-8 and the delimiter to Comma, and load it.
Will Unity, Unreal or Godot read this CSV?
The template’s CSV is made for spreadsheets and for Nodary’s import. Engines each read their own format: from the same table, Nodary’s string table exports CSV for Godot and Unity, gettext .po for Unreal and Godot, JSON for most engines and XLIFF for translation tools.
Can I add languages?
Yes. Add a column named with the language’s code, such as ja or pt-BR. Nodary recognizes codes and language names in the headers, and its string table can add a column for a language too.
Keep the game’s text where the team works.
Import the template into Nodary and the string table sits on the same map as the design and the dialogue, with every translation’s state in view. Free with two members, one project and ten documents, no card needed.