Compare commits
26 Commits
Author | SHA1 | Date | |
---|---|---|---|
73521f1ab2 | |||
11e367a747 | |||
8251ac6ab3 | |||
d5b494bbee | |||
f0a479d7c5 | |||
acaf46b835 | |||
60ae06b581 | |||
32d3d59f1d | |||
5507375bdf | |||
e2d5de3c62 | |||
6ede586866 | |||
fa4fa75944 | |||
6a0cfdb26a | |||
c93a60965f | |||
60cfd016d6 | |||
62f4415b28 | |||
5873dff9ec | |||
27ccde0bec | |||
2a371d627f | |||
f82ded7e5d | |||
dfea11cafd | |||
a614dc95c6 | |||
f4b6addca3 | |||
40df5aff5a | |||
2106596e9c | |||
170271666d |
@ -1,17 +1,40 @@
|
||||
import io.gitlab.jfronny.scripts.*
|
||||
|
||||
plugins {
|
||||
id("jfmod") version "1.2-SNAPSHOT"
|
||||
id("io.gitlab.jfronny.libjf.libjf-config-compiler-plugin")
|
||||
id("jfmod") version "1.6-SNAPSHOT"
|
||||
}
|
||||
|
||||
allprojects { group = "io.gitlab.jfronny" }
|
||||
base.archivesName = "translater"
|
||||
|
||||
val modmenuVersion = "11.0.0-beta.1"
|
||||
jfMod {
|
||||
minecraftVersion = "1.21"
|
||||
yarn("build.1")
|
||||
loaderVersion = "0.15.11"
|
||||
libJfVersion = "3.16.0"
|
||||
fabricApiVersion = "0.100.1+1.21"
|
||||
|
||||
modrinth {
|
||||
projectId = "translater"
|
||||
requiredDependencies.add("libjf")
|
||||
optionalDependencies.add("modmenu")
|
||||
}
|
||||
curseforge {
|
||||
projectId = "394823"
|
||||
requiredDependencies.add("libjf")
|
||||
optionalDependencies.add("modmenu")
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
modImplementation("io.gitlab.jfronny.libjf:libjf-config-core-v1:${prop("libjf_version")}")
|
||||
modImplementation("io.gitlab.jfronny.libjf:libjf-translate-v1:${prop("libjf_version")}")
|
||||
modImplementation("io.gitlab.jfronny.libjf:libjf-config-core-v2")
|
||||
modImplementation("io.gitlab.jfronny.libjf:libjf-translate-v1")
|
||||
|
||||
// Dev env
|
||||
modLocalRuntime("io.gitlab.jfronny.libjf:libjf-config-reflect-v1:${prop("libjf_version")}")
|
||||
modLocalRuntime("io.gitlab.jfronny.libjf:libjf-config-ui-tiny-v1:${prop("libjf_version")}")
|
||||
modLocalRuntime("io.gitlab.jfronny.libjf:libjf-devutil:${prop("libjf_version")}")
|
||||
modLocalRuntime("com.terraformersmc:modmenu:${prop("modmenu_version")}")
|
||||
modLocalRuntime("io.gitlab.jfronny.libjf:libjf-config-ui-tiny")
|
||||
modLocalRuntime("io.gitlab.jfronny.libjf:libjf-devutil")
|
||||
modLocalRuntime("com.terraformersmc:modmenu:$modmenuVersion")
|
||||
// for modmenu
|
||||
modLocalRuntime("net.fabricmc.fabric-api:fabric-resource-loader-v0")
|
||||
modLocalRuntime("net.fabricmc.fabric-api:fabric-screen-api-v1")
|
||||
modLocalRuntime("net.fabricmc.fabric-api:fabric-key-binding-api-v1")
|
||||
}
|
||||
|
@ -1,18 +0,0 @@
|
||||
# https://fabricmc.net/develop/
|
||||
minecraft_version=1.19.3
|
||||
yarn_mappings=build.2
|
||||
loader_version=0.14.11
|
||||
|
||||
maven_group=io.gitlab.jfronny
|
||||
archives_base_name=translater
|
||||
|
||||
modrinth_id=translater
|
||||
modrinth_required_dependencies=libjf
|
||||
modrinth_optional_dependencies=modmenu
|
||||
curseforge_id=394823
|
||||
curseforge_required_dependencies=libjf
|
||||
curseforge_optional_dependencies=modmenu
|
||||
|
||||
libjf_version=3.3.0
|
||||
fabric_version=0.68.1+1.19.3
|
||||
modmenu_version=5.0.0-alpha.4
|
@ -1,13 +1,9 @@
|
||||
pluginManagement {
|
||||
val libjf_version: String by settings
|
||||
repositories {
|
||||
maven("https://maven.fabricmc.net/") // FabricMC
|
||||
maven("https://maven.frohnmeyer-wds.de/artifacts") // scripts
|
||||
gradlePluginPortal()
|
||||
}
|
||||
plugins {
|
||||
id("io.gitlab.jfronny.libjf.libjf-config-compiler-plugin") version libjf_version
|
||||
}
|
||||
}
|
||||
|
||||
rootProject.name = "translater"
|
@ -1,13 +1,20 @@
|
||||
package io.gitlab.jfronny.translater;
|
||||
|
||||
import io.gitlab.jfronny.libjf.config.api.v1.Entry;
|
||||
import io.gitlab.jfronny.libjf.config.api.v1.JfConfig;
|
||||
import io.gitlab.jfronny.libjf.config.api.v2.Entry;
|
||||
import io.gitlab.jfronny.libjf.config.api.v2.JfConfig;
|
||||
|
||||
@JfConfig(referencedConfigs = "libjf-translate-v1")
|
||||
@JfConfig(referencedConfigs = "libjf-translate-v1", tweaker = CfgMigration.class)
|
||||
public class Cfg {
|
||||
@Entry public static int rounds = 5;
|
||||
@Entry public static boolean breakFully = false;
|
||||
@Entry public static String targetLanguage = "en";
|
||||
@Entry public static ProgressMode renderProgress = ProgressMode.None;
|
||||
@Entry public static boolean progressGui = false;
|
||||
@Entry public static boolean progressConsole = true;
|
||||
@Entry public static boolean detailedProgress = false;
|
||||
@Entry public static boolean forceRegenerate = false;
|
||||
@Entry public static boolean useDefaultCache = true;
|
||||
|
||||
static {
|
||||
JFC_Cfg.ensureInitialized();
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,26 @@
|
||||
package io.gitlab.jfronny.translater;
|
||||
|
||||
import io.gitlab.jfronny.libjf.config.api.v2.dsl.ConfigBuilder;
|
||||
import io.gitlab.jfronny.libjf.config.api.v2.dsl.Migration;
|
||||
|
||||
public class CfgMigration {
|
||||
@SuppressWarnings("UnstableApiUsage")
|
||||
public static ConfigBuilder<?> tweak(ConfigBuilder<?> cb) {
|
||||
return cb.addMigration("renderProgress", Migration.of(reader -> {
|
||||
String renderMode = reader.nextString();
|
||||
if (renderMode == null) return;
|
||||
switch (renderMode.toLowerCase()) {
|
||||
case "full" -> Cfg.progressGui = Cfg.progressConsole = Cfg.detailedProgress = true;
|
||||
case "gui" -> {
|
||||
Cfg.progressConsole = Cfg.detailedProgress = false;
|
||||
Cfg.progressGui = true;
|
||||
}
|
||||
case "console" -> {
|
||||
Cfg.progressGui = Cfg.detailedProgress = false;
|
||||
Cfg.progressConsole = true;
|
||||
}
|
||||
case "none" -> Cfg.progressGui = Cfg.progressConsole = Cfg.detailedProgress = false;
|
||||
}
|
||||
}));
|
||||
}
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
package io.gitlab.jfronny.translater;
|
||||
|
||||
import io.gitlab.jfronny.translater.mixin.MinecraftClientAccessor;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
public class RenderScheduler {
|
||||
private final AtomicBoolean shouldRun = new AtomicBoolean(false);
|
||||
|
||||
public void scheduleRender() {
|
||||
shouldRun.set(true);
|
||||
MinecraftClient mc = MinecraftClient.getInstance();
|
||||
if (mc != null && mc.isOnThread()) performTask();
|
||||
}
|
||||
|
||||
public void deschedule() {
|
||||
shouldRun.set(false);
|
||||
}
|
||||
|
||||
private void performTask() {
|
||||
do {
|
||||
((MinecraftClientAccessor) MinecraftClient.getInstance()).invokeRender(false);
|
||||
} while (shouldRun.compareAndSet(true, false));
|
||||
}
|
||||
}
|
@ -2,6 +2,7 @@ package io.gitlab.jfronny.translater;
|
||||
|
||||
import io.gitlab.jfronny.libjf.translate.api.TranslateService;
|
||||
import io.gitlab.jfronny.translater.transformer.CachingTransformer;
|
||||
import io.gitlab.jfronny.translater.transformer.FailTransformer;
|
||||
import io.gitlab.jfronny.translater.transformer.TransformingMap;
|
||||
import io.gitlab.jfronny.translater.transformer.TranslatingTransformer;
|
||||
import net.fabricmc.api.EnvType;
|
||||
@ -17,13 +18,16 @@ import java.util.Map;
|
||||
public class Translater {
|
||||
public static final String MOD_ID = "translater";
|
||||
public static final Logger LOGGER = LoggerFactory.getLogger(MOD_ID);
|
||||
private static final TransformingMap map = new TransformingMap(new CachingTransformer(new TranslatingTransformer<>(TranslateService.getConfigured())));
|
||||
private static final TransformingMap map;
|
||||
|
||||
public static boolean progressUIEnabled() {
|
||||
return Cfg.renderProgress == ProgressMode.Full || Cfg.renderProgress == ProgressMode.Gui;
|
||||
static {
|
||||
TranslateService<?> ts = TranslateService.getConfigured();
|
||||
if (ts == null || ts.getName().equals("Noop")) {
|
||||
LOGGER.error("No translation service found! Please configure a translation service in the libjf-translate config and restart the game!\nThis means NO NEW TRANSLATIONS WILL BE GENERATED!");
|
||||
map = new TransformingMap(new CachingTransformer(new FailTransformer()));
|
||||
} else {
|
||||
map = new TransformingMap(new CachingTransformer(new TranslatingTransformer<>(ts)));
|
||||
}
|
||||
public static boolean progressLogsEnabled() {
|
||||
return Cfg.renderProgress == ProgressMode.Full || Cfg.renderProgress == ProgressMode.Console;
|
||||
}
|
||||
|
||||
public static @NotNull TransformingMap getMap(@Nullable Map<String, String> base) {
|
||||
|
@ -4,18 +4,29 @@ import io.gitlab.jfronny.translater.Translater;
|
||||
import net.minecraft.client.resource.language.TranslationStorage;
|
||||
import net.minecraft.util.Language;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
import org.spongepowered.asm.mixin.injection.*;
|
||||
|
||||
@Mixin(Language.class)
|
||||
import java.util.Map;
|
||||
|
||||
@Mixin(value = Language.class, priority = 900)
|
||||
public class LanguageMixin {
|
||||
@Inject(at = @At("HEAD"), method = "setInstance")
|
||||
private static void languageSetInstance(Language language, CallbackInfo ci) {
|
||||
@ModifyVariable(at = @At("HEAD"), method = "setInstance", argsOnly = true)
|
||||
private static Language languageSetInstance(Language language) {
|
||||
if (language instanceof TranslationStorage t) {
|
||||
TranslationStorageAccessor ta = (TranslationStorageAccessor) t;
|
||||
ta.setTranslations(Translater.getMap(ta.getTranslations()));
|
||||
Translater.LOGGER.info("Set translater backend");
|
||||
Translater.LOGGER.info("Set translater backend 2");
|
||||
} else Translater.LOGGER.error("Unsupported language configured: {}", language);
|
||||
return language;
|
||||
}
|
||||
|
||||
@ModifyArg(
|
||||
at = @At(value = "INVOKE", target = "Lnet/minecraft/util/Language$1;<init>(Ljava/util/Map;)V"),
|
||||
method = "create()Lnet/minecraft/util/Language;",
|
||||
index = 0
|
||||
)
|
||||
private static Map<String, String> postCreate(Map<String, String> par1) {
|
||||
Translater.LOGGER.info("Set translater backend 1");
|
||||
return Translater.getMap(par1);
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
package io.gitlab.jfronny.translater.mixin;
|
||||
|
||||
import io.gitlab.jfronny.translater.Translater;
|
||||
import io.gitlab.jfronny.libjf.LibJf;
|
||||
import io.gitlab.jfronny.translater.Cfg;
|
||||
import org.objectweb.asm.tree.ClassNode;
|
||||
import org.spongepowered.asm.mixin.extensibility.IMixinConfigPlugin;
|
||||
import org.spongepowered.asm.mixin.extensibility.IMixinInfo;
|
||||
@ -22,13 +23,14 @@ public class Plugin implements IMixinConfigPlugin {
|
||||
@SuppressWarnings("ReferenceToMixin")
|
||||
@Override
|
||||
public boolean shouldApplyMixin(String targetClassName, String mixinClassName) {
|
||||
LibJf.setup();
|
||||
if (Objects.equals(mixinClassName, LanguageMixin.class.getName())
|
||||
|| Objects.equals(mixinClassName, TranslationStorageAccessor.class.getName()))
|
||||
return true;
|
||||
else if (Objects.equals(mixinClassName, MinecraftClientAccessor.class.getName()))
|
||||
return Translater.progressUIEnabled();
|
||||
return Cfg.progressGui;
|
||||
else if (Objects.equals(mixinClassName, SplashScreenMixin.class.getName()))
|
||||
return Translater.progressUIEnabled();
|
||||
return Cfg.progressGui;
|
||||
else
|
||||
throw new IllegalStateException("Unrecognized mixin! This should never happen");
|
||||
}
|
||||
|
@ -1,43 +1,42 @@
|
||||
package io.gitlab.jfronny.translater.mixin;
|
||||
|
||||
import com.google.gson.JsonParser;
|
||||
import com.mojang.serialization.JsonOps;
|
||||
import io.gitlab.jfronny.translater.Translater;
|
||||
import io.gitlab.jfronny.translater.transformer.TransformingMap;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.client.font.FontStorage;
|
||||
import net.minecraft.client.font.FontType;
|
||||
import net.minecraft.client.font.TextRenderer;
|
||||
import net.minecraft.client.font.*;
|
||||
import net.minecraft.client.gui.DrawContext;
|
||||
import net.minecraft.client.gui.screen.Overlay;
|
||||
import net.minecraft.client.gui.screen.SplashOverlay;
|
||||
import net.minecraft.client.util.math.MatrixStack;
|
||||
import net.minecraft.util.Identifier;
|
||||
import org.spongepowered.asm.mixin.Final;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.*;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
|
||||
@Mixin(SplashOverlay.class)
|
||||
public abstract class SplashScreenMixin extends Overlay {
|
||||
@Shadow @Final private MinecraftClient client;
|
||||
|
||||
private TextRenderer translater$textRenderer;
|
||||
@Unique private TextRenderer translater$textRenderer;
|
||||
|
||||
@Inject(at = @At("RETURN"), method = "renderProgressBar")
|
||||
private void renderTranslationProgress(MatrixStack matrixStack, int i, int j, int k, int l, float f, CallbackInfo ci) {
|
||||
private void renderTranslationProgress(DrawContext context, int minX, int minY, int maxX, int maxY, float opacity, CallbackInfo ci) {
|
||||
TransformingMap map = Translater.getMap(null);
|
||||
if (map.initializing) {
|
||||
translater$textRenderer.draw(matrixStack, map.getInitProgress(), 10, 10, 0);
|
||||
context.drawText(translater$textRenderer, map.getInitProgress(), 10, 10, 0, false);
|
||||
}
|
||||
}
|
||||
|
||||
@Inject(method = "<init>", at = @At("RETURN"))
|
||||
public void setup(CallbackInfo ci) {
|
||||
final FontStorage fontStorage = new FontStorage(client.getTextureManager(), new Identifier("loading"));
|
||||
fontStorage.setFonts(Collections.singletonList(FontType.BITMAP.createLoader(JsonParser.parseString("""
|
||||
public void setup(CallbackInfo ci) throws IOException {
|
||||
final FontStorage fontStorage = new FontStorage(client.getTextureManager(), Identifier.ofVanilla("loading"));
|
||||
Font font = JsonOps.INSTANCE.getMap(JsonParser.parseString("""
|
||||
{
|
||||
"type": "bitmap",
|
||||
"file": "minecraft:font/ascii.png",
|
||||
@ -60,7 +59,11 @@ public abstract class SplashScreenMixin extends Overlay {
|
||||
"\\u03b1\\u03b2\\u0393\\u03c0\\u03a3\\u03c3\\u03bc\\u03c4\\u03a6\\u0398\\u03a9\\u03b4\\u221e\\u2205\\u2208\\u2229",
|
||||
"\\u2261\\u00b1\\u2265\\u2264\\u2320\\u2321\\u00f7\\u2248\\u00b0\\u2219\\u00b7\\u221a\\u207f\\u00b2\\u25a0\\u0000"
|
||||
]
|
||||
}""").getAsJsonObject()).load(client.getResourceManager())));
|
||||
}""").getAsJsonObject())
|
||||
.flatMap(ml -> FontType.BITMAP.getLoaderCodec().decode(JsonOps.INSTANCE, ml))
|
||||
.map(fl -> fl.build().left().orElseThrow()).getOrThrow()
|
||||
.load(client.getResourceManager());
|
||||
fontStorage.setFonts(Collections.singletonList(new Font.FontFilterPair(font, FontFilterType.FilterMap.NO_FILTER)), Set.of());
|
||||
translater$textRenderer = new TextRenderer(id -> fontStorage, false);
|
||||
}
|
||||
}
|
||||
|
@ -1,17 +1,22 @@
|
||||
package io.gitlab.jfronny.translater.transformer;
|
||||
|
||||
import io.gitlab.jfronny.libjf.config.api.v1.ConfigHolder;
|
||||
import io.gitlab.jfronny.commons.concurrent.AsyncRequestState;
|
||||
import io.gitlab.jfronny.libjf.config.api.v2.ConfigHolder;
|
||||
import io.gitlab.jfronny.translater.Cfg;
|
||||
import io.gitlab.jfronny.translater.Translater;
|
||||
import net.fabricmc.loader.api.FabricLoader;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.*;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Properties;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public class CachingTransformer implements Transformer {
|
||||
private static final Path CACHE_FILE = FabricLoader.getInstance().getConfigDir().resolve(Translater.MOD_ID + ".cache");
|
||||
private final @Nullable Properties defaultCache;
|
||||
private final Properties cache = new Properties();
|
||||
private final Transformer transformer;
|
||||
|
||||
@ -21,18 +26,47 @@ public class CachingTransformer implements Transformer {
|
||||
return null;
|
||||
//Transform and cache if not present
|
||||
if (!cache.containsKey(str)) {
|
||||
if (defaultCache != null && defaultCache.containsKey(str)) return (String) defaultCache.get(str);
|
||||
String transformed = transformer.transform(str);
|
||||
if (transformed == null) {
|
||||
// The transformer failed
|
||||
return str;
|
||||
}
|
||||
cache.put(str, transformed);
|
||||
save();
|
||||
scheduleSave();
|
||||
}
|
||||
//Return cached result
|
||||
return (String) cache.get(str);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void transformMultiple(Stream<? extends String> strings, ResultConsumer results) {
|
||||
AtomicInteger count = new AtomicInteger(0);
|
||||
transformer.transformMultiple(strings.filter(s -> {
|
||||
String translation = (String) cache.get(s);
|
||||
if (translation != null) {
|
||||
results.accept(s, translation);
|
||||
return false;
|
||||
}
|
||||
if (defaultCache != null) {
|
||||
translation = (String) defaultCache.get(s);
|
||||
if (translation != null) {
|
||||
results.accept(s, translation);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}), (str, translation) -> {
|
||||
cache.put(str, translation);
|
||||
results.accept(str, translation);
|
||||
if (count.incrementAndGet() == 50) {
|
||||
count.addAndGet(-50);
|
||||
scheduleSave();
|
||||
}
|
||||
});
|
||||
if (count.get() > 0) scheduleSave();
|
||||
}
|
||||
|
||||
public CachingTransformer(Transformer baseTransformer) {
|
||||
transformer = baseTransformer;
|
||||
if (Cfg.forceRegenerate) {
|
||||
@ -47,32 +81,37 @@ public class CachingTransformer implements Transformer {
|
||||
} catch (IOException e) {
|
||||
Translater.LOGGER.error("Could not load translater cache", e);
|
||||
}
|
||||
} else {
|
||||
}
|
||||
}
|
||||
//Save default cache if parameters are default
|
||||
if (!Cfg.breakFully && Cfg.rounds == 5) {
|
||||
if (Cfg.useDefaultCache && !Cfg.breakFully && Cfg.rounds == 5 && "en".equals(Cfg.targetLanguage) && !Cfg.forceRegenerate) {
|
||||
Translater.LOGGER.info("Initializing default cache");
|
||||
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
|
||||
InputStream inS = classLoader.getResourceAsStream("namecache.ini");
|
||||
if (inS != null) {
|
||||
try {
|
||||
cache.load(inS);
|
||||
inS.close();
|
||||
save();
|
||||
Properties p = new Properties();
|
||||
try (InputStream inS = classLoader.getResourceAsStream("namecache.ini")) {
|
||||
if (inS == null) p = null;
|
||||
else p.load(inS);
|
||||
} catch (IOException e) {
|
||||
Translater.LOGGER.error("Could not initialize default translater cache");
|
||||
p = null;
|
||||
Translater.LOGGER.error("Could not initialize default translater cache", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
save();
|
||||
defaultCache = p;
|
||||
} else defaultCache = null;
|
||||
scheduleSave();
|
||||
}
|
||||
|
||||
private void save() {
|
||||
private final AsyncRequestState state = new AsyncRequestState();
|
||||
private void scheduleSave() {
|
||||
if (state.request().shouldStart()) {
|
||||
do {
|
||||
if (!cache.isEmpty()) {
|
||||
try (OutputStream outS = Files.newOutputStream(CACHE_FILE)) {
|
||||
cache.store(outS, "---Lang---");
|
||||
} catch (IOException e) {
|
||||
Translater.LOGGER.error("Could not save translater cache");
|
||||
}
|
||||
}
|
||||
} while (state.emitFinished().shouldContinue());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,14 @@
|
||||
package io.gitlab.jfronny.translater.transformer;
|
||||
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public class FailTransformer implements Transformer {
|
||||
@Override
|
||||
public String transform(String str) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void transformMultiple(Stream<? extends String> strings, ResultConsumer results) {
|
||||
}
|
||||
}
|
@ -1,5 +1,13 @@
|
||||
package io.gitlab.jfronny.translater.transformer;
|
||||
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public interface Transformer {
|
||||
String transform(String str);
|
||||
void transformMultiple(Stream<? extends String> strings, ResultConsumer results);
|
||||
|
||||
@FunctionalInterface
|
||||
interface ResultConsumer {
|
||||
void accept(String str, String translation);
|
||||
}
|
||||
}
|
||||
|
@ -1,18 +1,21 @@
|
||||
package io.gitlab.jfronny.translater.transformer;
|
||||
|
||||
import io.gitlab.jfronny.translater.Cfg;
|
||||
import io.gitlab.jfronny.translater.RenderScheduler;
|
||||
import io.gitlab.jfronny.translater.Translater;
|
||||
import io.gitlab.jfronny.translater.mixin.MinecraftClientAccessor;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
public class TransformingMap implements Map<String, String> {
|
||||
private final Transformer transformer;
|
||||
private final RenderScheduler renderScheduler = new RenderScheduler();
|
||||
private Map<String, String> backer = null;
|
||||
public boolean initializing = false;
|
||||
private String initProgress = null;
|
||||
private AtomicInteger initProgress = null;
|
||||
private int maxProgress = 0;
|
||||
|
||||
public TransformingMap(Transformer t) {
|
||||
transformer = t;
|
||||
@ -23,24 +26,28 @@ public class TransformingMap implements Map<String, String> {
|
||||
this.backer = backer;
|
||||
Collection<String> strings = backer.values();
|
||||
initializing = true;
|
||||
final int max = strings.size();
|
||||
int i = 0;
|
||||
for (String value : strings) {
|
||||
initProgress = "Transforming " + i++ + "/" + max;
|
||||
if (Translater.progressLogsEnabled())
|
||||
Translater.LOGGER.info(initProgress);
|
||||
if (Translater.progressUIEnabled() && i % 10 == 0)
|
||||
((MinecraftClientAccessor) MinecraftClient.getInstance()).invokeRender(false);
|
||||
initProgress = null;
|
||||
transformer.transform(value);
|
||||
}
|
||||
generateTranslations(strings);
|
||||
initializing = false;
|
||||
}
|
||||
}
|
||||
|
||||
private void generateTranslations(Collection<? extends String> strings) {
|
||||
maxProgress = strings.size();
|
||||
initProgress = new AtomicInteger();
|
||||
transformer.transformMultiple(strings.parallelStream(), (str, translation) -> {
|
||||
int i = initProgress.incrementAndGet();
|
||||
if (i % 10 == 0 || Cfg.detailedProgress) {
|
||||
if (Cfg.progressConsole) Translater.LOGGER.info(getInitProgress());
|
||||
if (Cfg.progressGui && i % 10 == 0) renderScheduler.scheduleRender();
|
||||
}
|
||||
});
|
||||
renderScheduler.deschedule();
|
||||
initProgress = null;
|
||||
}
|
||||
|
||||
public String getInitProgress() {
|
||||
if (initProgress == null || !initializing) throw new IllegalStateException("Tried to get init progress while not initializing");
|
||||
return initProgress;
|
||||
return "Transforming %d/%d".formatted(initProgress.get(), maxProgress);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -65,8 +72,7 @@ public class TransformingMap implements Map<String, String> {
|
||||
|
||||
@Override
|
||||
public String get(Object o) {
|
||||
if (o instanceof String && ((String)o).startsWith("translater."))
|
||||
return backer.get(o);
|
||||
if (o instanceof String s && s.startsWith("translater.")) return backer.get(s);
|
||||
return transformer.transform(backer.get(o));
|
||||
}
|
||||
|
||||
@ -83,9 +89,7 @@ public class TransformingMap implements Map<String, String> {
|
||||
|
||||
@Override
|
||||
public void putAll(Map<? extends String, ? extends String> map) {
|
||||
for (String value : map.values()) {
|
||||
transformer.transform(value);
|
||||
}
|
||||
generateTranslations(map.values());
|
||||
backer.putAll(map);
|
||||
}
|
||||
|
||||
@ -101,11 +105,11 @@ public class TransformingMap implements Map<String, String> {
|
||||
|
||||
@Override
|
||||
public Collection<String> values() {
|
||||
return backer.values();
|
||||
return backer.values(); // This does not support updates, but I don't care
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<Entry<String, String>> entrySet() {
|
||||
return backer.entrySet();
|
||||
return backer.entrySet(); // This does not support updates, but I don't care
|
||||
}
|
||||
}
|
||||
|
@ -7,10 +7,13 @@ import io.gitlab.jfronny.translater.Cfg;
|
||||
import io.gitlab.jfronny.translater.Translater;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
import java.util.*;
|
||||
import java.util.function.Function;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static java.util.function.Function.identity;
|
||||
|
||||
public class TranslatingTransformer<T extends Language> implements Transformer {
|
||||
public TranslatingTransformer(TranslateService<T> ts) {
|
||||
@ -31,16 +34,24 @@ public class TranslatingTransformer<T extends Language> implements Transformer {
|
||||
@Override
|
||||
public String transform(String str) {
|
||||
try {
|
||||
return tryTransform(str);
|
||||
} catch (Exception e) {
|
||||
Translater.LOGGER.warn("Failed to transform: \"{}\" ({} characters)! Please report this bug with the mod containing the lang file! ({})", str, str.length(), e.getLocalizedMessage());
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private String tryTransform(String str) throws TranslateException {
|
||||
if (str.contains("%")) {
|
||||
StringBuilder res = new StringBuilder();
|
||||
boolean f = true;
|
||||
for (String s : str.split("%")) {
|
||||
if (!f) {
|
||||
res.append("%");
|
||||
if (s.length() > 0)
|
||||
res.append(s.charAt(0)).append(transform(s.substring(1)).replace("%", ""));
|
||||
} else
|
||||
res.append(transform(s));
|
||||
if (!s.isEmpty()) {
|
||||
appendTransformed(res.append(s.charAt(0)), s.substring(1), x -> x.replace("%", ""));
|
||||
}
|
||||
} else appendTransformed(res, s, identity());
|
||||
f = false;
|
||||
}
|
||||
return res.toString();
|
||||
@ -48,10 +59,8 @@ public class TranslatingTransformer<T extends Language> implements Transformer {
|
||||
StringBuilder res = new StringBuilder();
|
||||
boolean f = true;
|
||||
for (String s : str.split("\\$")) {
|
||||
if (!f) {
|
||||
res.append("$").append(s.charAt(0)).append(transform(s.substring(1)).replace("$", ""));
|
||||
} else
|
||||
res.append(transform(s));
|
||||
if (f) appendTransformed(res, s, identity());
|
||||
else appendTransformed(res.append("$").append(s.charAt(0)), s.substring(1), x -> x.replace("$", ""));
|
||||
f = false;
|
||||
}
|
||||
return res.toString();
|
||||
@ -59,10 +68,8 @@ public class TranslatingTransformer<T extends Language> implements Transformer {
|
||||
StringBuilder res = new StringBuilder();
|
||||
boolean f = true;
|
||||
for (String s : str.split("§")) {
|
||||
if (!f) {
|
||||
res.append("§").append(s.charAt(0)).append(transform(s.substring(1)).replace("§", ""));
|
||||
} else
|
||||
res.append(transform(s));
|
||||
if (f) appendTransformed(res, s, identity());
|
||||
else appendTransformed(res.append("§").append(s.charAt(0)), s.substring(1), x -> x.replace("§", ""));
|
||||
f = false;
|
||||
}
|
||||
return res.toString();
|
||||
@ -70,17 +77,29 @@ public class TranslatingTransformer<T extends Language> implements Transformer {
|
||||
return translateMultiple(str);
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
Translater.LOGGER.warn("Failed to transform: \"" + str + "\" (" + str.length() + " characters)");
|
||||
Translater.LOGGER.warn("Please report this bug with the mod containing the lang file");
|
||||
return null;
|
||||
|
||||
private void appendTransformed(StringBuilder sb, String transformable, Function<String, String> fix) throws TranslateException {
|
||||
if (transformable.isEmpty()) return;
|
||||
sb.append(fix.apply(tryTransform(transformable)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void transformMultiple(Stream<? extends String> strings, ResultConsumer results) {
|
||||
strings.flatMap(s -> {
|
||||
try {
|
||||
return Stream.of(new Translation(s, tryTransform(s)));
|
||||
} catch (Exception e) {
|
||||
return Stream.empty();
|
||||
}
|
||||
}).forEach(t -> results.accept(t.from, t.to));
|
||||
}
|
||||
|
||||
private record Translation(String from, String to) {}
|
||||
|
||||
private String translateMultiple(String str) throws TranslateException {
|
||||
Matcher m = SURROUNDING_SPACE_PATTERN.matcher(str);
|
||||
if (!m.find()) {
|
||||
Translater.LOGGER.info("Skipping translation of \"" + str + "\"");
|
||||
if (Cfg.detailedProgress) Translater.LOGGER.info("Skipping translation of \"{}\"", str);
|
||||
return str;
|
||||
}
|
||||
try {
|
||||
@ -96,10 +115,11 @@ public class TranslatingTransformer<T extends Language> implements Transformer {
|
||||
}
|
||||
currentState = ts.translate(currentState, currentLang, startLang == languageAuto ? languageEnglish : startLang); // Translate to starting language
|
||||
currentState = m.group(1) + currentState + m.group(3); // Add back surrounding white space
|
||||
Translater.LOGGER.info("Transformed: \"" + str + "\" to: \"" + currentState + "\"");
|
||||
if (Cfg.detailedProgress) Translater.LOGGER.info("Transformed: \"{}\" to: \"{}\"", str, currentState);
|
||||
return currentState;
|
||||
} catch (Exception e) {
|
||||
Translater.LOGGER.warn("Failed to break: \"" + m.group(2) + "\" (" + m.group(2).length() + " characters). Is your API key valid?");
|
||||
String s = m.group(2);
|
||||
Translater.LOGGER.warn("Failed to break: \"{}\" ({} characters). Is your API key valid? ({})", s, s.length(), e.getLocalizedMessage());
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
@ -6,12 +6,14 @@
|
||||
"translater.jfconfig.breakFully.tooltip": "Whether to fully break the texts content by translating from the wrong language (enable for complete breaking)",
|
||||
"translater.jfconfig.targetLanguage": "Target Language",
|
||||
"translater.jfconfig.targetLanguage.tooltip": "The language to translate to - Leave empty for auto-detection (might break text even more)",
|
||||
"translater.jfconfig.renderProgress": "Progress Renderer",
|
||||
"translater.jfconfig.renderProgress.tooltip": "Significantly slows down the loading time but gives a visual of the progress. Values: Full, Console, None",
|
||||
"translater.jfconfig.progressGui": "Progress GUI",
|
||||
"translater.jfconfig.progressGui.tooltip": "Significantly slows down the loading time but gives an in-game visual of the progress",
|
||||
"translater.jfconfig.progressConsole": "Progress Console",
|
||||
"translater.jfconfig.progressConsole.tooltip": "Slightly slows down the loading time but logs the progress",
|
||||
"translater.jfconfig.detailedProgress": "Detailed Progress",
|
||||
"translater.jfconfig.renderProgress.tooltip": "Significantly slows down the loading time but provides information about individual translations",
|
||||
"translater.jfconfig.forceRegenerate": "Force Regenerate",
|
||||
"translater.jfconfig.forceRegenerate.tooltip": "Use this if something is broken. This initiates the regeneration of the cache",
|
||||
"translater.jfconfig.enum.ProgressMode.Full": "Full",
|
||||
"translater.jfconfig.enum.ProgressMode.Gui": "Gui",
|
||||
"translater.jfconfig.enum.ProgressMode.Console": "Console",
|
||||
"translater.jfconfig.enum.ProgressMode.None": "None"
|
||||
"translater.jfconfig.useDefaultCache": "Use default Cache",
|
||||
"translater.jfconfig.useDefaultCache.tooltip": "Use pre-generated translations shipped with the mod if the config permits to save time"
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -15,7 +15,7 @@
|
||||
"icon": "assets/translater/icon.png",
|
||||
"environment": "client",
|
||||
"entrypoints": {
|
||||
"libjf:config": ["io.gitlab.jfronny.translater.Cfg"]
|
||||
"libjf:config": ["io.gitlab.jfronny.translater.JFC_Cfg"]
|
||||
},
|
||||
"mixins": [
|
||||
"translater.mixins.json"
|
||||
@ -25,11 +25,5 @@
|
||||
"minecraft": "*",
|
||||
"libjf-config-core-v1": ">=3.0.3",
|
||||
"libjf-translate-v1": ">=3.0.3"
|
||||
},
|
||||
"custom": {
|
||||
"modupdater": {
|
||||
"strategy": "curseforge",
|
||||
"projectID": 394823
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user