Solo & indie devsこの記事を日本語で読む

Text management mistakes in your first game, and how to undo them

Right now, the text in your game works. The dialogue shows up, the menus read correctly, the item descriptions say what they should. From inside development there is no signal at all that anything is wrong with how that text is stored, because the game is the only thing reading it and the game does not care.

The signal arrives later, and always from outside: you decide to add a language, or an editor asks for the full script, or a player reports a typo you then have to find in forty places. At that moment the way you have been storing text stops being an internal detail and becomes the thing that determines how much work everything costs.

This is a catalog of the mistakes that cost the most, grouped by what they are actually about — where the text lives, how you refer to it, and what gets embedded inside it — plus a way to fix them that does not require stopping development.

None of this hurts today

It is worth being precise about why these mistakes stay invisible for so long, because that is what makes them worth writing down. A solo developer holds the whole game in their head. You know that the shop confirmation and the blacksmith confirmation are the same sentence typed twice, and you know where both are, so duplicating them cost nothing. The cost only appears when the knowledge has to leave your head — when a translator, an editor, a second programmer, or you in eight months needs to work with the text without knowing where anything is.

It is also worth being clear about what triggers it. Adding a language is the big one, because it forces every piece of text to be findable, extractable, and replaceable at once. But the same mistakes bite on much smaller events: renaming your currency, changing a character's speech style, adjusting a tutorial that turned out to confuse people, or having a publisher ask for the word count. Every one of those is easy with well-managed text and grim without it.

The good news is that none of these mistakes is hard to fix individually. They are only expensive in bulk, which is an argument for stopping the bleeding early rather than for a heroic rewrite later.

Where the text lives

The first group of mistakes is about location: text that is somewhere no tool can reach.

  • Text typed directly into code. The classic. It runs fine, but it cannot be exported, counted, or handed to anyone without handing over the source, and there is no reliable automatic way to tell a player-facing line from a debug label
  • Text typed into the editor's scene or prefab data. Subtler than hardcoding and often worse, because it hides inside binary or semi-binary project files where even a text search across the repository may not find it
  • The same sentence copy-pasted into several places. Now a fix has to be applied everywhere it exists, translation is paid for more than once, and the copies drift apart until two screens word the same idea differently
  • Text baked into images. Signs, logos, tutorial diagrams, buttons with the label drawn into the art. It is not text as far as any tool is concerned, and it is invisible in every count and every export until someone plays the game and sees it
  • A spreadsheet that is not the source of truth. A file someone made once, in a personal cloud drive, exported by hand into the project, and edited on both sides since. Nobody can say which version is current, and eventually the answer is neither

How you point at the text

The second group is about identity: how the code asks for a specific string. Getting this wrong is what makes text impossible to update safely later.

The worst version is having no identifiers at all — code that looks up text by the original sentence itself. It works until the sentence changes by one character, at which point every translation attached to it silently detaches. Nearly as bad is naming keys after their content, because the name becomes a lie the first time the wording is edited. Keys should describe where the text appears and what job it does, so a rewrite of the sentence leaves the key untouched.

Two related habits cause quieter damage. Reusing one entry in unrelated places looks efficient — the word 'Open' appears on a door prompt and a menu — but those are the same word only in your language; in others they are different words, or need different grammar, and a shared entry can only ever be one of them. And auto-numbered keys, the ones that come out as text_001 through text_400, break the moment a line is inserted or deleted in the middle and everything after it shifts by one.

# Fragile: identity depends on the wording or on position
lookup("Not enough gold.")
lookup("text_137")

# Durable: identity describes the slot, not the sentence
shop.error.insufficientFunds = "Not enough gold."
door.prompt.open = "Open"
menu.file.open = "Open"

What gets baked into the text

The third group is about the content of the strings themselves: things typed into a line of dialogue that are really layout, formatting, or program logic in disguise.

Hard line breaks are the most common. Someone presses enter in the middle of a sentence so it wraps nicely in the current text box, and now that break is part of the data. Change the box size, the font, or the language, and the break lands in the wrong place — usually mid-phrase, which reads as broken in any language and is genuinely wrong in Japanese, where lines should break at phrase boundaries. Let the renderer wrap, and reserve manual breaks for places where a break is truly intentional, like a poem or a title.

Sentences assembled from pieces are the most damaging. Code that concatenates a fragment, a number, and another fragment produces a sentence that exists nowhere as a whole, so it cannot be read, reviewed, or translated as a sentence. Word order, grammatical agreement, and pluralization all differ by language and none of them survive concatenation. One string with a placeholder in it solves this, and it is easier to write than the concatenation was.

The rest of this group is small but adds up: trailing and leading spaces used as padding, which become invisible garbage the first time a tool trims them; punctuation used to fake layout, like a row of dashes acting as a separator; markup and control characters typed by hand and inconsistently, so half the file uses one tag style and half another; and numbers or dates formatted directly into the sentence rather than passed in, which locks the entire line to one region's conventions.

Fixing it without pausing development

You do not need to stop building the game to get out of this, and attempting a full text refactor in one sitting is how these efforts get abandoned halfway. Work in this order instead.

First, stop adding new instances. Agree with yourself — or your team — on one rule for new text starting today: every new player-visible string goes into the text file with a key, no exceptions. This costs almost nothing per string and immediately caps the size of the problem, which is the single highest-value thing you can do this week.

Second, take an inventory before you migrate anything. Search the project for quoted literals and list what you find by screen or system, without fixing yet. The list is usually shorter than feared and tells you where the mess is concentrated — often one or two systems written early, before you had any conventions.

Third, migrate by screen rather than by file. Moving all the text for the shop, then all the text for the pause menu, keeps the game playable and testable after every step, and you can stop at any point with the game in a working state. Migrating file by file leaves the game half-converted in a way that is hard to verify.

Fourth, dedupe once during the migration, not before it. When you move a string and find its twin, merge them then. Trying to find every duplicate up front is a large, boring task that pays off much less than it seems.

If you are mid-project and only have time for one of these, do the first. A game where new text is clean and old text is messy converges on clean; a game where both are messy does not.

The habits that keep it fixed

The mistakes above all come back the moment attention lapses, so it helps to make the correct path the easy one. Keep the text file in version control alongside the code, so a text change appears in the same history as everything else and you can see what a patch actually changed. Write down your key naming convention somewhere in the project, even if it is three lines in a README, because a convention that lives only in your head is a convention that stops applying the moment someone else touches the project or you come back after a break.

Add a status column, or a marker of some kind, for lines that are placeholder or unfinished. Every project ships with a 'TODO: write this' somewhere visible, and a status column turns that from an accident into a query you can run before release.

Finally, sweep for stray literals periodically rather than never. It takes a few minutes to search the project for quoted text and skim for anything a player could see, and doing it before each milestone catches new strays while they are still cheap. Text that is well managed does not stay that way on its own — but it takes far less effort to maintain than it does to repair.

Related articles