Repository navigation
Localization
Home > Localization
Everything you need to know to translate Dungeon Train into another language — what's translatable, how each piece is delivered (resource pack vs. data pack), and how to get credited for it.
Dungeon Train's translatable content is split across three independent systems, each with its own delivery mechanism:
| Content | Mechanism | Applies to | Loaded by |
|---|---|---|---|
| UI text (menus, HUD, advancements, tooltips) | Resource pack | Client only | Vanilla lang-file merging |
| Narrative prose (stories, books, death-lore) | Data pack | Server only |
LocalizationCreditRegistry's server-side siblings — StoryRegistry etc. |
| Localization credit (thank-you on the title screen) | Resource pack | Client only | LocalizationCreditRegistry |
Why the split matters: a resource pack is client-side and active even at the main menu (before any world is loaded) — that's how your language and your translator credit can show up on the title screen. A data pack only becomes active once a world/server exists, so it can't be read at the main menu, but it's the right channel for the game's actual book/story text, since a datapack on the server delivers the same translated books to everyone connected — no client-side pack needed by players.
If you're translating both the UI and the narrative content, you'll end up shipping two separate packages: a resource pack (for UI text + your credit) and a data pack (for story/book text) — see each section below for exactly what goes where.
Since: ongoing; last major pass v0.444.0 (PR #733)
All of Dungeon Train's menu text, HUD labels, advancement titles/descriptions, and tooltips are translation keys — currently ~748 keys in assets/dungeontrain/lang/en_us.json.
- Create a resource pack with the standard
pack.mcmeta+assets/layout. - Add
assets/dungeontrain/lang/<locale>.json(e.g.es_es.json,de_de.json,pt_br.json— must match Minecraft's own locale codes). - Copy whichever keys you want to translate from the mod's
en_us.json(browse it on GitHub:en_us.json) into your file, translated.
You don't need every key. Minecraft always loads en_us.json as the base and layers your selected locale's file on top — any key your file doesn't cover silently falls back to English. Ship a partial translation and expand it over time; nothing breaks.
Nearly every player-facing screen is translatable as of v0.444.0 — settings, world options, the cinematic skip prompt, death-screen stats, advancements, dev-message labels, and more.
Known gap: the in-game creative/dev-gated editor UI (client/menu/*) and the /dungeontrain command tree (command/*) are explicitly out of scope — still hard-coded English. These are dev-tooling surfaces, not part of the player-facing run, so they haven't been prioritized. (Tracked internally; not yet scheduled.)
Dungeon Train bundles several sibling mods via jarJar (Discord Presence, Adventure Item Names, Adventure Item Stats, Player Mob, EnderChestPersistence). Each ships its own namespace under assets/<modid>/lang/, separate from assets/dungeontrain/. If you want full coverage, translate those too — e.g. Discord Presence's title-screen "Connect to the internet?" consent card and feedback-survey screen live in assets/discordpresence/lang/en_us.json (source, translatable since v0.48.0 / PR #52). Add assets/discordpresence/lang/<locale>.json to the same resource pack as your dungeontrain translation — Minecraft merges lang files across all loaded mod namespaces the same way regardless of which mod jar they come from.
Don't be misled by narratives/originals/ or narratives/unused/ folders you might see in the GitHub repo — those are raw author drafts and held-back content, never loaded at runtime, and excluded from the shipped jar entirely since v0.443.0 (PR #731). The actual loaded files are the lowercase JSON ones under narratives/stories/, narratives/random_books/, narratives/starting_books/.
Drop your resource pack in resourcepacks/, enable it from Options → Resource Packs, then pick your language from Options → Language (or the title-screen language button). Changes apply on resource-pack reload — no restart needed.
A resource pack is the route for translating in bulk offline. For fixing the lines that read wrong in the language you're already playing, there's an in-game editor (Help Translate) that edits keys one at a time and submits them for review — no pack, no files, no restart. Approved lines come back down to every client running that language.
Four doorways, all pointing at the language the game is currently displaying:
| Where | Looks like |
|---|---|
| Title screen | A pencil icon stacked above the vanilla Language button |
| ESC menu (in-world) | The same pencil icon, in the icon strip on the Mods | Shaders row — the editor opens over the world, so you can translate while riding the train. Since v0.846.0 (PR #1369); see Pause menu buttons
|
| Options → Language | A labelled "Help Translate" button in the footer row |
| Ways to Help (title screen or ESC menu) | A "4. Help Translate" section — since v0.557.0 (PR #964) |
The Ways to Help section is the only one that's conditional: it appears when the language you're playing in still has lines that were machine-translated and nobody has reviewed (LocalizationCreditRegistry.aiFraction() > 0), and retires itself once a language is fully reviewed. The other three doorways show for any language the mod ships a translation for. None appear on en_us — English is the source language, so there's nothing to translate into.
Inside the editor, the "Needs a human" filter is the useful one: it narrows the list to exactly the AI-written lines nobody has read yet — plus, since v0.874.0 (PR #1403), the lines whose English was edited after they were last translated or reviewed. Those carry an amber ↻ badge beside the key (next to the blue AI one; a line can have both) and the edit screen's English heading says the English changed after this was translated. The "Outdated" filter shows just those lines, so after a batch of English rewrites a translator can sweep exactly what moved. Every translated line remembers the English it came from (source_hash in the provenance sidecars), so this is exact, not a guess — and an approved fix from the relay clears the flag, because it was written against the newer English.
Your submission carries the AI line you replaced, alongside the English source and your own text. It is worth knowing why, because it changes what a good submission looks like from the other end.
Approving a line publishes it to every player in that language, and the person approving it usually cannot read that language. Before this, a submission arrived as English source plus your text and nothing else — so a careful three-word fix to an otherwise decent line and a wholesale replacement with something unrelated looked exactly the same. Now the review page shows English → what the AI said → what you wrote, with the changed words marked and an English back-translation under each, so a genuine correction is visible as a correction.
Two practical consequences:
- Edit the line rather than rewriting it where the AI was close. A small, visible diff is easier to trust and quicker to approve than a from-scratch replacement that happens to also be correct.
- Submitting a line unchanged does nothing. The queue marks it as identical to the machine translation; if the AI line is already right, leave it and spend the effort on one that isn't.
Older builds do not send the replaced line, and submissions from them are still reviewed — they just cost the reviewer the comparison.
A reviewer can now write back. When a line of yours is turned down, the reviewer can say why, and that reply comes to your client: a ● beside the string in the editor's list with the reply on the line under it, the same text above the box when you open the string, and a note on the title screen (plus a toast) when something new is waiting. The usual reasons are worth knowing in advance — a lost %s or %1$s placeholder breaks the screen the line appears on, and a translation that reads well but drifts from the English is not the same line any more.
Replies are fetched every time you open the editor, so one written while you were playing shows up as soon as you go back in. If you have used the main-menu chat panel, the reply also arrives there as a message.
"Good As Is" answers the commonest case: the machine translation is already correct. The button sits on the edit screen beside Save, and it retires that line from your queue — it leaves "Needs a human" and "still to do", and stops being offered. It is per install and reversible: the same button becomes Needs Work, and the All filter still lists the line, tagged ✓ instead of AI. Nothing is published by dismissing a line and nothing happens to it for anyone else; it is only a record that somebody who reads the language went through it and let it stand.
Before this, the only way out of the AI queue was to rewrite a line that needed nothing, so an honest pass through the list met the same lines on every visit.
Since: v0.445.0 (PR #735)
The train's hand-authored stories, welcome/starting books, random chest books, and death-screen lore can be overridden or replaced entirely by a data pack — no mod-jar edits, and it's honored on /reload.
| Content | Data pack path |
|---|---|
| Stories (signed-book letters found via lecterns) | data/dungeontrain/narratives/stories/<id>.json |
| Random chest books | data/dungeontrain/narratives/random_books/<id>.json |
| Welcome/starting books |
data/dungeontrain/narratives/starting_books/<context>/<id>.json (contexts: new_world, respawn, joined_world, nether, end) |
| Death-screen lore | data/dungeontrain/death_lore/<id>.json |
Ship a file at the same path as a bundled one to override it, or a new filename to add to the pool. Full schema + writing conventions (page composition, variant rules, newline semantics): narratives/stories/CLAUDE.md in the repo.
Data packs are per-world (or per-server): drop your pack in <world_save>/datapacks/ (singleplayer) or the equivalent on a dedicated server. Only the server needs it — book text reaches every connected client as regular written-book item data, so players don't need anything installed themselves.
- Vanilla
/reload, or -
/dungeontrain narrative reload(also re-scans random books) and/dungeontrain narrative startingbook reload(op-only testing commands — seeNarrativeCommand.java)
Story/book ids are preserved exactly (only the .json suffix is stripped), so a translated file at the same path doesn't reset players' seen-book tracking or story-set achievement progress.
Death-lore has one extra tier: a per-install filesystem override at config/dungeontrain/user/death_lore/*.json, additive alongside the data-pack tier — useful for a server operator who wants to add lore without packaging a full data pack.
Since: v0.446.0 (PR #736) — see Feature: Localization credits for the full writeup.
If you shipped a UI translation (section 1 above), you can also credit yourself right on the title screen. Add a small file to the same resource pack as your lang/<locale>.json:
assets/dungeontrain/localization_credits/<your_slug>.json:
{
"locale": "es_es",
"name": "Your Name",
"url": "https://example.com"
}locale and name are required; url is optional (omit it to show as plain text instead of a link). This must be a resource pack — the credit needs to be visible on the main menu before any world is loaded, which a data pack can't do. When a player has your locale selected, "Localized by <name>" appears immediately left of the title screen's language button; otherwise nothing shows. Full schema + rules: localization_credits/CLAUDE.md in the repo.
Not something you configure, but worth knowing about: the community shared-book system (players' own signed books, uploaded and redistributed as loot to other players) is filtered server-side by the relay so a player is served books from their own language family first, falling back to English when there aren't enough (relay #101, shipped alongside v0.443.0 / DT#732). This is entirely automatic and lives on the community relay, not in translatable game files — mentioned here only so it's not confused with the systems above.
| I want to translate… | Ship a… | Path | Test with |
|---|---|---|---|
| Menus, HUD, advancements, tooltips | Resource pack | assets/dungeontrain/lang/<locale>.json |
Options → Resource Packs, then Options → Language |
| Stories, welcome books, random books, death-lore | Data pack |
data/dungeontrain/narratives/..., data/dungeontrain/death_lore/...
|
<world>/datapacks/ + /reload
|
| A thank-you credit for your translation | Resource pack (same one as your lang file) | assets/dungeontrain/localization_credits/<slug>.json |
Options → Resource Packs, select your language on the title screen |