Skip to content

Localization

The quest system ships with full English (en-US) and German (de-DE) translations. Server owners can edit existing translations, add new languages, and add custom translation keys for their own quests.

Translation files live in the localization/ folder inside your quest data directory:

configs/kyuubisoft_questbook/
localization/
en-US.json <-- English (base, auto-updated)
de-DE.json <-- German (base, auto-updated)
custom_en-US.json <-- Your English overrides (never overwritten)
custom_de-DE.json <-- Your German overrides (never overwritten)
custom_en-US.json.example <-- Template file
custom_de-DE.json.example <-- Template file

Base files (en-US.json, de-DE.json) are extracted from the mod JAR and updated when the mod ships a newer version. Custom files are never touched by updates.

Translation keys follow a dot-separated naming convention:

en-US.json (excerpt)
{
"_localization_version": "22",
"quest.book.title": "QUEST BOOK",
"quest.daily": "Daily Quests",
"quest.weekly": "Weekly Quests",
"quest.story": "Story Quests",
"quest.status.active": "ACTIVE",
"quest.status.completed": "COMPLETED",
"quest.status.locked": "Locked",
"quest.progress": "{current}/{target}",
"quest.rewards.tokens": "{amount} Quest Tokens",
"quest.rewards.item": "{amount}x {item}",
"quest.turn_in.npc": "Turn in: {0} ({1}, {2})"
}

Common prefixes: quest.* (UI labels), tab.* (navigation), quest.status.* (statuses), quest.rewards.* (reward templates), quest.hud.* (HUD tracker), admin.* (admin panel), error.* (error messages).

Placeholders use either numbered ({0}, {1}) or named ({amount}, {item}) syntax.

:::danger Critical: Always bump the version when adding new keys The quest system uses a file-first pattern. If a localization file already exists on disk, it is not replaced by default. The only way to trigger an update is through the version number.

If you add new translation keys to the base files in development but forget to bump _localization_version, servers that already have the old file will never receive your new keys. :::

The version check works as follows:

  1. On startup, the mod reads _localization_version from the file on disk
  2. It compares it to the version compiled into the mod
  3. If the file version is lower, the old file is backed up and the new version is extracted
  4. If versions match, the existing file is kept as-is

Backups are saved as en-US.json.backup-v{N} so you can compare and merge any manual edits you made.

When you create custom quests, their names and descriptions can use inline translations:

custom/custom_quests.json
{
"quests": [
{
"id": "my_quest",
"name": { "en-US": "My Quest", "de-DE": "Meine Quest" },
"description": { "en-US": "Do the thing.", "de-DE": "Mach die Sache." }
}
]
}

Alternatively, use localization keys and define them in custom locale files:

localization/custom_en-US.json
{
"quest.my_quest.name": "My Custom Quest",
"quest.my_quest.description": "Complete the custom objective."
}

To change any existing translation text without modifying the base file, add the key to your custom file:

localization/custom_en-US.json
{
"quest.book.title": "ADVENTURE LOG"
}

Custom translations are loaded after base translations, so they override any matching keys.

The system auto-discovers language files by scanning the localization/ folder. To add a new language:

  1. Create a new file named {locale}.json (e.g. fr-FR.json)
  2. Add the _localization_version key and translate all keys from en-US.json
  3. Set the server language in config.json:
    {
    "language": "fr-FR"
    }
  4. Reload the config with /ksquestadmin reload

The translation lookup follows this priority:

  1. Current language (e.g. de-DE) with custom overrides merged in
  2. English (en-US) as fallback
  3. The raw key string if no translation exists

This means you only need to translate the keys you want — any missing keys will fall back to English automatically.

After editing any localization file, run:

/ksquestadmin reload

This reloads all translation files from disk, including custom files. No server restart is required.