Skip to content
This repository was archived by the owner on Oct 6, 2025. It is now read-only.

Commit ed5fbb0

Browse files
committed
MiniMessage translator docs
1 parent 7d75ebf commit ed5fbb0

4 files changed

Lines changed: 179 additions & 0 deletions

File tree

source/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ There are many community-supported libraries that extend the capabilities of Adv
3939
tablist
4040
resource-pack
4141
minimessage/index
42+
localization
4243

4344
platform/index
4445

source/localization.rst

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
.. _localization:
2+
3+
Localization
4+
============
5+
6+
Adventure provides a way to utilize Minecraft's built-in localization system for client-side translations as well as an additional Adventure-specific system for translating text.
7+
8+
Using Minecraft's localization
9+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
10+
11+
To send text to a player that will be translated in the language they have selected in their client settings, use a translatable component.
12+
For example, :java:`Component.translatable("block.minecraft.diamond_block")` will render as "Block of Diamond" (or translated to another language) when viewed by the client.
13+
Some translation keys have arguments which are inserted into the translated content.
14+
For example, :java:`Component.translatable("block.minecraft.player_head.named", Component.text("Kezz101"))` will render as "Kezz101's Head".
15+
Translatable components can have styling, hover/click events and children components just like any other component type.
16+
17+
Resource pack language files
18+
----------------------------
19+
20+
You can provide translation files in a resource pack in order to change existing translations or add new ones.
21+
For a guide on how to do that, see the `Minecraft Wiki <https://minecraft.wiki/w/Resource_pack#Language>`_.
22+
23+
Using Adventure's localization
24+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
25+
26+
Adventure also provides a way to handle localization in Adventure itself.
27+
This can be useful in environments where you do not have access to resource packs, or wish to do translations yourself, without relying on Minecraft's translation system.
28+
29+
Any component that is sent to a client is ran through the ``GlobalTranslator`` using the locale of the client.
30+
This means that if you wish to have automatic translation of components using your own translation data, you can add a ``Translator`` to the ``GlobalTranslator``.
31+
You can either provide your own implementation of ``Translator`` or use one of the implementations that Adventure provides.
32+
33+
Once you have a ``Translator`` instance, you can register it to the ``GlobalTranslator`` using :java:`GlobalTranslator.translator().addSource(myTranslator)`.
34+
This will then make it available for automatic translation across the platform.
35+
36+
.. warning::
37+
38+
Some implementations may not use the ``GlobalTranslator`` in every area, or at all.
39+
For example, Paper does not use it for items, and Minestom does not use it unless specifically enabled.
40+
Please consult the documentation for your platform for any limitations.
41+
42+
Using a custom ``Translator``
43+
-----------------------------
44+
45+
A ``Translator`` is a simple interface that provides two ways of translating content.
46+
47+
The first ``translate`` method provides the translation key and locale as an argument and expects a nullable ``MessageFormat`` in return.
48+
This system is comparable to Minecraft's built-in localization system, using the standard Java `message format <https://docs.oracle.com/javase/8/docs/api/java/text/MessageFormat.html>`_ for arguments.
49+
50+
If the first ``translate`` method returns ``null`, the second method which provides the translatable component and locale as an argument can be used.
51+
This method allows for much richer customization of the translation process as you can return an entire component.
52+
This means you can, for example, customize the colour and styling of the translated component, rather than relying solely on strings for the message format system.
53+
54+
.. warning::
55+
56+
If you are overriding the component ``translate`` method, you should be careful not to unintentionally lose the children of the translatable component.
57+
See the Javadocs for the translate method for a code example of how to avoid this common error.
58+
59+
Below is an example of how one might implement a custom ``Translator``.
60+
61+
.. code:: java
62+
63+
public class MyTranslator implements Translator {
64+
65+
@Override
66+
public @NotNull Key name() {
67+
// Every translator has a name which is used to identify this specific translator instance.
68+
return Key.key("mynamespace:mykey");
69+
}
70+
71+
@Override
72+
public @Nullable MessageFormat translate(final @NotNull String key, final @NotNull Locale locale) {
73+
// You could retrieve a string from a properties file, a config file, or some other system.
74+
// An an example, we will hard-code a check for a specific key here.
75+
if (key.equals("mytranslation.key") && locale == Locale.US) {
76+
return new MessageFormat("Hello %s!", locale);
77+
} else {
78+
// If you only want to use component translation, you can override this method and always return `null`.
79+
return null;
80+
}
81+
}
82+
83+
@Override
84+
public @Nullable Component translate(@NotNull TranslatableComponent component, @NotNull Locale locale) {
85+
// As above, we will hardcode a check here, but you should be reading this from elsewhere.
86+
if (key.equals("mytranslation.colorful") && locale == Locale.US) {
87+
return Component.text("Hello, ", NamedTextColor.GREEN)
88+
.append(component.arguments().get(0).color(NamedTextColor.RED))
89+
.append(component.children()); // Always make sure to copy the children over!
90+
} else {
91+
return null;
92+
}
93+
}
94+
}
95+
96+
Using a ``TranslationRegistry``
97+
-------------------------------
98+
99+
A ``TranslationRegistry`` is a collection of ``Translator`` instances.
100+
It can provide a simpler way creating a ``Translator`` without having to implement the logic for determining translations yourself.
101+
You can create a translation registry and then add or remove translations at will.
102+
This allows you to retain the same functionality as a ``Translator`` without the overhead of writing your own logic for determining the translations.
103+
104+
There are also methods on ``TranslationRegistry`` to bulk register from `resource bundles <https://docs.oracle.com/javase/8/docs/api/java/util/ResourceBundle.html>`_.
105+
You may also want to use Adventure's ``UTF8ResourceBundleControl`` utility class to create your bundle.
106+
107+
.. code:: java
108+
109+
// As above, every translator needs an identifying key!
110+
final TranslationRegistry myRegistry = TranslationRegistry.create(Key.key("mynamespace:mykey"));
111+
112+
// You can add translations one-by-one, or in bulk. Consult the Javadocs for a full list of methods.
113+
myRegistry.register("mytranslation.key", Locale.US, new MessageFormat("Hello %s!", Locale.US));
114+
115+
// You can then register this to the global translator so the translations are available there!
116+
GlobalTranslator.translator().addSource(myRegistry);
117+
118+
Using ``MiniMessageTranslator``
119+
-------------------------------
120+
121+
Adventure also provides a translator that can use MiniMessage strings, with automatic support for placeholders and arguments.
122+
For more information, see :ref:`minimessage-translator`.

source/minimessage/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,4 @@ If you're looking to write messages with MiniMessage, take a look at the :ref:`m
1616
format
1717
api
1818
dynamic-replacements
19+
translator

source/minimessage/translator.rst

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
.. _minimessage-translator:
2+
3+
MiniMessage Translator
4+
======================
5+
6+
.. info::
7+
8+
For more information about both Minecraft and Adventure's localization systems, see :ref:`localization`.
9+
10+
MiniMessage provides a ``Translator`` implementation that allows you to use MiniMessage as translation strings.
11+
It also provides automatic support for argument placeholders, letting you use simple translatable components throughout your codebase.
12+
13+
Creating a MiniMessage translator
14+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
15+
16+
To start, create an implementation of the ``MiniMessageTranslator`` and register it to the ``GlobalTranslator``.
17+
This can be done using :java:`GlobalTranslator.translator().addSource(myMiniMessageTranslator)`.
18+
For an example of how to create your own ``MiniMessageTranslator``, see the below code block.
19+
20+
.. code:: java
21+
22+
public class MyMiniMessageTranslator extends MiniMessageTranslator() {
23+
24+
public MyMiniMessageTranslator() {
25+
// By default, the standard MiniMessage instance will be used.
26+
// You can specify a custom one in the super constructor.
27+
super(MiniMessage.miniMessage());
28+
}
29+
30+
@Override
31+
public @Nullable String getMiniMessageString(final @NotNull String key, final @NotNull Locale locale) {
32+
// Creating a custom MiniMessage translator is as simple as overriding this one method.
33+
// All you need to do is return a MiniMessage string for the provided key and locale.
34+
// In this example we will hardcode this, but you could pull it from a resource bundle, a properties file, a config file or something else entirely.
35+
if (key.equals("mykey") && locale == Locale.US) {
36+
return "<red>Hello, <name>! Today is <day_of_week>."
37+
} else {
38+
// Returning null "ignores" this translation.
39+
return null;
40+
}
41+
}
42+
}
43+
44+
Using a MiniMessage translator
45+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
46+
47+
The MiniMessage translator will automatically turn translatable component arguments into a custom tag.
48+
This tag will be :mm:`<arg:index>` or :mm:`<argument:index>` where ``index`` is the zero indexed position of the argument.
49+
For example, this component :java:`Component.translatable(key, Component.text("Kezz"))` with the MiniMessage string :mm:`Hello, <arg:0>!` will produce "Hello, Kezz!".
50+
51+
You can also use the `Argument` class to create named tags for ease of use.
52+
For example, this component :java:`Component.translatable(key, Argument.component("name", Component.text("Kezz"))` will produce the string "Hello, Kezz!" when used with either :mm:`Hello, <arg:0>!` or :mm:`Hello, <name>!`.
53+
54+
Finally, you can also add entirely custom tags or tag resolvers to the deserialization by using the rest of the methods on ``Argument``.
55+
For a full list, please see the Javadocs for the ``Argument`` class.

0 commit comments

Comments
 (0)