Skip to content

Commit

Permalink
Stop using Mojang's translation system entirely
Browse files Browse the repository at this point in the history
Fixes JustAlittleWolf/ModDetectionPreventer#6

Sorry for breaking all open translation PRs with this commit, but it's
necessary for security reasons. Anything in the lang folder can
potentially be read by servers, so the files had to be moved.
  • Loading branch information
Alexander01998 committed Jul 11, 2024
1 parent 5987308 commit f8a096c
Show file tree
Hide file tree
Showing 24 changed files with 255 additions and 228 deletions.
49 changes: 9 additions & 40 deletions src/main/java/net/wurstclient/WurstClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,10 @@
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.IllegalFormatException;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import org.lwjgl.glfw.GLFW;

import net.fabricmc.fabric.api.client.keybinding.v1.KeyBindingHelper;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.option.KeyBinding;
import net.minecraft.client.resource.language.I18n;
import net.minecraft.client.util.InputUtil;
import net.wurstclient.altmanager.AltManager;
import net.wurstclient.altmanager.Encryption;
import net.wurstclient.analytics.WurstAnalytics;
Expand All @@ -41,7 +34,6 @@
import net.wurstclient.hud.IngameHUD;
import net.wurstclient.keybinds.KeybindList;
import net.wurstclient.keybinds.KeybindProcessor;
import net.wurstclient.mixinterface.ILanguageManager;
import net.wurstclient.mixinterface.IMinecraftClient;
import net.wurstclient.navigator.Navigator;
import net.wurstclient.other_feature.OtfList;
Expand Down Expand Up @@ -76,15 +68,14 @@ public enum WurstClient
private IngameHUD hud;
private RotationFaker rotationFaker;
private FriendsList friends;
private WurstTranslator translator;

private boolean enabled = true;
private static boolean guiInitialized;
private WurstUpdater updater;
private ProblematicResourcePackDetector problematicPackDetector;
private Path wurstFolder;

private KeyBinding zoomKey;

public void initialize()
{
System.out.println("Starting Wurst Client...");
Expand Down Expand Up @@ -126,6 +117,8 @@ public void initialize()
friends = new FriendsList(friendsFile);
friends.load();

translator = new WurstTranslator();

cmdProcessor = new CmdProcessor(cmds);
eventManager.add(ChatOutputListener.class, cmdProcessor);

Expand All @@ -150,10 +143,6 @@ public void initialize()
Path encFolder = Encryption.chooseEncryptionFolder();
altManager = new AltManager(altsFile, encFolder);

zoomKey = new KeyBinding("key.wurst.zoom", InputUtil.Type.KEYSYM,
GLFW.GLFW_KEY_V, KeyBinding.MISC_CATEGORY);
KeyBindingHelper.registerKeyBinding(zoomKey);

analytics.trackPageView("/mc" + MC_VERSION + "/v" + VERSION,
"Wurst " + VERSION + " MC" + MC_VERSION);
}
Expand All @@ -178,27 +167,7 @@ private Path createWurstFolder()

public String translate(String key, Object... args)
{
if(otfs.translationsOtf.getForceEnglish().isChecked())
{
String string = ILanguageManager.getEnglish().get(key);

try
{
return String.format(string, args);

}catch(IllegalFormatException e)
{
return key;
}
}

// This extra check is necessary because I18n.translate() doesn't
// always return the key when the translation is missing. If the key
// contains a '%', it will return "Format Error: key" instead.
if(!I18n.hasTranslation(key))
return key;

return I18n.translate(key, args);
return translator.translate(key, args);
}

public WurstAnalytics getAnalytics()
Expand Down Expand Up @@ -314,6 +283,11 @@ public FriendsList getFriends()
return friends;
}

public WurstTranslator getTranslator()
{
return translator;
}

public boolean isEnabled()
{
return enabled;
Expand Down Expand Up @@ -345,11 +319,6 @@ public Path getWurstFolder()
return wurstFolder;
}

public KeyBinding getZoomKey()
{
return zoomKey;
}

public AltManager getAltManager()
{
return altManager;
Expand Down
183 changes: 183 additions & 0 deletions src/main/java/net/wurstclient/WurstTranslator.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,183 @@
/*
* Copyright (c) 2014-2024 Wurst-Imperium and contributors.
*
* This source code is subject to the terms of the GNU General Public
* License, version 3. If a copy of the GPL was not distributed with this
* file, You can obtain one at: https://www.gnu.org/licenses/gpl-3.0.txt
*/
package net.wurstclient;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.IllegalFormatException;
import java.util.List;
import java.util.function.BiConsumer;

import com.google.common.collect.Lists;

import net.minecraft.client.MinecraftClient;
import net.minecraft.client.resource.language.I18n;
import net.minecraft.client.resource.language.TranslationStorage;
import net.minecraft.resource.Resource;
import net.minecraft.resource.ResourceManager;
import net.minecraft.resource.SynchronousResourceReloader;
import net.minecraft.util.Identifier;
import net.minecraft.util.Language;

public class WurstTranslator implements SynchronousResourceReloader
{
private final WurstClient wurst = WurstClient.INSTANCE;
private TranslationStorage mcEnglish;

private final HashMap<String, String> englishOnlyStrings = new HashMap<>();
private final HashMap<String, String> currentLangStrings = new HashMap<>();

@Override
public void reload(ResourceManager manager)
{
mcEnglish = TranslationStorage.load(manager,
Lists.newArrayList("en_us"), false);

currentLangStrings.clear();
loadTranslations(manager, getCurrentLangCodes(),
currentLangStrings::put);

englishOnlyStrings.clear();
loadTranslations(manager, List.of("en_us"), englishOnlyStrings::put);
}

/**
* Translates the given key with the given args into the current language,
* or into English if the "Force English" setting is enabled. Both Wurst and
* vanilla translations are supported.
*/
public String translate(String key, Object... args)
{
// Forced English
if(isForcedEnglish())
return translateEnglish(key, args);

// Wurst translation
String string = currentLangStrings.get(key);
if(string != null)
try
{
return String.format(string, args);

}catch(IllegalFormatException e)
{
return key;
}

// Vanilla translation
return translateMc(key, args);
}

/**
* Translates the given key with the given args into English, regardless of
* the current language. Both Wurst and vanilla translations are supported.
*/
public String translateEnglish(String key, Object... args)
{
String string = englishOnlyStrings.get(key);
if(string == null)
string = mcEnglish.get(key);

try
{
return String.format(string, args);

}catch(IllegalFormatException e)
{
return key;
}
}

/**
* Translates the given key with the given args into the current language,
* or into English if the "Force English" setting is enabled, using only
* Minecraft's own translations.
*
* @apiNote This method differs from
* {@link I18n#translate(String, Object...)} in that it does not
* return "Format error" if the key contains a percent sign.
*/
public String translateMc(String key, Object... args)
{
if(I18n.hasTranslation(key))
return I18n.translate(key, args);

return key;
}

/**
* Translates the given key with the given args into English, regardless of
* the current language, using only Minecraft's own translations.
*
* @apiNote This method differs from
* {@link I18n#translate(String, Object...)} in that it does not
* return "Format error" if the key contains a percent sign.
*/
public String translateMcEnglish(String key, Object... args)
{
try
{
return String.format(mcEnglish.get(key), args);

}catch(IllegalFormatException e)
{
return key;
}
}

public boolean isForcedEnglish()
{
return wurst.getOtfs().translationsOtf.getForceEnglish().isChecked();
}

/**
* Returns a translation storage for Minecraft's English strings, regardless
* of the current language. Does not include any of Wurst's translations.
*/
public TranslationStorage getMcEnglish()
{
return mcEnglish;
}

private ArrayList<String> getCurrentLangCodes()
{
String mainLangCode =
MinecraftClient.getInstance().getLanguageManager().getLanguage();

ArrayList<String> langCodes = new ArrayList<>();
langCodes.add("en_us");
if(!"en_us".equals(mainLangCode))
langCodes.add(mainLangCode);

return langCodes;
}

private void loadTranslations(ResourceManager manager,
Iterable<String> langCodes, BiConsumer<String, String> entryConsumer)
{
for(String langCode : langCodes)
{
String langFilePath = "translations/" + langCode + ".json";
Identifier langId = Identifier.of("wurst", langFilePath);

for(Resource resource : manager.getAllResources(langId))
try(InputStream stream = resource.getInputStream())
{
Language.load(stream, entryConsumer);

}catch(IOException e)
{
System.out.println("Failed to load translations for "
+ langCode + " from pack " + resource.getPackId());
e.printStackTrace();
}
}
}
}
16 changes: 7 additions & 9 deletions src/main/java/net/wurstclient/hacks/autolibrarian/BookOffer.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
import java.util.Objects;
import java.util.Optional;

import net.minecraft.client.resource.language.TranslationStorage;
import net.minecraft.enchantment.Enchantment;
import net.minecraft.registry.DynamicRegistryManager;
import net.minecraft.registry.Registry;
Expand All @@ -21,7 +20,7 @@
import net.minecraft.text.TranslatableTextContent;
import net.minecraft.util.Identifier;
import net.wurstclient.WurstClient;
import net.wurstclient.mixinterface.ILanguageManager;
import net.wurstclient.WurstTranslator;

public record BookOffer(String id, int level, int price)
implements Comparable<BookOffer>
Expand Down Expand Up @@ -53,28 +52,27 @@ public String getEnchantmentName()
{
Text description = getEnchantment().description();
if(description.getContent() instanceof TranslatableTextContent tr)
{
TranslationStorage english = ILanguageManager.getEnglish();
return english.get(tr.getKey());
}
return WurstClient.INSTANCE.getTranslator()
.translateMcEnglish(tr.getKey());

return description.getString();
}

public String getEnchantmentNameWithLevel()
{
TranslationStorage english = ILanguageManager.getEnglish();
WurstTranslator translator = WurstClient.INSTANCE.getTranslator();
Enchantment enchantment = getEnchantment();
String name;

if(enchantment.description()
.getContent() instanceof TranslatableTextContent tr)
name = english.get(tr.getKey());
name = translator.translateMcEnglish(tr.getKey());
else
name = enchantment.description().getString();

if(enchantment.getMaxLevel() > 1)
name += " " + english.get("enchantment.level." + level);
name += " "
+ translator.translateMcEnglish("enchantment.level." + level);

return name;
}
Expand Down
Loading

0 comments on commit f8a096c

Please sign in to comment.