Skip to content

Commit 61a9413

Browse files
Replace ComponentLocalizer with MiniMessageTranslator
1 parent 148d4a0 commit 61a9413

3 files changed

Lines changed: 75 additions & 159 deletions

File tree

invui/src/main/java/xyz/xenondevs/invui/i18n/Languages.java

Lines changed: 70 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,28 @@
11
package xyz.xenondevs.invui.i18n;
22

33
import com.google.gson.stream.JsonReader;
4+
import net.kyori.adventure.key.Key;
45
import net.kyori.adventure.text.Component;
6+
import net.kyori.adventure.text.TranslatableComponent;
7+
import net.kyori.adventure.text.TranslationArgument;
58
import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver;
9+
import net.kyori.adventure.text.minimessage.translation.Argument;
10+
import net.kyori.adventure.text.minimessage.translation.MiniMessageTranslator;
11+
import net.kyori.adventure.text.renderer.ComponentRenderer;
12+
import net.kyori.adventure.text.renderer.TranslatableComponentRenderer;
13+
import net.kyori.adventure.translation.Translator;
14+
import net.kyori.adventure.util.TriState;
615
import org.bukkit.entity.Player;
716
import org.jspecify.annotations.Nullable;
8-
import xyz.xenondevs.invui.internal.util.ComponentLocalizer;
17+
import xyz.xenondevs.invui.InvUI;
918

1019
import java.io.File;
1120
import java.io.FileReader;
1221
import java.io.IOException;
1322
import java.io.Reader;
1423
import java.nio.charset.Charset;
15-
import java.util.HashMap;
16-
import java.util.Locale;
17-
import java.util.Map;
18-
import java.util.function.BiFunction;
24+
import java.text.MessageFormat;
25+
import java.util.*;
1926
import java.util.function.Function;
2027

2128
/**
@@ -25,14 +32,34 @@ public class Languages {
2532

2633
private static final Languages INSTANCE = new Languages();
2734
private final Map<Locale, Map<String, String>> translations = new HashMap<>();
28-
private Function<Player, Locale> localeProvider = Player::locale;
35+
private Function<? super Player, Locale> localeProvider = Player::locale;
2936
private boolean serverSideTranslations = true;
3037

38+
private final Translator translator = new MiniMessageTranslator() {
39+
40+
@Override
41+
public Key name() {
42+
return Key.key(InvUI.getInstance().getPlugin(), "invui_translator");
43+
}
44+
45+
@Override
46+
public boolean canTranslate(String key, Locale locale) {
47+
return getFormatString(locale, key) != null;
48+
}
49+
50+
@Override
51+
protected String getMiniMessageString(String key, Locale locale) {
52+
return Objects.requireNonNull(getFormatString(locale, key));
53+
}
54+
55+
};
56+
3157
private Languages() {
3258
}
3359

3460
/**
3561
* Gets the singleton instance of Languages.
62+
*
3663
* @return The singleton instance of Languages.
3764
*/
3865
public static Languages getInstance() {
@@ -111,7 +138,7 @@ public void loadLanguage(Locale locale, File file, Charset charset) throws IOExc
111138
*
112139
* @param localeProvider The language provider.
113140
*/
114-
public void setLocaleProvider(Function<Player, Locale> localeProvider) {
141+
public void setLocaleProvider(Function<? super Player, Locale> localeProvider) {
115142
this.localeProvider = localeProvider;
116143
}
117144

@@ -148,8 +175,7 @@ public boolean doesServerSideTranslations() {
148175
*
149176
* @param player The player to translate the component for.
150177
* @param component The component to translate.
151-
* @param resolvers Additional mini message tag resolvers that may or may not be used, depending on the
152-
* configured {@link #setComponentCreator(BiFunction) component creator}
178+
* @param resolvers Additional mini message tag resolvers
153179
* @return The translated component or the original component if server-side translations are disabled.
154180
*/
155181
public Component localized(Player player, Component component, TagResolver... resolvers) {
@@ -161,25 +187,50 @@ public Component localized(Player player, Component component, TagResolver... re
161187
*
162188
* @param locale The language to translate the component to.
163189
* @param component The component to translate.
164-
* @param resolvers Additional mini message tag resolvers that may or may not be used, depending on the
165-
* configured {@link #setComponentCreator(BiFunction) component creator}
190+
* @param resolvers Additional mini message tag resolvers
166191
* @return The translated component or the original component if server-side translations are disabled.
167192
*/
168193
public Component localized(Locale locale, Component component, TagResolver... resolvers) {
169194
if (serverSideTranslations) {
170-
return ComponentLocalizer.getInstance().localize(locale, component, resolvers);
195+
return getRenderer(resolvers).render(component, locale);
171196
}
172197

173198
return component;
174199
}
175200

176-
/**
177-
* Configures how components are created from translation strings.
178-
*
179-
* @param componentCreator The function that creates components from translation strings.
180-
*/
181-
public void setComponentCreator(BiFunction<String, TagResolver[], Component> componentCreator) {
182-
ComponentLocalizer.getInstance().setComponentCreator(componentCreator);
201+
private ComponentRenderer<Locale> getRenderer(TagResolver[] resolvers) {
202+
if (resolvers.length == 0)
203+
return TranslatableComponentRenderer.usingTranslationSource(translator);
204+
205+
// specialized TranslatableComponentRenderer that injects resolvers to each TranslatableComponent's arguments
206+
return new TranslatableComponentRenderer<>() {
207+
208+
@Override
209+
protected @Nullable MessageFormat translate(String key, Locale context) {
210+
return translator.translate(key, context);
211+
}
212+
213+
@Override
214+
protected Component renderTranslatableInner(TranslatableComponent component, Locale context) {
215+
TriState anyTranslations = translator.hasAnyTranslations();
216+
if (anyTranslations == TriState.FALSE)
217+
return component;
218+
219+
Component translated;
220+
if (translator.canTranslate(component.key(), context)) {
221+
var args = new ArrayList<>(component.arguments());
222+
args.add(TranslationArgument.component(Argument.tagResolver(resolvers)));
223+
translated = translator.translate(component.arguments(args), context);
224+
} else {
225+
translated = null;
226+
}
227+
228+
return translated != null
229+
? this.render(translated, context)
230+
: super.renderTranslatableInner(component, context);
231+
}
232+
233+
};
183234
}
184235

185236
}

invui/src/main/java/xyz/xenondevs/invui/internal/util/ComponentLocalizer.java

Lines changed: 0 additions & 124 deletions
This file was deleted.

invui/src/test/java/xyz/xenondevs/invui/i18n/LanguagesTest.java

Lines changed: 5 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
import java.util.Locale;
99
import java.util.Map;
1010

11-
import static org.junit.jupiter.api.Assertions.*;
11+
import static org.junit.jupiter.api.Assertions.assertEquals;
1212

1313
class LanguagesTest {
1414

@@ -26,33 +26,22 @@ public void testLocalizeSimple() {
2626
@Test
2727
public void testLocalizeWithParams() {
2828
var l = Languages.getInstance();
29-
l.addLanguage(Locale.US, Map.of("a.b.c", "Sale: %s%% off"));
29+
l.addLanguage(Locale.US, Map.of("a.b.c", "Sale: <arg:0>% off"));
3030

3131
var translatable = Component.translatable("a.b.c", Component.text("50"));
3232
var translated = l.localized(Locale.US, translatable);
3333

3434
assertTextEquals("Sale: 50% off", translated);
3535
}
3636

37-
@Test
38-
public void testLocalizeWithPercentageSymbol() {
39-
var l = Languages.getInstance();
40-
l.addLanguage(Locale.US, Map.of("a.b.c", "%% A %% B %% C"));
41-
42-
var translatable = Component.translatable("a.b.c");
43-
var translated = l.localized(Locale.US, translatable);
44-
45-
assertTextEquals("% A % B % C", translated);
46-
}
47-
4837
@Test
4938
public void testLocalizeWithNestedParams() {
5039
var l = Languages.getInstance();
5140
l.addLanguage(
5241
Locale.US,
5342
Map.of(
54-
"a", "Sale: %s%s%% off",
55-
"b", "%s%s",
43+
"a", "Sale: <arg:0>% off",
44+
"b", "<arg:0><arg:1>",
5645
"c", "5",
5746
"d", "0"
5847
));
@@ -66,7 +55,7 @@ public void testLocalizeWithNestedParams() {
6655
@Test
6756
public void testLocalizedWithPlaceholders() {
6857
var l = Languages.getInstance();
69-
l.addLanguage(Locale.US, Map.of("a.b.c", "Sale: <percentage>%% off"));
58+
l.addLanguage(Locale.US, Map.of("a.b.c", "Sale: <percentage>% off"));
7059

7160
var translatable = Component.translatable("a.b.c");
7261
var translated = l.localized(Locale.US, translatable, Placeholder.unparsed("percentage", "50"));

0 commit comments

Comments
 (0)