Localization
Multi-language support
Included Languages
| Code | Language |
|---|---|
en-US | English |
de-DE | German |
es-ES | Spanish |
fr-FR | French |
hu-HU | Hungarian |
it-IT | Italian |
pt-BR | Portuguese (Brazilian) |
ru-RU | Russian |
tr-TR | Turkish |
Each player sees the game in their own client locale; the server never reads or stores a per-player language preference. The matching .lang file is resolved client-side, with English as the per-key fallback.
Native Language Files (.lang)
The nine built-in languages ship as native Hytale .lang translation files bundled in the mod jar, and new languages are added the same way - as a small asset pack dropped into your mods directory. This is the recommended way to add or share a language: it is discovered automatically at server start, needs no admin commands, and survives mod updates.
- The full authoring guide (the
mmoskilltree.langfilename rule, the fallback chain, and the zip gotcha) is on the Translation Packs page.
Quest and achievement notice wording (progress ticks, completion jingles, parked notices, the achievement unlock toast and its server banner, claim chimes, the server-first note) is not a .lang file at all - it is authored per moment under Server/ZiggfreedCommon/FeedbackMoments/, and reworded, recoloured, or silenced by dropping a same-named file in a content pack. See Feedback Moments.
Prefer to tweak a handful of strings without shipping a pack? Use the optional per-server JSON admin override below; it layers on top of the native files and always wins.
The Filename Is the Key Prefix
The single most common cause of a raw key on screen
.lang file's name is the prefix of every key inside it. A key written in mmoskilltree.lang resolves as mmoskilltree.<key>, and the exact same key written into a differently named file resolves under that other name, where nothing is looking for it. If a raw key is showing in game, check which file it is in before checking anything else.In practice that means a key goes in the file named for whoever owns it. Most MMO Skill Tree keys go in mmoskilltree.lang, but the jar ships five more, each holding one slice of the mod's own vocabulary:
| File | Holds |
|---|---|
mmoskilltree.lang | UI text, notifications, skill/reward names, command responses - most of the mod's own vocabulary |
npcs.lang | Placed-character display names, keyed npcs.<CharacterName>.name (see below) |
items.lang | Item display names and descriptions the mod adds |
general.lang | Shared cross-cutting strings not specific to any one page |
client.lang | Client-side strings the server never resolves |
server.lang | Server-resolved strings (console output, admin-only sinks) |
A net-new file for this mod follows the same convention: name it mmoskilltree.<domain>.lang, and every key inside it drops the segment the filename already carries (invisible to call sites, since the engine prefixes every key with the file's basename).
An empty value means the key silently never ships
=, an empty key, an empty value - with a per-line warning and keeps the rest of the file, so a key written as key = with nothing after the equals sign simply never ships and renders as its raw id on screen. A duplicated key keeps its first definition, and an unterminated quote gets no diagnostic at all and ships the literal quote character (the mod's own build checks catch these shapes). The standing advice holds: never author an empty value; a string that must render as nothing is handled at the call site instead (Msg.raw("")).The required ZiggfreedCommon jar ships files of its own, in all 9 languages, and you override one of its words by writing into a file with that same name:
| File | Holds |
|---|---|
ziggfreedcommon.commerce.lang | The neutral default words for shop shelves and board difficulty bands, and the economy screens |
ziggfreedcommon.commerce.admin.lang | Everything the shared economy admin command says |
ziggfreedcommon.progression.lang | The shared quest and achievement wording |
ziggfreedcommon.progression.admin.lang | Everything the shared quest/achievement admin commands (/zigprogress and its aliases) say |
ziggfreedcommon.dialogue.lang | The shared conversation engine's own wording |
ziggfreedcommon.feedback.lang | The neutral default notice wording for quest and achievement moments |
ziggfreedcommon.fmt.lang | Shared number, time and list formatting |
Keys You Can Answer Yourself
Some names are looked up by convention, so simply authoring the key is enough to give something a proper, translated name. These work from a content pack or from your own language pack:
| Key | Names |
|---|---|
board.grade.<name> | A bounty board difficulty band |
shop.category.<name> | A storefront shelf |
currency.<name>.name | A wallet |
npcs.<CharacterName>.name | A placed character |
quest.<name>.title / .flavor | A quest's title and its flavor line |
achievement.<name>.title / .desc | An achievement's title and description |
For a shelf or a band the ladder is: what the content itself authors, then your own key, then the shared library's neutral default, then the raw name shown as-is.
Character keys are matched exactly
npcs.Mmo_Hub.name is what resolves the Adventurer's Guide's name and the older MMO_Hub spelling does not. A pack overriding one of those keys, or shipping a character of its own, spells the key exactly as the character is spelled.Admin Override: Custom Translations
Scope: the server's single default language only
en unless changed), set with /mmoconfig language <code>. The JSON override below affects only that one language, and only the small set of strings the server itself resolves and sends (floating combat text, item-slot tooltip hover, console/admin output, quest markdown). It does not retranslate the UI for a player on a different client locale - almost all UI text is resolved client-side from the native .lang packs above, which a server-side JSON file can never reach. To change what a player on locale X sees, ship or edit that locale's .lang pack instead.Use this override to tweak a handful of server-resolved strings (in the server's default language) without shipping a full language pack. These overrides live on your server and always win over pack and built-in translations for that language:
- Set the server's default language if it isn't already what you want to edit:
/mmoconfig language <code>(e.g./mmoconfig language ja) - Create
mods/mmoskilltree/localization/messages-<code>.json(e.g.messages-ja.json) - there is no file to copy, the mod never writes a reference file to disk; start from an empty object - Add only the specific keys you want to override, as a flat key-value map; English key names and values for reference live in the bundled
en-US/mmoskilltree.langfile - Run
/mmoconfig reloadlang - The overridden strings apply immediately, but only to the server-resolved sinks listed above, for the server's configured default language
Message Structure
Language files use a flat key-value structure with placeholder support:
{
"language.name": "English",
"ui.button.close": "CLOSE",
"ui.button.back": "< BACK",
"ui.viewxp.title": "Skill Overview",
"ui.viewxp.level_prefix": "Lv. {0}",
"notify.xp_gain": "+{0} {1} XP",
"notify.level_up": "LEVEL UP! {0} is now Level {1}!",
"skill.mining": "Mining",
"reward.stat_health": "Max Health",
"reward.format.percent": "+{0}%",
"reward.format.flat": "+{0}"
}Message Categories
| Prefix | Description |
|---|---|
ui.* | UI labels, buttons, page text |
notify.* | XP gain, level up, combat notifications |
skill.* | Skill names |
reward.* | Reward type names and formats |
cmd.* | Command responses |
cmd.config.* | /mmoconfig command messages |
Placeholders
Use {0}, {1}, etc. for dynamic values:
"notify.xp_gain": "+{0} {1} XP"→ "+50 Mining XP""ui.viewxp.level_prefix": "Lv. {0}"→ "Lv. 42"
Hot Reload
/mmoconfig reloadlangReload all language files without server restart. New translations take effect immediately.
Server Default Language
/mmoconfig language <code>Sets the server's single default language, stored in mods/mmoskilltree/skill-config.json (default en). This does not change what any individual player sees - per-player locale is resolved entirely client-side and the server never reads or stores it. This command only controls which language the admin-override JSON files above and the residual server-resolved sinks (combat text, tooltips, console output) target.
Fallback Behavior
- Resolution order: admin override, then native language file, then English default
- Missing keys fall back to English, per-key
- A conversation line with no translation behind it renders as its raw key instead, so it can be spotted and fixed rather than dropping the player from their session
Sharing Translations
Override files are portable; share your messages-XX.json with other servers. To publish a full language for everyone, package it as a native language asset pack.
What's Localized
- All UI text (pages, buttons, labels)
- XP and level-up notifications
- Skill names
- Reward type names and descriptions
- Command responses and error messages
- Settings labels