Files
blight/blight-common/src/main/java/de/blight/common/model/TextBundleIO.java
Mario b05eb1055d Lokalisierungs-Editor: liest/schreibt messages_<lang>.properties in blight-lang
TextBundleIO von JSON auf Java-Properties-Format umgestellt (messages_*.properties).
Reihenfolge der Keys bleibt beim Laden erhalten. EditorApp zeigt jetzt auf
blight-lang/src/main/resources/lang/ statt blight-assets/localization/.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-06 07:15:14 +02:00

116 lines
4.7 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package de.blight.common.model;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.*;
import java.util.stream.Stream;
/**
* Lädt und speichert {@link TextBundle}-Instanzen als Java-Properties-Dateien.
* Dateiformat: {@code messages_<lang>.properties} im lang/-Verzeichnis.
*/
public final class TextBundleIO {
private static final Logger log = LoggerFactory.getLogger(TextBundleIO.class);
private static final String PREFIX = "messages_";
private static final String EXTENSION = ".properties";
private TextBundleIO() {}
public static void save(TextBundle bundle, Path dir) throws IOException {
Files.createDirectories(dir);
Path file = dir.resolve(PREFIX + bundle.getLanguage() + EXTENSION);
Properties props = new Properties();
props.putAll(bundle.getEntries());
try (BufferedWriter w = Files.newBufferedWriter(file, StandardCharsets.UTF_8)) {
// Manuell schreiben um Kommentar-Header und Reihenfolge zu erhalten
for (Map.Entry<String, String> e : bundle.getEntries().entrySet()) {
w.write(escapeKey(e.getKey()) + "=" + escapeValue(e.getValue()));
w.newLine();
}
}
log.debug("[TextBundleIO] Gespeichert: {}", file);
}
public static TextBundle load(Path file) throws IOException {
String name = file.getFileName().toString();
String lang = name.replace(PREFIX, "").replace(EXTENSION, "");
Properties props = new Properties();
try (BufferedReader r = Files.newBufferedReader(file, StandardCharsets.UTF_8)) {
props.load(r);
}
// Properties erhält keine garantierte Reihenfolge beim Laden Reihenfolge aus Datei rekonstruieren
LinkedHashMap<String, String> ordered = new LinkedHashMap<>();
try (BufferedReader r = Files.newBufferedReader(file, StandardCharsets.UTF_8)) {
String line;
while ((line = r.readLine()) != null) {
line = line.trim();
if (line.isEmpty() || line.startsWith("#") || line.startsWith("!")) continue;
int eq = line.indexOf('=');
int colon = line.indexOf(':');
int sep = (eq >= 0 && (colon < 0 || eq <= colon)) ? eq : colon;
if (sep < 0) continue;
String key = line.substring(0, sep).trim();
String val = props.getProperty(key, "");
ordered.put(key, val);
}
}
TextBundle bundle = new TextBundle(lang);
bundle.setEntries(ordered);
return bundle;
}
public static List<TextBundle> loadAll(Path dir) {
List<TextBundle> result = new ArrayList<>();
if (!Files.isDirectory(dir)) return result;
try (Stream<Path> walk = Files.list(dir)) {
walk.filter(p -> {
String n = p.getFileName().toString();
return n.startsWith(PREFIX) && n.endsWith(EXTENSION);
})
.sorted()
.forEach(p -> {
try { result.add(load(p)); }
catch (IOException e) { log.warn("[TextBundleIO] Fehler: {}", e.getMessage()); }
});
} catch (IOException e) {
log.warn("[TextBundleIO] Scan-Fehler: {}", e.getMessage());
}
return result;
}
public static List<String> availableLanguages(Path dir) {
List<String> langs = new ArrayList<>();
if (!Files.isDirectory(dir)) return langs;
try (Stream<Path> walk = Files.list(dir)) {
walk.filter(p -> {
String n = p.getFileName().toString();
return n.startsWith(PREFIX) && n.endsWith(EXTENSION);
})
.map(p -> p.getFileName().toString().replace(PREFIX, "").replace(EXTENSION, ""))
.sorted()
.forEach(langs::add);
} catch (IOException ignored) {}
return langs;
}
public static void delete(String language, Path dir) throws IOException {
Files.deleteIfExists(dir.resolve(PREFIX + language + EXTENSION));
}
// ── Hilfsmethoden ─────────────────────────────────────────────────────────
private static String escapeKey(String key) {
return key.replace(" ", "\\ ");
}
private static String escapeValue(String val) {
return val.replace("\\", "\\\\").replace("\n", "\\n").replace("\r", "\\r");
}
}