Localization
Localization
Section titled “Localization”The plugin supports multiple languages with full translation coverage.
:::info Version 1.6.0+ Since version 1.6.0, language files are stored externally as JSON files, allowing server operators to customize translations without modifying the JAR. :::
Supported Languages
Section titled “Supported Languages”| Language | Code | Status |
|---|---|---|
| English | en-US | ✅ Complete |
| German | de-DE | ✅ Complete |
:::tip Custom Languages
Additional languages can be added manually. Simply create a <locale>.json file in the localization folder and set the language code in config.json.
:::
Configuration
Section titled “Configuration”Set the language in config.json:
{ "language": "en-US"}Language Files
Section titled “Language Files”Language files are located in the plugin’s data folder:
KyuubiAchievements/└── localization/ ├── en-US.json # English (standard) ├── de-DE.json # German (standard) ├── custom_en-US.json # Custom English overrides ├── custom_de-DE.json # Custom German overrides ├── custom_en-US.json.example # Template for custom translations └── custom_de-DE.json.example # Template for custom translations:::tip Auto-Extraction On first start, the plugin automatically extracts the standard language files from the JAR. Standard files may be updated during plugin updates to include new translations. :::
:::info Version 1.8.6+
Custom translation files (custom_*.json) are NEVER overwritten by plugin updates. Use these files for your own translations to preserve them across updates.
:::
:::tip Custom Languages
Any language can be added manually! Simply create a <locale>.json file (e.g., es-ES.json, pt-BR.json, ja-JP.json) in the localization folder and set "language": "<locale>" in config.json. No code changes required!
:::
File Format
Section titled “File Format”Language files use JSON format:
{ "achievements.ui.gallery": "Achievement Gallery", "achievements.ui.search": "Search...", "achievements.name.first_blood": "First Blood", "achievements.desc.first_blood": "Kill your first enemy"}Benefits of JSON Format
Section titled “Benefits of JSON Format”- Syntax Highlighting - Better editor support
- Validation - JSON schema validation possible
- No Escaping Issues - Special characters handled automatically
- Standard Format - Widely supported and understood
Key Structure
Section titled “Key Structure”Achievement Names
Section titled “Achievement Names”{ "achievements.name.first_blood": "First Blood", "achievements.name.spider_hunter_1": "Spider Hunter I", "achievements.name.spider_hunter_2": "Spider Hunter II"}Achievement Descriptions
Section titled “Achievement Descriptions”{ "achievements.desc.first_blood": "Kill your first enemy", "achievements.desc.spider_hunter_1": "Kill 1 spider", "achievements.desc.spider_hunter_2": "Kill 10 spiders"}Title Names
Section titled “Title Names”{ "achievements.title.spider_slayer": "Spider Slayer", "achievements.title.monster_hunter": "Monster Hunter", "achievements.title.veteran": "Veteran"}UI Text
Section titled “UI Text”achievements.ui.gallery=Achievement Galleryachievements.ui.search=Search...achievements.ui.all=Allachievements.ui.combat=Combatachievements.ui.progression=Progressionachievements.ui.exploration=Explorationachievements.ui.social=Socialachievements.ui.completed=Completedachievements.ui.locked=Lockedachievements.ui.unlocked=Unlockedachievements.ui.progress=Progressachievements.ui.requires=Requiresachievements.ui.reward=Rewardachievements.ui.title=Titleachievements.ui.prev=Previousachievements.ui.next=Nextachievements.ui.page=PageTrigger Descriptions
Section titled “Trigger Descriptions”achievements.trigger.blocks_mined=Mine {0} blocksachievements.trigger.blocks_placed=Place {0} blocksachievements.trigger.kills=Kill {0} {1}achievements.trigger.items_crafted=Craft {0} {1}achievements.trigger.playtime_minutes=Play for {0} minutesachievements.trigger.distance_walked=Walk {0} blocksachievements.trigger.chat_messages=Send {0} chat messagesachievements.trigger.zones_discovered=Discover {0} zonesCommand Messages
Section titled “Command Messages”achievements.cmd.grant.success=Granted {0} to {1}achievements.cmd.grant.already=Player already has this achievementachievements.cmd.revoke.success=Revoked {0} from {1}achievements.cmd.revoke.not_unlocked=Player doesn't have this achievementachievements.cmd.list.header={0}'s Achievements ({1}/{2}):achievements.cmd.list.empty=No achievements unlockedBroadcast Messages
Section titled “Broadcast Messages”achievements.broadcast.unlock={0} unlocked: {1}achievements.broadcast.title={0} earned the title: {1}Custom Translation Files
Section titled “Custom Translation Files”:::info Version 1.8.6+ Custom translation files allow you to add or override translations without losing them during plugin updates. :::
How Custom Files Work
Section titled “How Custom Files Work”- Create
custom_en-US.json(copy fromcustom_en-US.json.example) - Add only the keys you want to override or add
- Custom translations are merged on top of standard translations
- Custom files are NEVER overwritten by updates
Load Order
Section titled “Load Order”Translations are loaded in this order:
localization/{language}.json(e.g.,en-US.json) - Standard translationslocalization/custom_{language}.json(e.g.,custom_en-US.json) - Custom overrides
Keys in the custom file will override keys from the standard file.
Example: Custom Translation File
Section titled “Example: Custom Translation File”localization/custom_en-US.json:
{ "achievements.name.first_blood": "My First Kill", "achievements.desc.first_blood": "Defeat your very first enemy!", "lootbag.name.my_custom_bag": "Treasure Chest", "lootbag.desc.my_custom_bag": "Contains rare treasures!"}Lootbag Localization
Section titled “Lootbag Localization”:::info Version 1.8.5+ All lootbag names, descriptions, and rarities are now fully localizable using translation keys. :::
Lootbag Translation Keys
Section titled “Lootbag Translation Keys”| Key Pattern | Description |
|---|---|
lootbag.name.<id> | Display name of the lootbag |
lootbag.desc.<id> | Description text |
lootbag.rarity.<rarity> | Rarity display name (common, uncommon, rare, epic, legendary) |
Example: Lootbag Translations
Section titled “Example: Lootbag Translations”localization/custom_en-US.json:
{ "lootbag.name.starter_pack": "Starter Pack", "lootbag.desc.starter_pack": "A bag of essential items for new adventurers.", "lootbag.name.epic_treasure": "Epic Treasure Chest", "lootbag.desc.epic_treasure": "Contains powerful weapons and rare materials!", "lootbag.rarity.common": "Common", "lootbag.rarity.uncommon": "Uncommon", "lootbag.rarity.rare": "Rare", "lootbag.rarity.epic": "Epic", "lootbag.rarity.legendary": "Legendary"}localization/custom_de-DE.json:
{ "lootbag.name.starter_pack": "Starterpaket", "lootbag.desc.starter_pack": "Eine Tasche mit wichtigen Gegenständen für neue Abenteurer.", "lootbag.name.epic_treasure": "Epische Schatzkiste", "lootbag.desc.epic_treasure": "Enthält mächtige Waffen und seltene Materialien!", "lootbag.rarity.common": "Gewöhnlich", "lootbag.rarity.uncommon": "Ungewöhnlich", "lootbag.rarity.rare": "Selten", "lootbag.rarity.epic": "Episch", "lootbag.rarity.legendary": "Legendär"}Adding Custom Translations
Section titled “Adding Custom Translations”For Custom Achievements
Section titled “For Custom Achievements”When creating custom achievements, add translations to the custom JSON files:
custom/custom_achievements.json:
{ "achievements": [ { "id": "my_custom_achievement", "category": "progression", "trigger": { "type": "blocks_mined", "target": "any", "count": 100 } } ]}localization/custom_en-US.json:
{ "achievements.name.my_custom_achievement": "My Custom Achievement", "achievements.desc.my_custom_achievement": "Mine 100 blocks of any type"}localization/custom_de-DE.json:
{ "achievements.name.my_custom_achievement": "Mein Eigenes Achievement", "achievements.desc.my_custom_achievement": "Baue 100 Blöcke beliebiger Art ab"}Fallback Behavior
Section titled “Fallback Behavior”If a translation is missing:
- Uses the achievement
idformatted as display name my_custom_achievement→My Custom Achievement- Underscores become spaces, words capitalized
Placeholders
Section titled “Placeholders”Numbered Placeholders
Section titled “Numbered Placeholders”# {0} = first parameter, {1} = second, etc.achievements.trigger.kills=Kill {0} {1}# Result: "Kill 50 Spiders"Named Placeholders (in code)
Section titled “Named Placeholders (in code)”achievements.broadcast.unlock={player} unlocked: {achievement}Adding a New Language
Section titled “Adding a New Language”Step 1: Create Language File
Section titled “Step 1: Create Language File”Create a new JSON file in the localization folder:
KyuubiAchievements/└── localization/ ├── en-US.json ├── de-DE.json ├── fr-FR.json └── es-ES.json ← New language fileStep 2: Copy English File
Section titled “Step 2: Copy English File”Copy en-US.json and rename it to your language code (e.g., fr-FR.json).
Step 3: Translate
Section titled “Step 3: Translate”Translate all values (keep keys unchanged):
{ "achievements.ui.gallery": "Galerie des Succès", "achievements.ui.search": "Rechercher...", "achievements.name.first_blood": "Premier Sang"}Step 4: Configure
Section titled “Step 4: Configure”Set the language in config.json:
{ "language": "fr-FR"}Translation Guidelines
Section titled “Translation Guidelines”Consistency
Section titled “Consistency”- Use consistent terminology throughout
- Match game terminology where applicable
- Keep placeholder positions logical
Length
Section titled “Length”- UI elements have limited space
- Test translations in-game
- Abbreviate if necessary
Special Characters
Section titled “Special Characters”- Umlauts and accents are supported (ä, ö, ü, é, etc.)
- Unicode characters work
- Emoji support depends on client font
Example Translations
Section titled “Example Translations”Achievement Chain (English)
Section titled “Achievement Chain (English)”{ "achievements.name.miner_1": "Novice Miner", "achievements.name.miner_2": "Apprentice Miner", "achievements.name.miner_3": "Journeyman Miner", "achievements.name.miner_4": "Master Miner", "achievements.desc.miner_1": "Mine 100 blocks", "achievements.desc.miner_2": "Mine 1,000 blocks", "achievements.desc.miner_3": "Mine 10,000 blocks", "achievements.desc.miner_4": "Mine 100,000 blocks"}Achievement Chain (German)
Section titled “Achievement Chain (German)”{ "achievements.name.miner_1": "Bergbau-Anfänger", "achievements.name.miner_2": "Bergbau-Lehrling", "achievements.name.miner_3": "Bergbau-Geselle", "achievements.name.miner_4": "Bergbau-Meister", "achievements.desc.miner_1": "Baue 100 Blöcke ab", "achievements.desc.miner_2": "Baue 1.000 Blöcke ab", "achievements.desc.miner_3": "Baue 10.000 Blöcke ab", "achievements.desc.miner_4": "Baue 100.000 Blöcke ab"}Hot Reload
Section titled “Hot Reload”Language changes require a server restart to take effect.
:::tip Development During development, consider creating a reload command to test translations without restarting. :::
Migration from v1.5.x
Section titled “Migration from v1.5.x”If you’re upgrading from v1.5.x or earlier:
- Automatic Migration - The plugin automatically extracts new JSON files on first start
- Old Format - The old
.langfiles inServer/Languages/are no longer used - Custom Translations - Copy your custom translations to the new JSON format in
localization/
Converting .lang to JSON
Section titled “Converting .lang to JSON”Old format:
achievements.name.my_achievement=My Achievementachievements.desc.my_achievement=Do something coolNew format:
{ "achievements.name.my_achievement": "My Achievement", "achievements.desc.my_achievement": "Do something cool"}