Globalization/src/main/java/io/gitlab/jfronny/globalization/GlobalizationMap.java

139 lines
4.8 KiB
Java

package io.gitlab.jfronny.globalization;
import io.gitlab.jfronny.libjf.translate.api.*;
import net.fabricmc.loader.api.FabricLoader;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.*;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.*;
import java.util.stream.Collectors;
public class GlobalizationMap extends AbstractMap<String, String> {
private static final Path targetPath = FabricLoader.getInstance().getConfigDir().resolve("globalization");
private List<Map<String, String>> pools = new LinkedList<>();
public void fork() {
if (pools.isEmpty() || !getCurrentPool().isEmpty()) pools.add(new LinkedHashMap<>());
}
public Map<String, String> generateMissing() {
if (pools.isEmpty()) return Map.of();
if (pools.size() == 1) return pools.get(0);
return generateMissing(pools.get(pools.size() - 1), pools.subList(0, pools.size() - 1), TranslateService.getConfigured());
}
private static <T extends Language, S extends TranslateService<T>> Map<String, String> generateMissing(Map<String, String> origin, List<Map<String, String>> other, S service) {
Map<String, String> target = new LinkedHashMap<>(origin);
Map<String, String> toAdd = other
.stream()
.map(Map::entrySet)
.flatMap(Collection::stream)
.filter(s -> !target.containsKey(s.getKey()))
.collect(Collectors.toMap(Entry::getKey, Entry::getValue));
Properties cache = new Properties();
T targetLang = service.parseLang(GlobalizationConfig.targetCode);
Path cacheFile = targetPath.resolve(targetLang.getIdentifier() + ".cache");
try {
Files.createDirectories(targetPath);
if (Files.exists(cacheFile)) {
try (Reader r = Files.newBufferedReader(cacheFile)) {
cache.load(r);
}
}
} catch (IOException e) {
Globalization.LOG.error("Could not read cache", e);
}
toAdd.forEach((k, v) -> {
try {
if (cache.containsKey(v)) target.put(k, cache.get(v).toString());
else {
String s = service.translate(v, service.detect(v), targetLang);
target.put(k, s);
cache.put(v, s);
Globalization.LOG.info("Translated " + v + " to " + s);
}
} catch (TranslateException e) {
Globalization.LOG.error("Could not translate " + v, e);
}
});
try {
Files.createDirectories(targetPath);
try (Writer w = Files.newBufferedWriter(cacheFile)) {
cache.store(w, "Cache for translations to " + targetLang.getDisplayName());
}
} catch (IOException e) {
Globalization.LOG.error("Could not write cache", e);
}
return target;
}
private Map<String, String> getCurrentPool() {
if (pools.isEmpty()) throw new IllegalStateException("Called method on non-forked globalization map");
return pools.get(pools.size() - 1);
}
@Nullable
@Override
public String put(String s, String s2) {
String s3 = getCurrentPool().put(s, s2);
if (s3 == null) {
for (Map<String, String> map : pools.subList(0, pools.size() - 1)) {
s3 = map.getOrDefault(s, s3);
}
}
return s3;
}
@NotNull
@Override
public Set<Entry<String, String>> entrySet() {
return pools.stream()
.map(Map::entrySet)
.flatMap(Collection::stream)
.collect(Collectors.groupingBy(Entry::getKey, Collectors.toList()))
.entrySet()
.stream()
.map(s -> new MapEntry<>(s.getKey(), s.getValue().get(s.getValue().size() - 1).getValue()))
.collect(Collectors.toUnmodifiableSet());
}
@Override
public boolean isEmpty() {
return pools.isEmpty() || (pools.size() == 1 && pools.get(0).isEmpty());
}
@Override
public boolean containsKey(Object o) {
return pools.stream().anyMatch(s -> s.containsKey(o));
}
@Override
public boolean containsValue(Object o) {
return pools.stream().anyMatch(s -> s.containsValue(o));
}
@Override
public String get(Object o) {
throw new UnsupportedOperationException();
}
@Override
public String remove(Object o) {
throw new UnsupportedOperationException();
}
@Override
public void clear() {
throw new UnsupportedOperationException();
}
@NotNull
@Override
public Set<String> keySet() {
return pools.stream().flatMap(s -> s.keySet().stream()).collect(Collectors.toUnmodifiableSet());
}
}