HoneyTranslator - Modern Per-Player Translations for Paper & Folia
HoneyTranslator is a high-performance, thread-safe translation engine designed for large-scale Minecraft servers. Built specifically for Paper and Folia (supporting Minecraft 1.21.1 through 1.21.11, Java 21), it delivers instant, localized experiences by serving messages to players in their chosen language.It is powered by an embedded version of PacketEvents (no ProtocolLib dependency required), features a first-class PlaceholderAPI bridge, and provides an elegant in-game GUI language selector. HoneyTranslator focuses entirely on high-speed, static translations based on your own custom language files, ensuring perfect grammatical accuracy without relying on unreliable machine translation APIs.
Technical Highlights
- Full Folia Compatibility: Engineered specifically for multi-threaded environments. All scheduling utilizes Paper/Folia region-aware schedulers (AsyncScheduler, GlobalRegionScheduler, and per-entity schedulers). The legacy, thread-unsafe BukkitScheduler is never touched, and UI inventories open safely on the owning player's region thread.
- Engineered for 500+ Player Environments:
- Lock-Free Lookups: Player language preferences are stored in a ConcurrentHashMap for $O(1)$ lock-free operations, ensuring safety across Folia region threads, PacketEvents netty threads, and async schedulers.
- Immutable Map Swapping: Translation configurations are loaded behind a single volatile reference to immutable maps. System reloads rebuild the maps in the background and swap the reference instantly in a single assignment, completely preventing ConcurrentModificationExceptions.
- Pre-Parsed Adventure Components: Static translations are parsed into Adventure components once during startup and cached. No overhead is spent re-parsing raw strings in the hot lookup path.
- Batched Asynchronous Storage: Player language changes are batched and written to disk off the main thread only when changes occur. Under MySQL or MariaDB backends, updates propagate across proxy networks instantly without stalling game loops.
- Ultra-Fast Packet Interception: The packet listener performs a single, fast substring check and returns immediately if no translation tokens are present, leaving vanilla chat performance completely unaffected.
- Deep Color Formatting Support: Fully compatible with MiniMessage gradients, rainbow, and hex tags, alongside legacy ampersand/section codes (& or §), curly-brace hex formats ({#RRGGBB}), and spigot hex strings (&x&R&R...). Any of these formatting types can be mixed freely within the same line.
- Extensively Configurable: Easily configure behaviors in config.yml, system messages in messages.yml, inventory designs in gui.yml, and drop custom languages directly into the translations directory.
Requirements
- Server Software: Paper, Folia, or any highly compatible Paper fork (1.21.1 to 1.21.11).
- Java Version: Java 21 or newer.
- Dependencies: None. PacketEvents is fully shaded within the plugin jar. PlaceholderAPI is completely optional but supported for cross-plugin bridge functionality.
Language File Configuration
Languages are loaded from individual YAML files located in plugins/HoneyTranslator/languages/<id>.yml.YAML
meta:
display: "<#FFD93D>Română</#FFD93D>"
locales: [ro_ro] # Client locales that automatically map to this language
gui: # Appearance in the /lang selector menu
material: WRITABLE_BOOK
slot: 15 # Only used when gui.layout is set to MANUAL
name: "<#FFD93D>Română</#FFD93D>"
lore: [ "<gray>Click to use Romanian." ]
messages:
welcome: "<green>Bun venit pe server!</green>"
menu:
title: "<gold>Meniu Principal</gold>"
Key structures are flattened and lower-cased automatically (e.g., welcome or menu.title). Missing translations will gracefully fall back to your designated default language file, and finally back to the literal raw key name if no translation exists.
Core Systems
Dynamic GUI Language Picker
Running /lang opens an interactive chest menu displaying available languages as customizable item buttons.- Layout configurations, borders, background glass, and titles are managed centrally inside gui.yml.
- Button icons, display names, and descriptions are loaded dynamically from each individual language file, eliminating the need to modify your GUI file when adding a new language.
- Includes an optional setting to automatically open the selection menu on a player's first join (open-gui-on-first-join).
Cross-Server Language Syncing
For multi-server setups (using Velocity or BungeeCord), HoneyTranslator supports immediate cross-server synchronization using external databases.YAML
# Add this to config.yml on every server in your network
storage:
type: MYSQL # Supports MYSQL or MARIADB
sql:
host: 10.0.0.5
port: 3306
database: minecraft
username: mc
password: "secret_password"
table: honeytranslator_languages # Automatically generated on startup
- Immediate Writes: Changes made via the GUI, commands, or APIs write to the database immediately on an asynchronous thread.
- On-Join Loading: Player preferences are pulled fresh from the SQL database the millisecond they connect, reflecting changes made on other network servers.
- On-Quit Cleanup: Saved preferences are written upon disconnection and players are cleared from active RAM caches, ensuring no stale data overwrites fresh choices on other instances.
- Automatic Drivers: Required JDBC drivers are fetched safely at startup via the Paper dependency system. If a database connection fails, the plugin logs a clean warning and falls back to flat-file storage to prevent server startup issues.
Smart Packet-Level Auto-Translation
This feature translates messages sent by other plugins that do not natively support HoneyTranslator. When enabled, outgoing chat packets are inspected; if the raw text matches a source language string, it is automatically re-rendered into the recipient's chosen language.- Formatting Insensitive: Color and style differences in outgoing text do not block matches.
- Wildcard Captures: Define variable positions using {} placeholders in both your source and target translation files:
YAML
# languages/en.yml
messages: { greet: "<gray>{} has joined for the first time!</gray>" }
# languages/de.yml
messages: { greet: "<gray>{} ist zum ersten Mal beigetreten!</gray>" }
An outgoing packet containing "Steve has joined for the first time!" will correctly match, extract "Steve", and render "Steve ist zum ersten Mal beigetreten!" for any German-speaking players on the server.
Four Integration Pathways
1. In-Game GUI
Players can type /lang to open the selector menu and pick their language manually.2. PlaceholderAPI
Use local placeholders in scoreboard, tab-list, hologram, or menu plugins. Every single viewer sees the output in their own language.- %honeytranslator_welcome% - Resolves the "welcome" message.
- %honeytranslator_lang% - Displays the current language ID of the player.
| Format Suffix | Example | Intended Target / Output |
| Default | %honeytranslator_welcome% | Uses the default format configured in placeholders.default-format. |
| MiniMessage | %honeytranslator_mm_welcome% | Keeps the text as raw MiniMessage (useful for modern plugins like FancyHolograms). |
| Legacy Ampersand | %honeytranslator_amp_welcome% | Converts to legacy & / hex colors (useful for DeluxeMenus). |
| Section Sign | %honeytranslator_legacy_welcome% | Converts to traditional § + §x hex formatting. |
| Plain Text | %honeytranslator_plain_welcome% | Strips all styling and color codes entirely. |
Commands & Permissions
| Command | Description | Default Permission |
| /lang | Opens the GUI language selector. | honeytranslator.use (Everyone) |
| /lang <id> | Instantly sets your language preference. | honeytranslator.use (Everyone) |
| /lang set <id> | Instantly sets your language preference. | honeytranslator.use (Everyone) |
| /lang list | Prints a text list of available languages. | honeytranslator.use (Everyone) |
| /lang reload | Reloads configuration files and language definitions. | honeytranslator.admin (OP) |
Available Aliases: /honeytranslator, /ht, /language, /languages.
