Skip to main content

Internationalization

Generally it's a good idea to support translations in your plugin, especially if you want to appeal to the largest user base. Adventure makes this simple by adding a server-side translation layer to almost all text that ends up being displayed to clients.

Javadocs

Adventure's Javadocs for all-things translations can be found here.

GlobalTranslator

All translation is done through GlobalTranslator. You can render translations yourself and add new sources for translations.

You can add sources to the GlobalTranslator by creating instances of TranslationRegistry or implementing the Translator interface yourself.

Where translations work

Vanilla Minecraft handles translations on the client by using the language files bundled with the client or provided via resource packs. If you don't want to send custom language files in a resource pack, server-side translations are the only alternative. They work anywhere the component API exists, except for ItemStack display text like the display name or lore. So chat, entity display names, scoreboards, tab lists, etc., all support translations.

caution

The player's language as declared in the settings packet sent by the client arrives after the player has joined the server, so there are no guarantees that translations will work for a client that is joining during the PlayerJoinEvent or any earlier event. You can listen for the first PlayerClientOptionsChangeEvent after joining to know with 100% certainty what language the client that joined is using.

Examples

ResourceBundle

src/main/resources/your/plugin/Bundle_en_US.properties
some.translation.key=Translated Message: {0}
TranslationRegistry registry = TranslationRegistry.create(Key.key("namespace:value"));

ResourceBundle bundle = ResourceBundle.getBundle("your.plugin.Bundle", Locale.US, UTF8ResourceBundleControl.get());
registry.registerAll(Locale.US, bundle, true);
GlobalTranslator.translator().addSource(registry);

This creates a new TranslationRegistry under a specified namespace. Then, a ResourceBundle is created from a bundle located on the classpath with the specified Locale. Finally, that ResourceBundle is added to the registry. That registry is then added as a source to the GlobalTranslator. This makes all the translations available server-side.

Now you can use translation keys in translatable components.

final Component message = Component.translatable("some.translation.key", Component.text("The Argument"))

This will show to clients using the US English language: Translated Message: The Argument.