Skip to content

Commit 2dff66c

Browse files
feat(i18n): add startup validation for missing translation keys
HypixelTranslator now eagerly loads all en_US keys at construction. I18n.requireKey() throws IllegalStateException if a key is missing from the default locale. All I18n.t(), string(), and dialogueLines() methods validate keys on use, failing fast at startup if any referenced key is absent from the English translation files.
1 parent a9a161b commit 2dff66c

3 files changed

Lines changed: 41 additions & 0 deletions

File tree

loader/src/main/java/net/swofty/loader/Hypixel.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
import net.swofty.type.generic.RavengardTypeLoader;
3535
import net.swofty.type.generic.SkyBlockTypeLoader;
3636
import net.swofty.type.generic.i18n.HypixelTranslator;
37+
import net.swofty.type.generic.i18n.I18n;
3738
import net.swofty.type.ravengardgeneric.RavengardGenericLoader;
3839
import net.swofty.type.skyblockgeneric.SkyBlockGenericLoader;
3940
import org.json.JSONArray;
@@ -190,7 +191,9 @@ static void main(String[] args) {
190191

191192
MinestomAdventure.AUTOMATIC_COMPONENT_TRANSLATION = true;
192193
HypixelTranslator translator = new HypixelTranslator();
194+
I18n.init(translator);
193195
GlobalTranslator.translator().addSource(translator);
196+
Logger.info("Loaded " + translator.keyCount() + " translation keys for default locale");
194197

195198
// Start the server
196199
MinecraftServer.setBrandName("Hypixel");

type.generic/src/main/java/net/swofty/type/generic/i18n/HypixelTranslator.java

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,24 +18,28 @@
1818
import java.nio.file.Path;
1919
import java.time.Duration;
2020
import java.util.HashMap;
21+
import java.util.HashSet;
2122
import java.util.Locale;
2223
import java.util.Map;
2324
import java.util.Objects;
2425
import java.util.Optional;
26+
import java.util.Set;
2527

2628
public class HypixelTranslator extends MiniMessageTranslator {
2729

2830
public static final Locale defaultLocale = Locale.US;
2931
private static final Path I18N_ROOT = Path.of("./configuration/i18n");
3032

3133
private final Map<Locale, Map<String, Path>> fileIndexByLocale;
34+
private final Set<String> defaultLocaleKeys;
3235
private final Cache<LocaleSubsystem, Map<String, String>> bundleCache;
3336
private final Cache<LocaleKey, Optional<String>> keyCache;
3437

3538
public HypixelTranslator() {
3639
super(MiniMessage.miniMessage());
3740

3841
this.fileIndexByLocale = buildFileIndex(I18N_ROOT);
42+
this.defaultLocaleKeys = loadAllKeysForLocale(defaultLocale);
3943

4044
this.bundleCache = Caffeine.newBuilder()
4145
.maximumSize(64L)
@@ -48,6 +52,25 @@ public HypixelTranslator() {
4852
.build();
4953
}
5054

55+
public boolean hasKey(String key) {
56+
return defaultLocaleKeys.contains(key);
57+
}
58+
59+
public int keyCount() {
60+
return defaultLocaleKeys.size();
61+
}
62+
63+
private Set<String> loadAllKeysForLocale(Locale locale) {
64+
Map<String, Path> localeIndex = fileIndexByLocale.get(locale);
65+
if (localeIndex == null) return Set.of();
66+
67+
Set<String> keys = new HashSet<>();
68+
for (Path file : localeIndex.values()) {
69+
keys.addAll(loadPropertiesFileFlat(file).keySet());
70+
}
71+
return Set.copyOf(keys);
72+
}
73+
5174
@Override
5275
public @Nullable String getMiniMessageString(@NotNull String key, @NotNull Locale locale) {
5376
LocaleKey lk = new LocaleKey(locale, key);

type.generic/src/main/java/net/swofty/type/generic/i18n/I18n.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,30 @@ public class I18n {
1515

1616
private static final String DIALOGUE_SEPARATOR = "\\|";
1717

18+
private static HypixelTranslator translator;
19+
20+
public static void init(HypixelTranslator instance) {
21+
translator = instance;
22+
}
23+
24+
public static void requireKey(String key) {
25+
if (translator != null && !translator.hasKey(key)) {
26+
throw new IllegalStateException("Missing translation key in en_US: " + key);
27+
}
28+
}
29+
1830
public static TranslatableComponent t(String key) {
31+
requireKey(key);
1932
return Component.translatable(key);
2033
}
2134

2235
public static TranslatableComponent t(String key, Component... args) {
36+
requireKey(key);
2337
return Component.translatable(key, args);
2438
}
2539

2640
public static String string(String key, Locale locale) {
41+
requireKey(key);
2742
Component rendered = GlobalTranslator.render(Component.translatable(key), locale);
2843
return LEGACY.serialize(rendered);
2944
}

0 commit comments

Comments
 (0)