diff --git a/text-minimessage/src/main/java/net/kyori/adventure/text/minimessage/tag/standard/TranslatableFallbackTag.java b/text-minimessage/src/main/java/net/kyori/adventure/text/minimessage/tag/standard/TranslatableFallbackTag.java index d437dee3c9..a37b36636e 100644 --- a/text-minimessage/src/main/java/net/kyori/adventure/text/minimessage/tag/standard/TranslatableFallbackTag.java +++ b/text-minimessage/src/main/java/net/kyori/adventure/text/minimessage/tag/standard/TranslatableFallbackTag.java @@ -26,7 +26,9 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; +import net.kyori.adventure.pointer.Pointered; import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.ComponentLike; import net.kyori.adventure.text.TranslatableComponent; import net.kyori.adventure.text.TranslationArgument; import net.kyori.adventure.text.minimessage.Context; @@ -36,6 +38,7 @@ import net.kyori.adventure.text.minimessage.tag.Tag; import net.kyori.adventure.text.minimessage.tag.resolver.ArgumentQueue; import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver; +import net.kyori.adventure.text.minimessage.translation.Argument; import org.jetbrains.annotations.Nullable; /** @@ -61,14 +64,20 @@ private TranslatableFallbackTag() { static Tag create(final ArgumentQueue args, final Context ctx) throws ParsingException { final String key = args.popOr("A translation key is required").value(); final String fallback = args.popOr("A fallback messages is required").value(); - final List with; + final Pointered pointered = ctx.target(); + final List with; if (args.hasNext()) { with = new ArrayList<>(); while (args.hasNext()) { with.add(ctx.deserialize(args.pop().value())); } + if (pointered != null) { + with.add(Argument.target(pointered)); + } } else { - with = Collections.emptyList(); + with = pointered == null + ? Collections.emptyList() + : Collections.singletonList(Argument.target(pointered)); } return Tag.inserting(Component.translatable(key, fallback, with)); diff --git a/text-minimessage/src/main/java/net/kyori/adventure/text/minimessage/tag/standard/TranslatableTag.java b/text-minimessage/src/main/java/net/kyori/adventure/text/minimessage/tag/standard/TranslatableTag.java index 6ec72c3db8..44ed2a28bf 100644 --- a/text-minimessage/src/main/java/net/kyori/adventure/text/minimessage/tag/standard/TranslatableTag.java +++ b/text-minimessage/src/main/java/net/kyori/adventure/text/minimessage/tag/standard/TranslatableTag.java @@ -26,7 +26,9 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; +import net.kyori.adventure.pointer.Pointered; import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.ComponentLike; import net.kyori.adventure.text.TranslatableComponent; import net.kyori.adventure.text.TranslationArgument; import net.kyori.adventure.text.minimessage.Context; @@ -36,6 +38,7 @@ import net.kyori.adventure.text.minimessage.tag.Tag; import net.kyori.adventure.text.minimessage.tag.resolver.ArgumentQueue; import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver; +import net.kyori.adventure.text.minimessage.translation.Argument; import org.jetbrains.annotations.Nullable; /** @@ -59,14 +62,20 @@ private TranslatableTag() { static Tag create(final ArgumentQueue args, final Context ctx) throws ParsingException { final String key = args.popOr("A translation key is required").value(); - final List with; + final Pointered pointered = ctx.target(); + final List with; if (args.hasNext()) { with = new ArrayList<>(); while (args.hasNext()) { with.add(ctx.deserialize(args.pop().value())); } + if (pointered != null) { + with.add(Argument.target(pointered)); + } } else { - with = Collections.emptyList(); + with = pointered == null + ? Collections.emptyList() + : Collections.singletonList(Argument.target(pointered)); } return Tag.inserting(Component.translatable(key, with)); diff --git a/text-minimessage/src/test/java/net/kyori/adventure/text/minimessage/AbstractTest.java b/text-minimessage/src/test/java/net/kyori/adventure/text/minimessage/AbstractTest.java index 52848b4f79..2d500706bd 100644 --- a/text-minimessage/src/test/java/net/kyori/adventure/text/minimessage/AbstractTest.java +++ b/text-minimessage/src/test/java/net/kyori/adventure/text/minimessage/AbstractTest.java @@ -27,6 +27,7 @@ import java.util.Collections; import java.util.function.UnaryOperator; import java.util.stream.Collectors; +import net.kyori.adventure.pointer.Pointered; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.ComponentLike; import net.kyori.adventure.text.VirtualComponentRenderer; @@ -37,6 +38,7 @@ import net.kyori.ansi.ColorLevel; import net.kyori.examination.string.MultiLineStringExaminer; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.UnknownNullability; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -57,13 +59,23 @@ protected void assertParsedEquals(final @NotNull Component expected, final @NotN } protected void assertParsedEquals(final @NotNull Component expected, final @NotNull String input, final @NotNull TagResolver... args) { - this.assertParsedEquals(PARSER, expected, input, args); + this.assertParsedEquals(PARSER, expected, input, null, args); } - protected void assertParsedEquals(final MiniMessage miniMessage, final Component expected, final String input, final @NotNull TagResolver... args) { + protected void assertParsedEquals(final @NotNull Component expected, final @NotNull String input, final @Nullable Pointered pointered, final @NotNull TagResolver... args) { + this.assertParsedEquals(PARSER, expected, input, pointered, args); + } + + protected void assertParsedEquals(final MiniMessage miniMessage, final @NotNull Component expected, final @NotNull String input, final @NotNull TagResolver... args) { + this.assertParsedEquals(miniMessage, expected, input, null, args); + } + + protected void assertParsedEquals(final MiniMessage miniMessage, final Component expected, final String input, final Pointered pointered, final @NotNull TagResolver... args) { final Component expectedCompacted = expected.compact(); final String expectedSerialized = this.prettyPrint(expectedCompacted); - final Component actualCompacted = miniMessage.deserialize(input, TagResolver.resolver(args)).compact(); + final Component actualCompacted = (pointered == null + ? miniMessage.deserialize(input, TagResolver.resolver(args)) + : miniMessage.deserialize(input, pointered, TagResolver.resolver(args))).compact(); final String actual = this.prettyPrint(actualCompacted); assertEquals(expectedSerialized, actual, () -> "Expected parsed value did not match actual:\n" + " Expected: " + ANSI.serialize(expectedCompacted) + '\n' diff --git a/text-minimessage/src/test/java/net/kyori/adventure/text/minimessage/tag/standard/TranslatableTagTest.java b/text-minimessage/src/test/java/net/kyori/adventure/text/minimessage/tag/standard/TranslatableTagTest.java index f15fa76703..9108c76035 100644 --- a/text-minimessage/src/test/java/net/kyori/adventure/text/minimessage/tag/standard/TranslatableTagTest.java +++ b/text-minimessage/src/test/java/net/kyori/adventure/text/minimessage/tag/standard/TranslatableTagTest.java @@ -23,10 +23,23 @@ */ package net.kyori.adventure.text.minimessage.tag.standard; +import java.util.Locale; +import net.kyori.adventure.key.Key; +import net.kyori.adventure.pointer.Pointered; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.TextComponent; import net.kyori.adventure.text.format.NamedTextColor; import net.kyori.adventure.text.minimessage.AbstractTest; +import net.kyori.adventure.text.minimessage.Context; +import net.kyori.adventure.text.minimessage.MiniMessage; +import net.kyori.adventure.text.minimessage.ParsingException; +import net.kyori.adventure.text.minimessage.tag.Tag; +import net.kyori.adventure.text.minimessage.tag.resolver.ArgumentQueue; +import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver; +import net.kyori.adventure.text.minimessage.translation.MiniMessageTranslationStore; +import net.kyori.adventure.translation.GlobalTranslator; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.junit.jupiter.api.Test; import static net.kyori.adventure.text.Component.text; @@ -104,4 +117,62 @@ void testKingAlter() { this.assertParsedEquals(expected, input); } + + @Test + void translatableProvidedTarget() { + final CustomPointered pointered = new CustomPointered("Custom Pointered"); + + final TagResolver pointeredResolver = new TagResolver() { + @Override + public @Nullable Tag resolve( + final @NotNull String name, + final @NotNull ArgumentQueue arguments, + final @NotNull Context ctx + ) throws ParsingException { + if (!this.has(name)) { + return null; + } + final Pointered target = ctx.target(); + if (target == null) { + return null; + } + if (target instanceof CustomPointered) { + final CustomPointered custom = (CustomPointered) target; + return Tag.preProcessParsed(custom.name); + } + return null; + } + + @Override + public boolean has(final @NotNull String name) { + return name.equalsIgnoreCase("pointered_name"); + } + }; + + final MiniMessageTranslationStore translationStore = MiniMessageTranslationStore.create( + Key.key("adventure:minimessage"), + MiniMessage.builder().debug(System.out::print).editTags(tags -> tags.resolver(pointeredResolver)).build() + ); + translationStore.defaultLocale(Locale.getDefault()); + translationStore.register("minimessage.test", Locale.getDefault(), ""); + + final MiniMessage miniMessage = MiniMessage.builder() + .postProcessor(component -> GlobalTranslator.render(component, Locale.getDefault())) + .debug(System.out::print) + .build(); + try { + GlobalTranslator.translator().addSource(translationStore); + this.assertParsedEquals(miniMessage, Component.text(pointered.name, NamedTextColor.RED), "", pointered); + } finally { + GlobalTranslator.translator().removeSource(translationStore); + } + } + + private static final class CustomPointered implements Pointered { + private final String name; + + private CustomPointered(final String name) { + this.name = name; + } + } }