diff --git a/ReforgerOutputConsole/index.html b/ReforgerOutputConsole/index.html
index bc57f1c..414024a 100644
--- a/ReforgerOutputConsole/index.html
+++ b/ReforgerOutputConsole/index.html
@@ -1,5 +1,5 @@
-
+
Reforger Output Console
@@ -163,9 +163,9 @@
Reforger Output Console
- verbinde…
+ connecting…
-
+
@@ -178,24 +178,24 @@
-
-
+
@@ -208,7 +208,7 @@ const connEl = document.getElementById('conn');
let maxLines = 20000;
const panes = [];
-// Zeilen wie "21:19:25.435 INIT (E): ..." bzw. "(W)"
+// Lines like "21:19:25.435 INIT (E): ..." or "(W)"
const LEVEL_RE = /^\s*\d{1,2}:\d{2}:\d{2}\.\d+\s+\S+\s*\((E|W)\)/;
const TIME_RE = /^\s*\d{1,2}:\d{2}:\d{2}\.\d+\s/;
@@ -265,9 +265,9 @@ function createPane(info) {
return p;
}
-// --- Spaltenbreiten ---------------------------------------------------------
-// Breiten werden als flex-grow-Verhältnis gespeichert, damit sie beim
-// Ändern der Fenstergröße proportional mitwachsen.
+// --- Column widths ---------------------------------------------------------
+// Widths are stored as flex-grow ratios so they scale proportionally
+// when the window is resized.
const MIN_PANE_PX = 150;
const WIDTHS_KEY = 'paneWidths';
@@ -294,15 +294,15 @@ function restoreWidths() {
function addSplitter() {
const sp = document.createElement('div');
sp.className = 'splitter';
- sp.title = 'Ziehen zum Anpassen, Doppelklick = gleich breit';
+ sp.title = 'Drag to resize, double-click = equal widths';
panesEl.appendChild(sp);
sp.addEventListener('pointerdown', (e) => {
e.preventDefault();
const left = sp.previousElementSibling;
const right = sp.nextElementSibling;
- // Alle Spalten auf ihre aktuelle Pixelbreite "einfrieren". Erst alle
- // messen, dann setzen – sonst verfälscht das Zwischen-Layout die Messung.
+ // "Freeze" all columns at their current pixel width. Measure all first,
+ // then set – otherwise the intermediate layout skews the measurement.
const els = paneEls();
const widths = els.map((el) => el.getBoundingClientRect().width);
els.forEach((el, i) => (el.style.flexGrow = widths[i]));
@@ -385,7 +385,7 @@ function makeLine(p, text) {
const m = LEVEL_RE.exec(text);
let lvl = '';
if (m) lvl = m[1] === 'E' ? 'e' : 'w';
- else if (!TIME_RE.test(text) && text.trim() !== '') lvl = p.lastLevel; // Fortsetzungszeile
+ else if (!TIME_RE.test(text) && text.trim() !== '') lvl = p.lastLevel; // continuation line
if (TIME_RE.test(text) || text.trim() === '') p.lastLevel = lvl;
if (lvl) {
div.className = lvl;
@@ -431,7 +431,7 @@ function appendText(p, chunk) {
else if (parts.length) p.jump.hidden = false;
}
-// text === null schließt den Crash-Bereich.
+// text === null closes the crash panel.
function showCrash(p, text) {
p.crashBody.textContent = text || '';
p.crashEl.hidden = text === null;
@@ -450,8 +450,8 @@ function resetPane(p, info) {
const msg = document.createElement('div');
msg.className = 'empty';
msg.textContent = info.dirMissing
- ? 'Ordner nicht gefunden: ' + info.logsDir
- : info.folder ? 'Warte auf ' + info.file + '…' : 'Noch kein Log-Ordner vorhanden.';
+ ? 'Folder not found: ' + info.logsDir
+ : info.folder ? 'Waiting for ' + info.file + '…' : 'No log folder yet.';
p.log.appendChild(msg);
}
setFollow(p, true);
@@ -475,7 +475,7 @@ es.addEventListener('init', (e) => {
resetPane(p, info);
}
restoreWidths();
- connEl.textContent = 'verbunden';
+ connEl.textContent = 'connected';
connEl.classList.remove('down');
});
es.addEventListener('reset', (e) => {
@@ -497,7 +497,7 @@ es.addEventListener('crash', (e) => {
flash(p);
});
es.onerror = () => {
- connEl.textContent = 'Verbindung getrennt – versuche erneut…';
+ connEl.textContent = 'Disconnected – retrying…';
connEl.classList.add('down');
};
diff --git a/ReforgerOutputConsole/server.js b/ReforgerOutputConsole/server.js
index 25d77fd..b0dd167 100644
--- a/ReforgerOutputConsole/server.js
+++ b/ReforgerOutputConsole/server.js
@@ -1,6 +1,6 @@
// Reforger Output Console
-// Überwacht mehrere Log-Ordner, nimmt jeweils den neuesten Unterordner und
-// streamt die darin liegende Log-Datei live an eine Browser-Oberfläche.
+// Watches several log folders, picks the newest subfolder of each and
+// streams the log file inside it live to a browser UI.
const http = require('http');
const fs = require('fs');
@@ -15,7 +15,7 @@ const config = JSON.parse(fs.readFileSync(CONFIG_PATH, 'utf8'));
const PORT = config.port || 8420;
const POLL_MS = config.pollIntervalMs || 500;
const MAX_LINES = config.maxLinesPerPane || 20000;
-// Server-seitiger Puffer, damit neu verbundene Browser den bisherigen Inhalt bekommen.
+// Server-side buffer so newly connected browsers receive the existing content.
const MAX_CHARS = MAX_LINES * 300;
const CRASH_FILE = config.crashFile || 'crash.log';
@@ -53,7 +53,7 @@ function snapshot(p) {
};
}
-// Neuester Unterordner nach Erstellungszeit (bei Gleichstand nach Name).
+// Newest subfolder by creation time (ties broken by name).
function newestFolder(dir) {
let entries;
try {
@@ -88,7 +88,7 @@ function resetPane(p) {
broadcast('reset', snapshot(p));
}
-// Crash-Report ist klein und wird bei jeder Änderung komplett neu gesendet.
+// The crash report is small and is resent in full on every change.
function pollCrash(p) {
const file = path.join(p.logsDir, p.folder, CRASH_FILE);
let st;
@@ -105,7 +105,7 @@ function pollCrash(p) {
} catch {
return;
}
- if (p.crash === null) console.log(`[${p.name}] Crash-Report gefunden: ${p.folder}\\${CRASH_FILE}`);
+ if (p.crash === null) console.log(`[${p.name}] Crash report found: ${p.folder}\\${CRASH_FILE}`);
p.crashStamp = stamp;
p.crash = text;
broadcast('crash', { id: p.id, text });
@@ -116,7 +116,7 @@ function pollPane(p) {
const dirMissing = folder === undefined;
if (folder !== p.folder || dirMissing !== p.dirMissing) {
if (p.folder !== undefined && folder) {
- console.log(`[${p.name}] Neuer Log-Ordner: ${folder}`);
+ console.log(`[${p.name}] New log folder: ${folder}`);
}
p.folder = folder;
p.dirMissing = dirMissing;
@@ -131,10 +131,10 @@ function pollPane(p) {
try {
size = fs.statSync(file).size;
} catch {
- return; // Datei existiert (noch) nicht
+ return; // file doesn't exist (yet)
}
- if (size < p.offset) resetPane(p); // Datei wurde gekürzt/neu geschrieben
+ if (size < p.offset) resetPane(p); // file was truncated/rewritten
if (size === p.offset) return;
let start = p.offset;
@@ -193,7 +193,7 @@ const server = http.createServer((req, res) => {
return;
}
- // Öffnet den aktuellen Log-Ordner eines Panes im Explorer.
+ // Opens a pane's current log folder in Explorer.
if (url.pathname === '/open' && req.method === 'POST') {
const p = panes[Number(url.searchParams.get('id'))];
if (p) {
@@ -207,16 +207,16 @@ const server = http.createServer((req, res) => {
res.writeHead(404).end();
});
-// Keep-alive, damit Verbindungen nicht wegen Inaktivität geschlossen werden.
+// Keep-alive so connections aren't closed due to inactivity.
setInterval(() => {
for (const res of clients) res.write(': ping\n\n');
}, 15000);
server.listen(PORT, '127.0.0.1', () => {
const url = `http://localhost:${PORT}`;
- console.log(`Reforger Output Console läuft auf ${url}`);
- for (const p of panes) console.log(` - ${p.name}: ${p.logsDir}\\\\${p.file}`);
- console.log('Beenden mit Strg+C.');
+ console.log(`Reforger Output Console running at ${url}`);
+ for (const p of panes) console.log(` - ${p.name}: ${p.logsDir}\\\\${p.file}`);
+ console.log('Press Ctrl+C to stop.');
pollAll();
setInterval(pollAll, POLL_MS);
if (config.openBrowser !== false) {
@@ -226,7 +226,7 @@ server.listen(PORT, '127.0.0.1', () => {
server.on('error', (err) => {
if (err.code === 'EADDRINUSE') {
- console.error(`Port ${PORT} ist schon belegt – läuft die Konsole bereits? Sonst "port" in config.json ändern.`);
+ console.error(`Port ${PORT} is already in use – is the console already running? Otherwise change "port" in config.json.`);
} else {
console.error(err);
}