Commit 98ac42a6 authored by AnimeGitB's avatar AnimeGitB
Browse files

Flatten language translation keys in-memory

parent a4f10208
...@@ -14,8 +14,6 @@ import it.unimi.dsi.fastutil.objects.Object2IntMap; ...@@ -14,8 +14,6 @@ import it.unimi.dsi.fastutil.objects.Object2IntMap;
import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
import javax.annotation.Nullable;
import static emu.grasscutter.config.Configuration.*; import static emu.grasscutter.config.Configuration.*;
import static emu.grasscutter.utils.FileUtils.getResourcePath; import static emu.grasscutter.utils.FileUtils.getResourcePath;
...@@ -46,9 +44,8 @@ import java.util.Map; ...@@ -46,9 +44,8 @@ import java.util.Map;
public final class Language { public final class Language {
private static final Map<String, Language> cachedLanguages = new ConcurrentHashMap<>(); private static final Map<String, Language> cachedLanguages = new ConcurrentHashMap<>();
private final JsonObject languageData;
private final String languageCode; private final String languageCode;
private final Map<String, String> cachedTranslations = new ConcurrentHashMap<>(); private final Map<String, String> translations = new ConcurrentHashMap<>();
/** /**
* Creates a language instance from a code. * Creates a language instance from a code.
...@@ -139,20 +136,36 @@ public final class Language { ...@@ -139,20 +136,36 @@ public final class Language {
return languageCode; return languageCode;
} }
/**
* Recursive helper function to flatten a Json tree
* Converts input like {"foo": {"bar": "baz"}} to {"foo.bar": "baz"}
* @param map The map to insert the keys into
* @param key The flattened key of the current element
* @param element The current element
*/
private static void putFlattenedKey(Map<String,String> map, String key, JsonElement element) {
if (element.isJsonObject()) {
element.getAsJsonObject().entrySet().forEach(entry -> {
String keyPrefix = key.isEmpty() ? "" : key + ".";
putFlattenedKey(map, keyPrefix + entry.getKey(), entry.getValue());
});
} else {
map.put(key, element.getAsString());
}
}
/** /**
* Reads a file and creates a language instance. * Reads a file and creates a language instance.
*/ */
private Language(LanguageStreamDescription description) { private Language(LanguageStreamDescription description) {
@Nullable JsonObject languageData = null;
languageCode = description.getLanguageCode(); languageCode = description.getLanguageCode();
try { try {
languageData = JsonUtils.decode(Utils.readFromInputStream(description.getLanguageFile()), JsonObject.class); var object = JsonUtils.decode(Utils.readFromInputStream(description.getLanguageFile()), JsonObject.class);
object.entrySet().forEach(entry -> putFlattenedKey(translations, entry.getKey(), entry.getValue()));
} catch (Exception exception) { } catch (Exception exception) {
Grasscutter.getLogger().warn("Failed to load language file: " + description.getLanguageCode(), exception); Grasscutter.getLogger().warn("Failed to load language file: " + description.getLanguageCode(), exception);
} }
this.languageData = languageData;
} }
/** /**
...@@ -199,41 +212,16 @@ public final class Language { ...@@ -199,41 +212,16 @@ public final class Language {
* @return The value (as a string) from a nested key. * @return The value (as a string) from a nested key.
*/ */
public String get(String key) { public String get(String key) {
if (this.cachedTranslations.containsKey(key)) { if (translations.containsKey(key)) return translations.get(key);
return this.cachedTranslations.get(key);
}
String[] keys = key.split("\\.");
JsonObject object = this.languageData;
int index = 0;
String valueNotFoundPattern = "This value does not exist. Please report this to the Discord: "; String valueNotFoundPattern = "This value does not exist. Please report this to the Discord: ";
String result = valueNotFoundPattern + key; String result = valueNotFoundPattern + key;
boolean isValueFound = false; if (!languageCode.equals("en-US")) {
String englishValue = getLanguage("en-US").get(key);
while (true) {
if (index == keys.length) break;
String currentKey = keys[index++];
if (object.has(currentKey)) {
JsonElement element = object.get(currentKey);
if (element.isJsonObject())
object = element.getAsJsonObject();
else {
isValueFound = true;
result = element.getAsString(); break;
}
} else break;
}
if (!isValueFound && !languageCode.equals("en-US")) {
var englishValue = getLanguage("en-US").get(key);
if (!englishValue.contains(valueNotFoundPattern)) { if (!englishValue.contains(valueNotFoundPattern)) {
result += "\nhere is english version:\n" + englishValue; result += "\nhere is english version:\n" + englishValue;
} }
} }
return result;
this.cachedTranslations.put(key, result); return result;
} }
private static class LanguageStreamDescription { private static class LanguageStreamDescription {
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment