diff --git a/api/src/main/java/net/kyori/adventure/translation/GlobalTranslator.java b/api/src/main/java/net/kyori/adventure/translation/GlobalTranslator.java index 537c754278..df5b18464f 100644 --- a/api/src/main/java/net/kyori/adventure/translation/GlobalTranslator.java +++ b/api/src/main/java/net/kyori/adventure/translation/GlobalTranslator.java @@ -25,12 +25,17 @@ import java.util.Locale; import net.kyori.adventure.audience.Audience; +import net.kyori.adventure.audience.ForwardingAudience; +import net.kyori.adventure.identity.Identity; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.TranslatableComponent; import net.kyori.adventure.text.renderer.TranslatableComponentRenderer; import net.kyori.examination.Examinable; import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import static java.util.Objects.requireNonNull; /** * A global source of translations. The global source is the default source used by adventure platforms @@ -75,6 +80,25 @@ public interface GlobalTranslator extends Translator, Examinable { return GlobalTranslatorImpl.INSTANCE.renderer; } + /** + * Renders a component using the {@link #renderer() global renderer}. + * + *
The locale will be determined using the + * {@link #localeOverride(Audience) locale override} or determined using the + * {@link Identity#LOCALE locale pointer}.
+ * + * @param component the component to render + * @param audience the audience to extract the locale from + * @return the rendered component + * @since 4.22.0 + */ + static @NotNull Component render(final @NotNull Component component, final @NotNull Audience audience) { + Locale locale = translator().localeOverride(requireNonNull(audience, "audience")); + if (locale == null) locale = audience.getOrDefault(Identity.LOCALE, null); + if (locale == null) return component; + return render(component, locale); + } + /** * Renders a component using the {@link #renderer() global renderer}. * @@ -115,4 +139,24 @@ public interface GlobalTranslator extends Translator, Examinable { * @since 4.0.0 */ boolean removeSource(final @NotNull Translator source); + + /** + * Sets an override for the locale of the audience when fetched using {@link #localeOverride(Audience)}. + * + * @param audience the audience, may be a {@link ForwardingAudience} to set the override for all members in the audience + * @param locale the locale to set, or {@code null} to remove the override + * @see #localeOverride(Audience) + * @since 4.22.0 + */ + void overrideLocale(final @NotNull Audience audience, final @Nullable Locale locale); + + /** + * Returns the override locale for an audience that will be used in {@link #render(Component, Audience)}. + * + * @param audience the audience member + * @return the locale, if any + * @see #overrideLocale(Audience, Locale) + * @since 4.22.0 + */ + @Nullable Locale localeOverride(final @NotNull Audience audience); } diff --git a/api/src/main/java/net/kyori/adventure/translation/GlobalTranslatorImpl.java b/api/src/main/java/net/kyori/adventure/translation/GlobalTranslatorImpl.java index ef9172cea1..749f09441b 100644 --- a/api/src/main/java/net/kyori/adventure/translation/GlobalTranslatorImpl.java +++ b/api/src/main/java/net/kyori/adventure/translation/GlobalTranslatorImpl.java @@ -26,9 +26,14 @@ import java.text.MessageFormat; import java.util.Collections; import java.util.Locale; +import java.util.Map; import java.util.Set; +import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; import java.util.stream.Stream; +import net.kyori.adventure.audience.Audience; +import net.kyori.adventure.audience.ForwardingAudience; +import net.kyori.adventure.identity.Identity; import net.kyori.adventure.key.Key; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.TranslatableComponent; @@ -45,6 +50,7 @@ final class GlobalTranslatorImpl implements GlobalTranslator { static final GlobalTranslatorImpl INSTANCE = new GlobalTranslatorImpl(); final TranslatableComponentRenderer