TurboMessages
Messaging service with named placeholders and translations
So what's this do?
I made this after wanting to be able to create translatable components that also had named placeholders.
The base adventure library does have both translations and placeholders, but their named placeholders are treated as adventure tags, requiring you to make a custom Tag that the Component parser will translate into the value you want.
It also requires you to use the <key> format, but I prefer the %key% format.
To make it even more worthwhile, my Message objects can replace placeholders with Components, other Messages, or converts objects to strings with Objects.toString().
You can convert Message objects to a single Component, or you can split them on each newline to get a List<Component>. (This is helpful for item lore!)
I also made it append an empty component with italic:false to each line, letting you create item names and lore without worrying about putting <i:false> at the front of each line.
Message also implements ComponentLike, allowing you to send raw Message objects to players without needing to convert them to Components yourself.
Translations are stored in YAML files in lang/base. Currently, the program only reads the ".yml" extension, so ".yaml" won't work.
Each translation should be key->value, but you can use more complex paths if you want.
The translation stores support MiniMessage formatting, and you can use placeholders by surrounding them with "%" symbols.
Installation
First things first, let's get the maven repo in your project.
repositories {
maven("https://maven.turbojax.org/releases")
}Then, we can add the dependency.
dependencies {
implementation("org.turbojax:messages:1.3.1")
}Usage
Folder setup
In your resources folder, make lang/base.
This is the collection of language files that should be overridden whenever there is an update.
If end users want to override a translation, they create a file with the same name as the locale they override, then edit it. (ex: "en_US.yml")
Then, they can just override the yaml key that the translation uses and it'll use the overridden message instead!
Example override:
- lang/base/en_US.yml
my_message: "Hello there!" message_2: "Hi" - lang/en_US.yml
my_message: "Hello world!"
As shown above, we have a file in lang and the base in lang/base. They both define the my_message translatable component, so when it is used in the code, it'll print "Hello world!" instead of the default value.
message_2 is not overriden, so printing it results in no change.
Initialization
To use the library, you first need to set the location of the lang directory. This tells the program where the translations are.
You do this with MessageManager#setLangDir. It takes a File object.
Next, you'll use the MessageManager to recursively load files from lang/base.
This is done by running MessageManager.loadBaseFiles().
EX:
public void onEnable() {
MessageManager.setLangDir(new File("plugins/Infuse/lang"));
MessageManager.loadBaseFiles();
}Text Messages
Now you're ready to create your own messages!
To make a generic text message, use Message.text(String message).
The message param can be serialized with MiniMessage.
You can also pass in a Set<String> of placeholders. You won't be able to send the Message until all of the placeholders have been applied.
If you do try to send the Message, it will throw an IllegalStateException.
EX:
Audience audience; // get it from somewhere
Message msg = Message.text("<green>Hello world!");
audience.sendMessage(msg);
msg = Message.text("I'm at <red>%x%, %y%, %z%<white>.", Set.of("x", "y", "z"));
msg.applyPlaceholder("x", 100);
audience.sendMessage(msg); // Fails. "y" and "z" have not been applied.
msg.applyPlaceholder("y", 0);
msg.applyPlaceholder("z", 0);
audience.sendMessage(msg); // Works now!Translatable Messages
Translatable messages can be created on the fly or by using existing MessageType objects.
The locale is not part of the MessageType class. It is passed directly into Message#translatable.
The default locale is Locale.US, with the language code "en_US".
If a message is not found in the requested locale, it checks for the message in the default locale. If the message doesn't exist in the default locale, it returns null and logs the error to console.
EX:
Player player; // Paper's Player
Locale spanish = new Locale("es");
// Regular translatable msg
Message msg = Message.translatable("emerald_name");
player.sendMessage(msg);
msg = Message.translatable("emerald_name", spanish);
player.sendMessage(msg);
// MessageType demo
final MessageType PLAYER_LOCATION = new MessageType("player_location", Set.of("x", "y", "z"));
msg = Message.translatable(PLAYER_LOCATION);
msg.applyPlaceholder("x", player.getLocation().getBlockX());
msg.applyPlaceholder("y", player.getLocation().getBlockX());
msg.applyPlaceholder("z", player.getLocation().getBlockX());
player.sendMessage(msg);
msg = Message.translatable(PLAYER_LOCATION, spanish);
msg.applyPlaceholder("x", player.getLocation().getBlockX());
msg.applyPlaceholder("y", player.getLocation().getBlockX());
msg.applyPlaceholder("z", player.getLocation().getBlockX());
player.sendMessage(msg);Links
Source: https://github.com/turbojax/turbomessages
Javadocs: https://maven.turbojax.org/javadoc/releases/org/turbojax/messages/1.3.1