mirror of
https://github.com/Multiverse/Multiverse-Core.git
synced 2024-11-22 10:36:06 +01:00
Merge pull request #3010 from Multiverse/ben/mv5/nested-locale-message
Add support for nested Message within MessageReplacement and fix some checkstyles
This commit is contained in:
commit
5a474d7efa
@ -35,7 +35,8 @@ public class MVCommandIssuer extends OpenBukkitCommandIssuer {
|
|||||||
|
|
||||||
private void sendMessage(MessageType messageType, Message message) {
|
private void sendMessage(MessageType messageType, Message message) {
|
||||||
if (message instanceof MessageKeyProvider) {
|
if (message instanceof MessageKeyProvider) {
|
||||||
sendMessage(messageType, (MessageKeyProvider) message, message.getReplacements());
|
sendMessage(messageType, (MessageKeyProvider) message,
|
||||||
|
message.getReplacements(getManager().getLocales(), this));
|
||||||
} else {
|
} else {
|
||||||
var formatter = getManager().getFormat(messageType);
|
var formatter = getManager().getFormat(messageType);
|
||||||
if (formatter != null) {
|
if (formatter != null) {
|
||||||
|
@ -58,9 +58,12 @@ public class MVCommandManager extends PaperCommandManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public BukkitLocales getLocales() {
|
public PluginLocales getLocales() {
|
||||||
return this.locales;
|
return (PluginLocales) this.locales;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -14,6 +14,31 @@ public class MultiverseException extends Exception {
|
|||||||
|
|
||||||
private final @Nullable Message message;
|
private final @Nullable Message message;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new exception with the given message.
|
||||||
|
* <br/>
|
||||||
|
* If the message is not null, this exception will also contain a {@link Message} which can be accessed via
|
||||||
|
* {@link #getMVMessage()}. This message will just be the given message wrapped in a {@link Message}.
|
||||||
|
*
|
||||||
|
* @param message The message for the exception
|
||||||
|
*/
|
||||||
|
public MultiverseException(@Nullable String message) {
|
||||||
|
this(message != null ? Message.of(message) : null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new exception with the given message.
|
||||||
|
* <br/>
|
||||||
|
* If the message is not null, this exception will also contain a String message which can be accessed via
|
||||||
|
* {@link #getMessage()}. This message will just be the given message formatted without locale support.
|
||||||
|
*
|
||||||
|
* @param message The message for the exception
|
||||||
|
*/
|
||||||
|
public MultiverseException(@Nullable Message message) {
|
||||||
|
super(message != null ? message.formatted() : null);
|
||||||
|
this.message = message;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new exception with the given message and cause.
|
* Creates a new exception with the given message and cause.
|
||||||
* <br/>
|
* <br/>
|
||||||
|
@ -17,8 +17,7 @@ final class LocalizedMessage extends Message implements MessageKeyProvider {
|
|||||||
LocalizedMessage(
|
LocalizedMessage(
|
||||||
@NotNull MessageKeyProvider messageKeyProvider,
|
@NotNull MessageKeyProvider messageKeyProvider,
|
||||||
@NotNull String message,
|
@NotNull String message,
|
||||||
@NotNull MessageReplacement... replacements
|
@NotNull MessageReplacement... replacements) {
|
||||||
) {
|
|
||||||
super(message, replacements);
|
super(message, replacements);
|
||||||
this.messageKeyProvider = messageKeyProvider;
|
this.messageKeyProvider = messageKeyProvider;
|
||||||
}
|
}
|
||||||
@ -28,13 +27,34 @@ final class LocalizedMessage extends Message implements MessageKeyProvider {
|
|||||||
return messageKeyProvider.getMessageKey();
|
return messageKeyProvider.getMessageKey();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull String[] getReplacements(@NotNull PluginLocales locales, @Nullable CommandIssuer commandIssuer) {
|
||||||
|
return toReplacementsArray(locales, commandIssuer, replacements);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public @NotNull String formatted(@NotNull PluginLocales locales, @Nullable CommandIssuer commandIssuer) {
|
public @NotNull String formatted(@NotNull PluginLocales locales, @Nullable CommandIssuer commandIssuer) {
|
||||||
Objects.requireNonNull(locales, "locales must not be null");
|
Objects.requireNonNull(locales, "locales must not be null");
|
||||||
|
|
||||||
if (getReplacements().length == 0) {
|
String[] parsedReplacements = getReplacements(locales, commandIssuer);
|
||||||
return raw();
|
if (parsedReplacements.length == 0) {
|
||||||
|
return locales.getMessage(commandIssuer, getMessageKey());
|
||||||
}
|
}
|
||||||
return ACFUtil.replaceStrings(locales.getMessage(commandIssuer, getMessageKey()), getReplacements());
|
return ACFUtil.replaceStrings(locales.getMessage(commandIssuer, getMessageKey()), parsedReplacements);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String[] toReplacementsArray(
|
||||||
|
@NotNull PluginLocales locales,
|
||||||
|
@Nullable CommandIssuer commandIssuer,
|
||||||
|
@NotNull MessageReplacement... replacements) {
|
||||||
|
String[] replacementsArray = new String[replacements.length * 2];
|
||||||
|
int i = 0;
|
||||||
|
for (MessageReplacement replacement : replacements) {
|
||||||
|
replacementsArray[i++] = replacement.getKey();
|
||||||
|
replacementsArray[i++] = replacement.getReplacement().fold(
|
||||||
|
str -> str,
|
||||||
|
message -> message.formatted(locales, commandIssuer));
|
||||||
|
}
|
||||||
|
return replacementsArray;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -48,8 +48,7 @@ public sealed class Message permits LocalizedMessage {
|
|||||||
public static Message of(
|
public static Message of(
|
||||||
@NotNull MessageKeyProvider messageKeyProvider,
|
@NotNull MessageKeyProvider messageKeyProvider,
|
||||||
@NotNull String nonLocalizedMessage,
|
@NotNull String nonLocalizedMessage,
|
||||||
@NotNull MessageReplacement... replacements
|
@NotNull MessageReplacement... replacements) {
|
||||||
) {
|
|
||||||
Objects.requireNonNull(messageKeyProvider, "messageKeyProvider must not be null");
|
Objects.requireNonNull(messageKeyProvider, "messageKeyProvider must not be null");
|
||||||
Objects.requireNonNull(nonLocalizedMessage, "message must not be null");
|
Objects.requireNonNull(nonLocalizedMessage, "message must not be null");
|
||||||
for (MessageReplacement replacement : replacements) {
|
for (MessageReplacement replacement : replacements) {
|
||||||
@ -60,11 +59,11 @@ public sealed class Message permits LocalizedMessage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private final @NotNull String message;
|
private final @NotNull String message;
|
||||||
private final @NotNull String[] replacements;
|
protected final @NotNull MessageReplacement[] replacements;
|
||||||
|
|
||||||
protected Message(@NotNull String message, @NotNull MessageReplacement... replacements) {
|
protected Message(@NotNull String message, @NotNull MessageReplacement... replacements) {
|
||||||
this.message = message;
|
this.message = message;
|
||||||
this.replacements = toReplacementsArray(replacements);
|
this.replacements = replacements;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -76,7 +75,21 @@ public sealed class Message permits LocalizedMessage {
|
|||||||
* @return The replacements
|
* @return The replacements
|
||||||
*/
|
*/
|
||||||
public @NotNull String[] getReplacements() {
|
public @NotNull String[] getReplacements() {
|
||||||
return replacements;
|
return toReplacementsArray(replacements);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the replacements for this message with localization support.
|
||||||
|
* <br/>
|
||||||
|
* This array is guaranteed to be of even length and suitable for use with
|
||||||
|
* {@link ACFUtil#replaceStrings(String, String...)}.
|
||||||
|
*
|
||||||
|
* @param locales The MultiverseCore locales provider
|
||||||
|
* @param commandIssuer The command issuer the message is for, or null for the console (default locale)
|
||||||
|
* @return The replacements
|
||||||
|
*/
|
||||||
|
public @NotNull String[] getReplacements(@NotNull PluginLocales locales, @Nullable CommandIssuer commandIssuer) {
|
||||||
|
return getReplacements();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -96,10 +109,11 @@ public sealed class Message permits LocalizedMessage {
|
|||||||
* @return The formatted message
|
* @return The formatted message
|
||||||
*/
|
*/
|
||||||
public @NotNull String formatted() {
|
public @NotNull String formatted() {
|
||||||
if (replacements.length == 0) {
|
String[] parsedReplacements = getReplacements();
|
||||||
|
if (parsedReplacements.length == 0) {
|
||||||
return raw();
|
return raw();
|
||||||
}
|
}
|
||||||
return ACFUtil.replaceStrings(message, replacements);
|
return ACFUtil.replaceStrings(message, parsedReplacements);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -133,7 +147,7 @@ public sealed class Message permits LocalizedMessage {
|
|||||||
int i = 0;
|
int i = 0;
|
||||||
for (MessageReplacement replacement : replacements) {
|
for (MessageReplacement replacement : replacements) {
|
||||||
replacementsArray[i++] = replacement.getKey();
|
replacementsArray[i++] = replacement.getKey();
|
||||||
replacementsArray[i++] = replacement.getReplacement();
|
replacementsArray[i++] = replacement.getReplacement().fold(s -> s, Message::formatted);
|
||||||
}
|
}
|
||||||
return replacementsArray;
|
return replacementsArray;
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package com.onarandombox.MultiverseCore.utils.message;
|
package com.onarandombox.MultiverseCore.utils.message;
|
||||||
|
|
||||||
|
import io.vavr.control.Either;
|
||||||
import org.jetbrains.annotations.Contract;
|
import org.jetbrains.annotations.Contract;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
@ -7,7 +8,7 @@ import org.jetbrains.annotations.Nullable;
|
|||||||
/**
|
/**
|
||||||
* Captures string replacements for {@link Message}s.
|
* Captures string replacements for {@link Message}s.
|
||||||
*/
|
*/
|
||||||
public final class MessageReplacement {
|
public final class MessageReplacement {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a replacement key for the given key string.
|
* Creates a replacement key for the given key string.
|
||||||
@ -20,6 +21,9 @@ import org.jetbrains.annotations.Nullable;
|
|||||||
return new MessageReplacement.Key(key);
|
return new MessageReplacement.Key(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A replacement key that maps to a value it can be replaced with.
|
||||||
|
*/
|
||||||
public static final class Key {
|
public static final class Key {
|
||||||
|
|
||||||
private final @NotNull String key;
|
private final @NotNull String key;
|
||||||
@ -28,6 +32,17 @@ import org.jetbrains.annotations.Nullable;
|
|||||||
this.key = key;
|
this.key = key;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a replacement for this key.
|
||||||
|
*
|
||||||
|
* @param replacement The replacement message
|
||||||
|
* @return A new message replacement
|
||||||
|
*/
|
||||||
|
@Contract(value = "_ -> new", pure = true)
|
||||||
|
public MessageReplacement with(@NotNull Message replacement) {
|
||||||
|
return new MessageReplacement(key, replacement);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a replacement for this key.
|
* Creates a replacement for this key.
|
||||||
*
|
*
|
||||||
@ -41,11 +56,16 @@ import org.jetbrains.annotations.Nullable;
|
|||||||
}
|
}
|
||||||
|
|
||||||
private final @NotNull String key;
|
private final @NotNull String key;
|
||||||
private final @NotNull String replacement;
|
private final @NotNull Either<String, Message> replacement;
|
||||||
|
|
||||||
|
private MessageReplacement(@NotNull String key, @NotNull Message replacement) {
|
||||||
|
this.key = key;
|
||||||
|
this.replacement = Either.right(replacement);
|
||||||
|
}
|
||||||
|
|
||||||
private MessageReplacement(@NotNull String key, @Nullable Object replacement) {
|
private MessageReplacement(@NotNull String key, @Nullable Object replacement) {
|
||||||
this.key = key;
|
this.key = key;
|
||||||
this.replacement = String.valueOf(replacement);
|
this.replacement = Either.left(String.valueOf(replacement));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -62,7 +82,7 @@ import org.jetbrains.annotations.Nullable;
|
|||||||
*
|
*
|
||||||
* @return The replacement
|
* @return The replacement
|
||||||
*/
|
*/
|
||||||
public @NotNull String getReplacement() {
|
public @NotNull Either<String, Message> getReplacement() {
|
||||||
return replacement;
|
return replacement;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1 @@
|
|||||||
|
package com.onarandombox.MultiverseCore.utils.message;
|
@ -253,4 +253,64 @@ class LocalizationTest : TestWithMockBukkit() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nested
|
||||||
|
inner class WithMessagesAsReplacement {
|
||||||
|
private val replacementKey = "{world}"
|
||||||
|
private val replacementValue = Message.of(MVCorei18n.GENERIC_SUCCESS, "success")
|
||||||
|
private val messageString = "Hello $replacementKey!"
|
||||||
|
private val replacedMessageString = "Hello success!"
|
||||||
|
private val replacedMessageStringLocale = "Cloned world 'Success!'!"
|
||||||
|
|
||||||
|
private val message = MVCorei18n.CLONE_SUCCESS
|
||||||
|
.bundle(messageString, replace(replacementKey).with(replacementValue))
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `The raw message should be the same as the original`() {
|
||||||
|
assertEquals(messageString, message.raw())
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `The formatted message should be the replaced original string`() {
|
||||||
|
assertEquals(replacedMessageString, message.formatted())
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `The formatted message with PluginLocales should be different from the replaced original string`() {
|
||||||
|
assertEquals(replacedMessageStringLocale, message.formatted(locales))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `The formatted message with PluginLocales should have performed replacement`() {
|
||||||
|
assertThat(message.formatted(locales), !containsSubstring(replacementKey))
|
||||||
|
assertThat(message.formatted(locales), containsSubstring("Success!"))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nested
|
||||||
|
@DisplayName("And a command sender is provided")
|
||||||
|
inner class WithCommandSender {
|
||||||
|
|
||||||
|
private lateinit var sender: CommandSender
|
||||||
|
private lateinit var issuer: MVCommandIssuer
|
||||||
|
|
||||||
|
@BeforeTest
|
||||||
|
fun setUp() {
|
||||||
|
sender = spy(Bukkit.getConsoleSender())
|
||||||
|
issuer = commandManager.getCommandIssuer(sender)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `Sending the issuer the message should send the formatted message to the sender`() {
|
||||||
|
issuer.sendInfo(message);
|
||||||
|
|
||||||
|
val sentMessage = argumentCaptor<String> {
|
||||||
|
verify(sender).sendMessage(capture())
|
||||||
|
}.firstValue
|
||||||
|
|
||||||
|
assertNotEquals(replacedMessageString, sentMessage)
|
||||||
|
assertThat(sentMessage, !containsSubstring(replacementKey))
|
||||||
|
assertThat(sentMessage, containsSubstring(replacedMessageStringLocale))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user