Engineeringこの記事を日本語で読む

Naninovel localization guide: scripts, managed text, and voice

Naninovel is a visual-novel framework for Unity, and it brings its own script format and its own localization system with it. That is mostly a gift — the mechanism for shipping a second language already exists and you do not have to invent one — but it also means the first decision on any Naninovel project is which system owns which text, because Unity has a localization package of its own and running both over the same strings is a good way to lose a day.

The other thing worth knowing before you start is that a Naninovel translation is not a single pile of text. The engine keeps script dialogue and non-script interface strings in different places, generated by different steps, and the classic bug in a first localization pass is an English build whose menus are still in the original language because only half the pipeline was run.

This article covers that split, how translation documents stay attached to the lines they translate, how to get text to translators who do not have Unity open, and the voice and typography problems that show up once the text has changed length.

Two kinds of text, localized two different ways

The first kind is script text: the lines a player reads inside your .nani scripts. Naninovel scripts are plain text files where a line beginning with a command marker is an instruction, a line beginning with a comment marker is a note for the team, and the rest is displayed content — narration, or dialogue attributed to a character by an identifier at the start of the line. Some commands also carry player-facing text as a parameter, the most important being choices.

The second kind is what Naninovel calls managed text: strings that are not part of any script but still appear on screen. Character display names, interface labels, tips or glossary entries, and other configurable text live here, in their own documents, and they are localized through their own step. If your build shows translated dialogue over untranslated menus, this is almost always the reason.

Alongside both, there are the parts that are neither: text baked into sprites and background art, anything a custom Unity UI you wrote yourself displays without going through Naninovel, and store-facing copy. None of those are covered by the engine's localization at all, and they need their own plan and their own line in the schedule.

; A comment line. Not shown to the player.
@bg village
Misaki: You never told me that.
@choice "Ask about the letter" goto:.Letter

How translation documents stay bound to the source

Naninovel generates localization documents per locale that mirror your scripts, and each translated line is associated with its source line through an identifier rather than by its position in the file. That is a good design and it has one consequence you must plan around: moving lines is safe, and editing the text of a source line is not. Change the original wording and the engine can no longer treat the existing translation as current, which is correct behaviour and also means the line quietly needs attention again.

The practical implication is scheduling, not tooling. Either freeze the source script before translation starts, or accept that every subsequent edit to the original creates a line that has to be found and re-translated. On a story-driven game, writers keep polishing the original right up to release, so the honest plan is usually a partial freeze — lock the chapters that are out for translation, keep editing the ones that are not, and treat any post-freeze change as a change request with a cost in every language.

Regenerating the documents after adding or editing lines is a routine step rather than a dangerous one, but do it deliberately and commit the result to version control before and after. The diff is the only reliable statement of what changed, and it is far easier to hand a translator a list of forty changed lines pulled from a diff than to ask them to find the changes themselves. The exact menu or configuration location for generating documents belongs in the official documentation for the version you are on, since it moves between releases.

Getting text to translators who do not have Unity

Localization documents are plain text and version-control friendly, which suits engineers perfectly and suits most translators badly. A professional game translator is used to working in a two-column view with context beside the source, not in a text file where a stray edit to an identifier silently detaches a line from the sentence it belongs to.

You have two workable options. Give translators the documents directly, with a rule sheet and a strict instruction never to touch identifiers, comment lines, or the structure of the document — this works when the team is small and technically comfortable. Or convert to a spreadsheet for the translation phase and convert back, using a script you own and understand. There is no third option where you paste text around by hand and it stays consistent over a year of updates.

If you convert, prove the round trip before the real batch: take a handful of lines through export, spreadsheet, re-import, and a build, including one line with an inline command in the middle and one choice. A conversion that loses identifiers or reorders the document does not fail loudly; it fails as a handful of lines that quietly stop being translated, discovered by a player.

  • Identifiers, labels, and comment lines are never edited or translated
  • Square-bracket inline commands inside a line are code — keep them, do not rename them
  • Character identifiers at the start of a line stay; the display name is translated in managed text instead
  • Anything ambiguous is flagged as a question, not resolved by guessing
  • The document structure and line order are never rearranged

Voice, and why line edits get expensive after recording

Naninovel can associate voice clips with lines automatically, based on the script and the position of the line within it. If your project is set up that way, inserting, deleting, splitting, or merging a line can shift what plays where — and the failure is not an error message, it is a character saying the wrong sentence in a scene nobody re-tested. Check the voicing chapter of the official documentation for how clip names are resolved in your setup, and then treat any script edit after recording as a change that has to be verified with the sound on.

This interacts with localization in a specific way. If a locale ships original audio with translated subtitles, the audio is bound to the source line, so the translation must not change the line structure — a translator splitting one long line into two for readability is a reasonable instinct that breaks the voice mapping. Say so explicitly in the rule sheet.

If a locale gets its own recording, budget for the fact that recorded audio makes text edits enormously more expensive in that language, and that translated lines rarely match the original's timing. Auto-advance settings, typewriter reveal speed, and any timed effect tuned against the original script need re-checking against the new lengths.

Fonts, length, and everything the printer touches

Because this is Unity underneath, glyph coverage is a font asset problem: a font atlas only renders the characters it was built with, and a missing glyph shows up as an empty box rather than an error. If your project moves between Japanese and Latin scripts, one font for all locales almost never works well — Naninovel supports per-locale font configuration, and the reason to use it is not preference but the fact that a face chosen for Japanese usually has weak Latin letterforms and vice versa.

Length is the other constant. English translated from Japanese tends to run longer in the printer, and the places that break are rarely the main dialogue box, which usually has room. Check the backlog, choice buttons, tips or glossary entries, character name plates, and the settings screen, all of which were sized against the original text and none of which are visible in a script diff.

Finish with a pass in the running game rather than in the documents. Switch locale from the settings screen mid-game and confirm that text already on screen updates, that the backlog is not left holding the previous language, and that saves made in one locale load correctly in the other. A build that reads perfectly in a text editor can still have three screens where nothing was ever wired up.

  • Every script has a current localization document for every shipping locale
  • Managed text documents are complete, including character display names
  • Choice text, backlog, tips, and settings checked in-game, not in the file
  • Fonts verified per locale on real screens, not in a preview
  • Voice mapping re-verified after any line edit that followed recording
  • Locale switching tested mid-session, plus save and load across locales

Related articles