Skip to content

Commit

Permalink
Merge pull request #1004 from KyoriPowered/feat/translatable-args
Browse files Browse the repository at this point in the history
feat(api): Support representing translation args losslessly
  • Loading branch information
zml2008 authored Dec 17, 2023
2 parents 11ecb1e + f5e1f38 commit 1915e23
Show file tree
Hide file tree
Showing 24 changed files with 689 additions and 105 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,10 @@ public interface ComponentIteratorType {
ComponentIteratorType DEPTH_FIRST = (component, deque, flags) -> {
if (flags.contains(ComponentIteratorFlag.INCLUDE_TRANSLATABLE_COMPONENT_ARGUMENTS) && component instanceof TranslatableComponent) {
final TranslatableComponent translatable = (TranslatableComponent) component;
final List<Component> args = translatable.args();
final List<? extends ComponentLike> args = translatable.arguments();

for (int i = args.size() - 1; i >= 0; i--) {
deque.addFirst(args.get(i));
deque.addFirst(args.get(i).asComponent());
}
}

Expand All @@ -79,7 +79,9 @@ public interface ComponentIteratorType {
*/
ComponentIteratorType BREADTH_FIRST = (component, deque, flags) -> {
if (flags.contains(ComponentIteratorFlag.INCLUDE_TRANSLATABLE_COMPONENT_ARGUMENTS) && component instanceof TranslatableComponent) {
deque.addAll(((TranslatableComponent) component).args());
for (final TranslationArgument argument : ((TranslatableComponent) component).arguments()) {
deque.add(argument.asComponent());
}
}

final HoverEvent<?> hoverEvent = component.hoverEvent();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -131,12 +131,12 @@ private TextReplacementRenderer() {
// otherwise, we haven't modified the component, so nothing to change
}
} else if (modified instanceof TranslatableComponent) { // get TranslatableComponent with() args
final List<Component> args = ((TranslatableComponent) modified).args();
List<Component> newArgs = null;
final List<TranslationArgument> args = ((TranslatableComponent) modified).arguments();
List<TranslationArgument> newArgs = null;
for (int i = 0, size = args.size(); i < size; i++) {
final Component original = args.get(i);
final Component replaced = this.render(original, state);
if (replaced != component) {
final TranslationArgument original = args.get(i);
final TranslationArgument replaced = original.value() instanceof Component ? TranslationArgument.component(this.render((Component) original.value(), state)) : original;
if (replaced != original) {
if (newArgs == null) {
newArgs = new ArrayList<>(size);
if (i > 0) {
Expand All @@ -149,7 +149,7 @@ private TextReplacementRenderer() {
}
}
if (newArgs != null) {
modified = ((TranslatableComponent) modified).args(newArgs);
modified = ((TranslatableComponent) modified).arguments(newArgs);
}
}
// Only visit children if we're running
Expand Down
112 changes: 104 additions & 8 deletions api/src/main/java/net/kyori/adventure/text/TranslatableComponent.java
Original file line number Diff line number Diff line change
Expand Up @@ -97,28 +97,76 @@ public interface TranslatableComponent extends BuildableComponent<TranslatableCo
*
* @return the unmodifiable list of translation arguments
* @since 4.0.0
* @deprecated for removal since 4.15.0, use {@link #arguments()} instead.
*/
@Deprecated
@NotNull List<Component> args();

/**
* Sets the translation arguments for this component.
*
* <p>Non-{@link Component} arguments can be wrapped in {@link TranslationArgument}, or represented with a {@link TranslationArgumentLike}.</p>
*
* @param args the translation arguments
* @return a translatable component
* @see TranslationArgument
* @since 4.0.0
* @deprecated for removal since 4.15.0, use {@link #arguments(ComponentLike...)} instead
*/
@Deprecated
@Contract(pure = true)
@NotNull TranslatableComponent args(final @NotNull ComponentLike@NotNull... args);
default @NotNull TranslatableComponent args(final @NotNull ComponentLike@NotNull... args) {
return this.arguments(args);
}

/**
* Sets the translation arguments for this component.
*
* <p>Non-{@link Component} arguments can be wrapped in {@link TranslationArgument}, or represented with a {@link TranslationArgumentLike}.</p>
*
* @param args the translation arguments
* @return a translatable component
* @since 4.0.0
* @deprecated for removal since 4.15.0, use {@link #arguments(List)} instead
*/
@Deprecated
@Contract(pure = true)
default @NotNull TranslatableComponent args(final @NotNull List<? extends ComponentLike> args) {
return this.arguments(args);
}

/**
* Gets the unmodifiable list of translation arguments.
*
* @return the unmodifiable list of translation arguments
* @since 4.0.0
*/
@NotNull List<TranslationArgument> arguments();

/**
* Sets the translation arguments for this component.
*
* <p>Non-{@link Component} arguments can be wrapped in {@link TranslationArgument}, or represented with a {@link TranslationArgumentLike}.</p>
*
* @param args the translation arguments
* @return a translatable component
* @see TranslationArgument
* @since 4.15.0
*/
@Contract(pure = true)
@NotNull TranslatableComponent arguments(final @NotNull ComponentLike@NotNull... args);

/**
* Sets the translation arguments for this component.
*
* <p>Non-{@link Component} arguments can be wrapped in {@link TranslationArgument}, or represented with a {@link TranslationArgumentLike}.</p>
*
* @param args the translation arguments
* @return a translatable component
* @since 4.15.0
*/
@Contract(pure = true)
@NotNull TranslatableComponent args(final @NotNull List<? extends ComponentLike> args);
@NotNull TranslatableComponent arguments(final @NotNull List<? extends ComponentLike> args);

/**
* Gets the translation fallback text for this component.
Expand Down Expand Up @@ -149,7 +197,7 @@ public interface TranslatableComponent extends BuildableComponent<TranslatableCo
return Stream.concat(
Stream.of(
ExaminableProperty.of("key", this.key()),
ExaminableProperty.of("args", this.args()),
ExaminableProperty.of("arguments", this.arguments()),
ExaminableProperty.of("fallback", this.fallback())
),
BuildableComponent.super.examinableProperties()
Expand Down Expand Up @@ -190,50 +238,98 @@ interface Builder extends ComponentBuilder<TranslatableComponent, Builder> {
* @param arg the translation arg
* @return this builder
* @since 4.0.0
* @deprecated for removal since 4.15.0, use {@link #arguments(ComponentLike...)} instead
*/
@Deprecated
@Contract("_ -> this")
@NotNull Builder args(final @NotNull ComponentBuilder<?, ?> arg);
default @NotNull Builder args(final @NotNull ComponentBuilder<?, ?> arg) {
return this.arguments(arg);
}

/**
* Sets the translation args.
*
* @param args the translation args
* @return this builder
* @since 4.0.0
* @deprecated for removal since 4.15.0, use {@link #arguments(ComponentLike...)} instead
*/
@Deprecated
@Contract("_ -> this")
@SuppressWarnings("checkstyle:GenericWhitespace")
@NotNull Builder args(final @NotNull ComponentBuilder<?, ?>@NotNull... args);
default @NotNull Builder args(final @NotNull ComponentBuilder<?, ?>@NotNull... args) {
return this.arguments(args);
}

/**
* Sets the translation args.
*
* @param arg the translation arg
* @return this builder
* @since 4.0.0
* @deprecated for removal since 4.15.0, use {@link #arguments(ComponentLike...)} instead
*/
@Deprecated
@Contract("_ -> this")
@NotNull Builder args(final @NotNull Component arg);
default @NotNull Builder args(final @NotNull Component arg) {
return this.arguments(arg);
}

/**
* Sets the translation args.
*
* <p>Non-{@link Component} arguments can be wrapped in {@link TranslationArgument}, or represented with a {@link TranslationArgumentLike}.</p>
*
* @param args the translation args
* @return this builder
* @since 4.0.0
* @deprecated for removal since 4.15.0, use {@link #arguments(ComponentLike...)} instead
*/
@Deprecated
@Contract("_ -> this")
@NotNull Builder args(final @NotNull ComponentLike@NotNull... args);
default @NotNull Builder args(final @NotNull ComponentLike@NotNull... args) {
return this.arguments(args);
}

/**
* Sets the translation args.
*
* <p>Non-{@link Component} arguments can be wrapped in {@link TranslationArgument}, or represented with a {@link TranslationArgumentLike}.</p>
*
* @param args the translation args
* @return this builder
* @since 4.0.0
* @deprecated for removal since 4.15.0, use {@link #arguments(List)} instead
*/
@Deprecated
@Contract("_ -> this")
default @NotNull Builder args(final @NotNull List<? extends ComponentLike> args) {
return this.arguments(args);
}

/**
* Sets the translation args.
*
* <p>Non-{@link Component} arguments can be wrapped in {@link TranslationArgument}, or represented with a {@link TranslationArgumentLike}.</p>
*
* @param args the translation args
* @return this builder
* @since 4.15.0
*/
@Contract("_ -> this")
@NotNull Builder arguments(final @NotNull ComponentLike@NotNull... args);

/**
* Sets the translation args.
*
* <p>Non-{@link Component} arguments can be wrapped in {@link TranslationArgument}, or represented with a {@link TranslationArgumentLike}.</p>
*
* @param args the translation args
* @return this builder
* @since 4.15.0
*/
@Contract("_ -> this")
@NotNull Builder args(final @NotNull List<? extends ComponentLike> args);
@NotNull Builder arguments(final @NotNull List<? extends ComponentLike> args);

/**
* Sets the translation fallback text.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,11 @@
*/
package net.kyori.adventure.text;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import net.kyori.adventure.internal.Internals;
import net.kyori.adventure.text.format.Style;
import org.jetbrains.annotations.NotNull;
Expand All @@ -48,15 +47,15 @@ static TranslatableComponent create(final @NotNull List<? extends ComponentLike>
requireNonNull(style, "style"),
requireNonNull(key, "key"),
fallback,
ComponentLike.asComponents(args) // Since translation arguments can be indexed, empty components are also included.
asArguments(args) // Since translation arguments can be indexed, empty components are also included.
);
}

private final String key;
private final @Nullable String fallback;
private final List<Component> args;
private final List<TranslationArgument> args;

TranslatableComponentImpl(final @NotNull List<Component> children, final @NotNull Style style, final @NotNull String key, final @Nullable String fallback, final @NotNull List<Component> args) {
TranslatableComponentImpl(final @NotNull List<Component> children, final @NotNull Style style, final @NotNull String key, final @Nullable String fallback, final @NotNull List<TranslationArgument> args) {
super(children, style);
this.key = key;
this.fallback = fallback;
Expand All @@ -75,17 +74,23 @@ static TranslatableComponent create(final @NotNull List<? extends ComponentLike>
}

@Override
@Deprecated
public @NotNull List<Component> args() {
return ComponentLike.asComponents(this.args); // eww
}

@Override
public @NotNull List<TranslationArgument> arguments() {
return this.args;
}

@Override
public @NotNull TranslatableComponent args(final @NotNull ComponentLike@NotNull... args) {
public @NotNull TranslatableComponent arguments(final @NotNull ComponentLike@NotNull... args) {
return create(this.children, this.style, this.key, this.fallback, args);
}

@Override
public @NotNull TranslatableComponent args(final @NotNull List<? extends ComponentLike> args) {
public @NotNull TranslatableComponent arguments(final @NotNull List<? extends ComponentLike> args) {
return create(this.children, this.style, this.key, this.fallback, args);
}

Expand Down Expand Up @@ -115,7 +120,7 @@ public boolean equals(final @Nullable Object other) {
if (!(other instanceof TranslatableComponent)) return false;
if (!super.equals(other)) return false;
final TranslatableComponent that = (TranslatableComponent) other;
return Objects.equals(this.key, that.key()) && Objects.equals(this.fallback, that.fallback()) && Objects.equals(this.args, that.args());
return Objects.equals(this.key, that.key()) && Objects.equals(this.fallback, that.fallback()) && Objects.equals(this.args, that.arguments());
}

@Override
Expand All @@ -140,15 +145,15 @@ public String toString() {
static final class BuilderImpl extends AbstractComponentBuilder<TranslatableComponent, Builder> implements TranslatableComponent.Builder {
private @Nullable String key;
private @Nullable String fallback;
private List<? extends Component> args = Collections.emptyList();
private List<TranslationArgument> args = Collections.emptyList();

BuilderImpl() {
}

BuilderImpl(final @NotNull TranslatableComponent component) {
super(component);
this.key = component.key();
this.args = component.args();
this.args = component.arguments();
this.fallback = component.fallback();
}

Expand All @@ -159,33 +164,15 @@ static final class BuilderImpl extends AbstractComponentBuilder<TranslatableComp
}

@Override
public @NotNull Builder args(final @NotNull ComponentBuilder<?, ?> arg) {
return this.args(Collections.singletonList(requireNonNull(arg, "arg").build()));
}

@Override
@SuppressWarnings("checkstyle:GenericWhitespace")
public @NotNull Builder args(final @NotNull ComponentBuilder<?, ?>@NotNull... args) {
public @NotNull Builder arguments(final @NotNull ComponentLike@NotNull... args) {
requireNonNull(args, "args");
if (args.length == 0) return this.args(Collections.emptyList());
return this.args(Stream.of(args).map(ComponentBuilder::build).collect(Collectors.toList()));
if (args.length == 0) return this.arguments(Collections.emptyList());
return this.arguments(Arrays.asList(args));
}

@Override
public @NotNull Builder args(final @NotNull Component arg) {
return this.args(Collections.singletonList(requireNonNull(arg, "arg")));
}

@Override
public @NotNull Builder args(final @NotNull ComponentLike@NotNull... args) {
requireNonNull(args, "args");
if (args.length == 0) return this.args(Collections.emptyList());
return this.args(Arrays.asList(args));
}

@Override
public @NotNull Builder args(final @NotNull List<? extends ComponentLike> args) {
this.args = ComponentLike.asComponents(requireNonNull(args, "args"));
public @NotNull Builder arguments(final @NotNull List<? extends ComponentLike> args) {
this.args = asArguments(requireNonNull(args, "args"));
return this;
}

Expand All @@ -201,4 +188,27 @@ static final class BuilderImpl extends AbstractComponentBuilder<TranslatableComp
return create(this.children, this.buildStyle(), this.key, this.fallback, this.args);
}
}

static List<TranslationArgument> asArguments(final @NotNull List<? extends ComponentLike> likes) {
if (likes.isEmpty()) {
return Collections.emptyList();
}

final List<TranslationArgument> ret = new ArrayList<>(likes.size());
for (int i = 0; i < likes.size(); i++) {
final ComponentLike like = likes.get(i);
if (like == null) {
throw new NullPointerException("likes[" + i + "]");
}
if (like instanceof TranslationArgument) {
ret.add((TranslationArgument) like);
} else if (like instanceof TranslationArgumentLike) {
ret.add(requireNonNull(((TranslationArgumentLike) like).asTranslationArgument(), "likes[" + i + "].asTranslationArgument()"));
} else {
ret.add(TranslationArgument.component(like));
}
}

return Collections.unmodifiableList(ret);
}
}
Loading

0 comments on commit 1915e23

Please sign in to comment.