Added localization support
This commit is contained in:
parent
79c7aa91f8
commit
5fcccf05ca
@ -27,6 +27,9 @@ import ru.windcorp.progressia.client.graphics.gui.event.HoverEvent;
|
||||
import ru.windcorp.progressia.client.graphics.gui.layout.LayoutAlign;
|
||||
import ru.windcorp.progressia.client.graphics.gui.layout.LayoutVertical;
|
||||
import ru.windcorp.progressia.client.graphics.input.KeyEvent;
|
||||
import ru.windcorp.progressia.client.localization.Localizer;
|
||||
|
||||
import java.net.http.WebSocket;
|
||||
|
||||
public class LayerTestGUI extends GUILayer {
|
||||
|
||||
@ -78,12 +81,14 @@ public class LayerTestGUI extends GUILayer {
|
||||
Component charlie = new DebugComponent("Charlie", null, 0x222222);
|
||||
charlie.setLayout(new LayoutVertical());
|
||||
|
||||
//Debug
|
||||
Localizer.getInstance().setLanguage("ru-RU");
|
||||
// These two are swapped in code due to a bug in layouts, fixing ATM
|
||||
charlie.addChild(
|
||||
new Label(
|
||||
"Epsilon",
|
||||
new Font().withColor(0x4444BB).deriveItalic(),
|
||||
"Hooray?.. \u269b"
|
||||
Localizer.getInstance().getValue("Epsilon")+"\u269b"
|
||||
)
|
||||
);
|
||||
charlie.addChild(
|
||||
|
@ -0,0 +1,6 @@
|
||||
package ru.windcorp.progressia.client.localization;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface LocaleListener {
|
||||
void onLocaleChanged(String newLanguage);
|
||||
}
|
@ -0,0 +1,76 @@
|
||||
package ru.windcorp.progressia.client.localization;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.*;
|
||||
|
||||
public class Localizer {
|
||||
private static final Localizer instance = new Localizer("assets/languages/lang_list.txt");
|
||||
|
||||
private final Parser langParser;
|
||||
|
||||
private String language;
|
||||
private final String langFolder;
|
||||
|
||||
private Map<String, String> data;
|
||||
private final Map<String, String> langList;
|
||||
|
||||
private final Collection<WeakReference<LocaleListener>> listeners =
|
||||
Collections.synchronizedCollection(new LinkedList<>());
|
||||
|
||||
//lang list must be in the same folder as .lang files
|
||||
public Localizer(String langList) {
|
||||
this.langFolder = langList.concat("/../");
|
||||
langParser = new Parser(langList);
|
||||
this.langList = langParser.parse();
|
||||
}
|
||||
|
||||
public synchronized void setLanguage(String language) {
|
||||
if (langList.containsKey(language)) {
|
||||
this.language = language;
|
||||
langParser.setFilePath(langFolder + language + ".lang");
|
||||
data = langParser.parse();
|
||||
pokeListeners(language);
|
||||
} else {
|
||||
throw new RuntimeException("Language not found: " + language);
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized String getLanguage() {
|
||||
return language;
|
||||
}
|
||||
|
||||
public synchronized String getValue(String key) {
|
||||
try {
|
||||
return data.getOrDefault(key, key);
|
||||
} catch (NullPointerException e) {
|
||||
e.printStackTrace();
|
||||
return key;
|
||||
}
|
||||
}
|
||||
|
||||
private void pokeListeners(String newLanguage) {
|
||||
synchronized (listeners) {
|
||||
Iterator<WeakReference<LocaleListener>> iterator = listeners.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
LocaleListener listenerOrNull = iterator.next().get();
|
||||
if (listenerOrNull == null) {
|
||||
iterator.remove();
|
||||
} else {
|
||||
listenerOrNull.onLocaleChanged(newLanguage);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static Localizer getInstance() {
|
||||
return instance;
|
||||
}
|
||||
|
||||
public void addListener(LocaleListener listener) {
|
||||
listeners.add(new WeakReference<>(listener));
|
||||
}
|
||||
|
||||
public void removeListener(LocaleListener listener) {
|
||||
listeners.removeIf(ref -> listener.equals(ref.get()));
|
||||
}
|
||||
}
|
@ -0,0 +1,94 @@
|
||||
package ru.windcorp.progressia.client.localization;
|
||||
|
||||
import ru.windcorp.jputil.chars.EscapeException;
|
||||
import ru.windcorp.jputil.chars.Escaper;
|
||||
import ru.windcorp.progressia.common.resource.ResourceManager;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.Reader;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class Parser {
|
||||
|
||||
public Parser(String filePath) {
|
||||
this.filePath = filePath;
|
||||
}
|
||||
|
||||
public void setFilePath(String filePath) {
|
||||
this.filePath = filePath;
|
||||
}
|
||||
|
||||
public Map<String, String> parse() {
|
||||
Map<String, String> parsedData = new HashMap<>();
|
||||
try (Reader rawData = ResourceManager
|
||||
.getResource(filePath)
|
||||
.getReader()
|
||||
) {
|
||||
int code;
|
||||
char c;
|
||||
StringBuilder stringBuilder = new StringBuilder();
|
||||
while (true) {
|
||||
code = rawData.read();
|
||||
if (code == -1) {
|
||||
break;
|
||||
}
|
||||
c = (char)code;
|
||||
if (c == '#') {
|
||||
while (c != '\n') {
|
||||
code = rawData.read();
|
||||
if (code == -1) {
|
||||
break;
|
||||
}
|
||||
c = (char)code;
|
||||
}
|
||||
} else if (c == ' ') {
|
||||
code = rawData.read();
|
||||
if (code == -1) {
|
||||
break;
|
||||
}
|
||||
c = (char) code;
|
||||
if (c == '=') {
|
||||
String key = escaper.escape(stringBuilder.toString());
|
||||
stringBuilder.setLength(0);
|
||||
rawData.read(); //skip a char
|
||||
while (true) {
|
||||
code = rawData.read();
|
||||
if (code == -1) {
|
||||
break;
|
||||
}
|
||||
|
||||
c = (char) code;
|
||||
if (code == '\n') {
|
||||
break;
|
||||
} else {
|
||||
stringBuilder.append(c);
|
||||
}
|
||||
}
|
||||
parsedData.put(escaper.unescape(key),
|
||||
escaper.unescape(stringBuilder.toString()));
|
||||
stringBuilder.setLength(0);
|
||||
}
|
||||
} else if (c == '\n') {
|
||||
stringBuilder.setLength(0);
|
||||
} else {
|
||||
stringBuilder.append(c);
|
||||
}
|
||||
}
|
||||
|
||||
} catch (IOException | EscapeException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
return parsedData;
|
||||
}
|
||||
|
||||
public String getFilePath() {
|
||||
return filePath;
|
||||
}
|
||||
|
||||
|
||||
private String filePath;
|
||||
static private final Escaper escaper = new Escaper.EscaperBuilder()
|
||||
.withChars("n", "\n").build();
|
||||
}
|
3
src/main/resources/assets/languages/en-US.lang
Normal file
3
src/main/resources/assets/languages/en-US.lang
Normal file
@ -0,0 +1,3 @@
|
||||
# ru-RU
|
||||
#test
|
||||
Epsilon = Hooray?..
|
2
src/main/resources/assets/languages/lang_list.txt
Normal file
2
src/main/resources/assets/languages/lang_list.txt
Normal file
@ -0,0 +1,2 @@
|
||||
en-US = US English
|
||||
ru-RU = Русский
|
3
src/main/resources/assets/languages/ru-RU.lang
Normal file
3
src/main/resources/assets/languages/ru-RU.lang
Normal file
@ -0,0 +1,3 @@
|
||||
# ru-RU
|
||||
#test
|
||||
Epsilon = Ура?
|
Reference in New Issue
Block a user