From e7f15f98ed0b0def22dbd428c460a036e37e7485 Mon Sep 17 00:00:00 2001 From: Henry Loenwind Date: Sun, 10 Nov 2024 15:07:10 +0100 Subject: [PATCH] Add support for proper plural translation (#1269) --- .../contents/TranslatableContents.java.patch | 50 +++++++++++++++++++ .../neoforge/client/ClientNeoForgeMod.java | 5 ++ 2 files changed, 55 insertions(+) diff --git a/patches/net/minecraft/network/chat/contents/TranslatableContents.java.patch b/patches/net/minecraft/network/chat/contents/TranslatableContents.java.patch index 8e9f97f07ef..2500960f751 100644 --- a/patches/net/minecraft/network/chat/contents/TranslatableContents.java.patch +++ b/patches/net/minecraft/network/chat/contents/TranslatableContents.java.patch @@ -1,5 +1,14 @@ --- a/net/minecraft/network/chat/contents/TranslatableContents.java +++ b/net/minecraft/network/chat/contents/TranslatableContents.java +@@ -55,7 +_,7 @@ + @Nullable + private Language decomposedWith; + private List decomposedParts = ImmutableList.of(); +- private static final Pattern FORMAT_PATTERN = Pattern.compile("%(?:(\\d+)\\$)?([A-Za-z%]|$)"); ++ private static final Pattern FORMAT_PATTERN = Pattern.compile("%(?:(\\d+)\\$)?(n\\([^)]+\\)|[A-Za-z%]|$)"); + + private static DataResult filterAllowedArguments(@Nullable Object p_304727_) { + return !isAllowedPrimitiveArgument(p_304727_) ? DataResult.error(() -> "This value needs to be parsed as component") : DataResult.success(p_304727_); @@ -81,6 +_,13 @@ this.key = p_265775_; this.fallback = p_265204_; @@ -28,6 +37,47 @@ String s = this.fallback != null ? language.getOrDefault(this.key, this.fallback) : language.getOrDefault(this.key); try { +@@ -127,6 +_,10 @@ + String s1 = p_237516_.substring(k, l); + if ("%".equals(s4) && "%%".equals(s1)) { + p_237517_.accept(TEXT_PERCENT); ++ } else if (s4 != null && s4.startsWith("n(")) { ++ String s2 = matcher.group(1); ++ int i1 = s2 != null ? Integer.parseInt(s2) - 1 : i++; ++ p_237517_.accept(FormattedText.of(new com.ibm.icu.text.PluralFormat(lang.get(), s4.substring(2, s4.length() - 1)).format(getArgumentNumeric(i1)))); + } else { + if (!"s".equals(s4)) { + throw new TranslatableFormatException(this, "Unsupported format: '" + s1 + "'"); +@@ -153,6 +_,29 @@ + } + } + ++ /** ++ * Neo: A server-safe way to get the locale from Minecraft#getLocale(). Is set in Neo's client mod. ++ */ ++ public static java.util.function.Supplier lang = () -> com.ibm.icu.util.ULocale.US; ++ ++ /** ++ * Neo: Variant of getArgument that directly converts numeric arguments to double instead of stringifying them first ++ */ ++ private double getArgumentNumeric(int p_237510_) { ++ if (p_237510_ >= 0 && p_237510_ < this.args.length) { ++ Object object = this.args[p_237510_]; ++ if (object instanceof Number number) { ++ return number.doubleValue(); ++ } else if (object instanceof Component component) { ++ return Double.valueOf(component.getString()); ++ } else { ++ return object == null ? 0.d : Double.valueOf(object.toString()); ++ } ++ } else { ++ throw new TranslatableFormatException(this, p_237510_); ++ } ++ } ++ + private FormattedText getArgument(int p_237510_) { + if (p_237510_ >= 0 && p_237510_ < this.args.length) { + Object object = this.args[p_237510_]; @@ -170,6 +_,12 @@ public Optional visit(FormattedText.StyledContentConsumer p_237521_, Style p_237522_) { this.decompose(); diff --git a/src/main/java/net/neoforged/neoforge/client/ClientNeoForgeMod.java b/src/main/java/net/neoforged/neoforge/client/ClientNeoForgeMod.java index d55c15caecb..f158b269bc9 100644 --- a/src/main/java/net/neoforged/neoforge/client/ClientNeoForgeMod.java +++ b/src/main/java/net/neoforged/neoforge/client/ClientNeoForgeMod.java @@ -9,6 +9,7 @@ import net.minecraft.client.renderer.BiomeColors; import net.minecraft.client.renderer.RenderType; import net.minecraft.core.BlockPos; +import net.minecraft.network.chat.contents.TranslatableContents; import net.minecraft.resources.ResourceLocation; import net.minecraft.util.ARGB; import net.minecraft.world.item.SpawnEggItem; @@ -48,6 +49,10 @@ @ApiStatus.Internal @Mod(value = "neoforge", dist = Dist.CLIENT) public class ClientNeoForgeMod { + static { + TranslatableContents.lang = () -> com.ibm.icu.util.ULocale.forLocale(net.minecraft.client.Minecraft.getInstance().getLocale()); + } + public ClientNeoForgeMod(IEventBus modEventBus, ModContainer container) { ClientCommandHandler.init(); TagConventionLogWarningClient.init();