Files
Stargate/src/main/java/net/knarcraft/stargate/config/LanguageLoader.java
EpicKnarvik97 1c906528f2 Cleans up message logging quite a bit
Adds methods to Stargate for easier logging and less redundancy
Loads the language loader in two parts to make it available while loading
Adds a translated string to the reload-message
Uses String.format to make long messages more readable
Makes it possible to get strings directly from the backup language to make debugging easier
2021-10-26 15:05:05 +02:00

256 lines
9.7 KiB
Java

package net.knarcraft.stargate.config;
import net.knarcraft.stargate.Stargate;
import net.knarcraft.stargate.utility.FileHelper;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
/**
* This class is responsible for loading all strings which are translated into several languages
*/
public final class LanguageLoader {
private final String languageFolder;
private final Map<String, String> loadedBackupStrings;
private String chosenLanguage;
private Map<String, String> loadedStringTranslations;
/**
* Instantiates a new language loader
*
* <p>This will only load the backup language. Set the chosen language and reload afterwards.</p>
*
* @param languageFolder <p>The folder containing the language files</p>
*/
public LanguageLoader(String languageFolder) {
this.languageFolder = languageFolder;
File testFile = new File(languageFolder, "en.txt");
if (!testFile.exists()) {
if (testFile.getParentFile().mkdirs()) {
Stargate.debug("LanguageLoader", "Created language folder");
}
}
//Load english as backup language in case the chosen language is missing newly added text strings
InputStream inputStream = FileHelper.getInputStreamForInternalFile("/lang/en.txt");
if (inputStream != null) {
loadedBackupStrings = load("en", inputStream);
} else {
loadedBackupStrings = null;
Stargate.getConsoleLogger().severe("[stargate] Error loading backup language. " +
"There may be missing text in-game");
}
}
/**
* Reloads languages from the files on disk
*/
public void reload() {
//Extracts/Updates the language as needed
updateLanguage(chosenLanguage);
loadedStringTranslations = load(chosenLanguage);
}
/**
* Gets the string to display given its name/key
*
* @param name <p>The name/key of the string to display</p>
* @return <p>The string in the user's preferred language</p>
*/
public String getString(String name) {
String value = null;
if (loadedStringTranslations != null) {
value = loadedStringTranslations.get(name);
}
if (value == null) {
value = getBackupString(name);
}
return value;
}
/**
* Gets the string to display given its name/key
*
* @param name <p>The name/key of the string to display</p>
* @return <p>The string in the backup language (English)</p>
*/
public String getBackupString(String name) {
String value = null;
if (loadedBackupStrings != null) {
value = loadedBackupStrings.get(name);
}
if (value == null) {
return "";
}
return value;
}
/**
* Sets the chosen plugin language
*
* @param chosenLanguage <p>The new plugin language</p>
*/
public void setChosenLanguage(String chosenLanguage) {
this.chosenLanguage = chosenLanguage;
}
/**
* Updates files in the plugin directory with contents from the compiled .jar
*
* @param language <p>The language to update</p>
*/
private void updateLanguage(String language) {
Map<String, String> currentLanguageValues = load(language);
InputStream inputStream = getClass().getResourceAsStream("/lang/" + language + ".txt");
if (inputStream == null) {
Stargate.logInfo(String.format("The language %s is not available. Falling back to english, You can add a " +
"custom language by creating a new text file in the lang directory.", language));
Stargate.debug("LanguageLoader::updateLanguage", String.format("Unable to load /lang/%s.txt", language));
return;
}
try {
readChangedLanguageStrings(inputStream, language, currentLanguageValues);
} catch (IOException ex) {
ex.printStackTrace();
}
}
/**
* Reads language strings
*
* @param inputStream <p>The input stream to read from</p>
* @param language <p>The selected language</p>
* @param currentLanguageValues <p>The current values of the loaded/processed language</p>
* @throws IOException <p>if unable to read a language file</p>
*/
private void readChangedLanguageStrings(InputStream inputStream, String language, Map<String,
String> currentLanguageValues) throws IOException {
//Get language values
BufferedReader bufferedReader = FileHelper.getBufferedReaderFromInputStream(inputStream);
Map<String, String> internalLanguageValues = FileHelper.readKeyValuePairs(bufferedReader);
//If currentLanguageValues is null; the chosen language has not been used before
if (currentLanguageValues == null) {
updateLanguageFile(language, internalLanguageValues, null);
Stargate.logInfo(String.format("Language (%s) has been loaded", language));
return;
}
//If a key is not found in the language file, add the one in the internal file. Must update the external file
if (!internalLanguageValues.keySet().equals(currentLanguageValues.keySet())) {
Map<String, String> newLanguageValues = new HashMap<>();
boolean updateNecessary = false;
for (String key : internalLanguageValues.keySet()) {
if (currentLanguageValues.get(key) == null) {
newLanguageValues.put(key, internalLanguageValues.get(key));
//Found at least one value in the internal file not in the external file. Need to update
updateNecessary = true;
} else {
newLanguageValues.put(key, currentLanguageValues.get(key));
currentLanguageValues.remove(key);
}
}
//Update the file itself
if (updateNecessary) {
updateLanguageFile(language, newLanguageValues, currentLanguageValues);
Stargate.logInfo(String.format("Your language file (%s.txt) has been updated", language));
}
}
}
/**
* Updates the language file for a given language
*
* @param language <p>The language to update</p>
* @param languageStrings <p>The updated language strings</p>
* @param customLanguageStrings <p>Any custom language strings not recognized</p>
* @throws IOException <p>If unable to write to the language file</p>
*/
private void updateLanguageFile(String language, Map<String, String> languageStrings,
Map<String, String> customLanguageStrings) throws IOException {
BufferedWriter bufferedWriter = FileHelper.getBufferedWriterFromString(languageFolder + language + ".txt");
//Output normal Language data
for (String key : languageStrings.keySet()) {
bufferedWriter.write(key + "=" + languageStrings.get(key));
bufferedWriter.newLine();
}
bufferedWriter.newLine();
//Output any custom language strings the user had
if (customLanguageStrings != null) {
for (String key : customLanguageStrings.keySet()) {
bufferedWriter.write(key + "=" + customLanguageStrings.get(key));
bufferedWriter.newLine();
}
}
bufferedWriter.close();
}
/**
* Loads the given language
*
* @param lang <p>The language to load</p>
* @return <p>A mapping between loaded string indexes and the strings to display</p>
*/
private Map<String, String> load(String lang) {
return load(lang, null);
}
/**
* Loads the given language
*
* @param lang <p>The language to load</p>
* @param inputStream <p>An optional input stream to use. Defaults to using a file input stream</p>
* @return <p>A mapping between loaded string indexes and the strings to display</p>
*/
private Map<String, String> load(String lang, InputStream inputStream) {
Map<String, String> strings;
BufferedReader bufferedReader;
try {
if (inputStream == null) {
bufferedReader = FileHelper.getBufferedReaderFromString(languageFolder + lang + ".txt");
} else {
bufferedReader = FileHelper.getBufferedReaderFromInputStream(inputStream);
}
strings = FileHelper.readKeyValuePairs(bufferedReader);
} catch (Exception e) {
if (Stargate.getStargateConfig().isDebuggingEnabled()) {
Stargate.getConsoleLogger().info("[Stargate] Unable to load language " + lang);
}
return null;
}
return strings;
}
/**
* Prints debug output to the console for checking loaded language strings/translations
*/
public void debug() {
if (loadedStringTranslations != null) {
Set<String> keys = loadedStringTranslations.keySet();
for (String key : keys) {
Stargate.debug("LanguageLoader::Debug::loadedStringTranslations", key + " => " +
loadedStringTranslations.get(key));
}
}
if (loadedBackupStrings == null) {
return;
}
Set<String> keys = loadedBackupStrings.keySet();
for (String key : keys) {
Stargate.debug("LanguageLoader::Debug::loadedBackupStrings", key + " => " +
loadedBackupStrings.get(key));
}
}
}