Skip to content

Commit b5f9f06

Browse files
committed
log in English
Everything a user reads was English except the log itself - so the diagnostic lines added over the last releases were unreadable for most of the audience they were written for, and anyone reporting an issue had to translate first.
1 parent 0d8b244 commit b5f9f06

13 files changed

Lines changed: 79 additions & 71 deletions

CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,14 @@
33
All notable changes to FaceID. The Home Assistant app shows this file in the
44
update dialog; standalone users can watch GitHub releases.
55

6+
## 0.6.13 — 2026-07-26
7+
8+
- **Log messages are English now.** README, UI, docs and changelog were English while the
9+
service logged in German — so anyone reporting a problem had to translate their own log
10+
first, and the diagnostic lines added in 0.6.10–0.6.12 were unreadable for most of the
11+
people they were written for. All user-facing log output is now English. (Code comments
12+
stay German; they are for whoever edits the source, not for whoever runs it.)
13+
614
## 0.6.12 — 2026-07-26
715

816
- **"No face found" now says which kind.** The log distinguishes *a face was detected but

app/backup_util.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,9 +55,9 @@ def loop():
5555
p = write_backup_file(data_dir, backup_dir)
5656
prune_backups(backup_dir, int(cfg_faceid.get("backup_keep", 7)))
5757
last_day = day
58-
log.info("Auto-Backup geschrieben: %s", p)
58+
log.info("auto backup written: %s", p)
5959
except Exception:
60-
log.exception("Auto-Backup fehlgeschlagen")
60+
log.exception("auto backup failed")
6161
time.sleep(300) # alle 5 Min prüfen
6262

6363
threading.Thread(target=loop, daemon=True, name="faceid-autobackup").start()

app/frigate_api.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ def snapshot(self, event_id: str, crop: bool = True) -> np.ndarray | None:
2424
img = cv2.imdecode(np.frombuffer(r.content, np.uint8), cv2.IMREAD_COLOR)
2525
return img
2626
except requests.RequestException as e:
27-
log.warning("Snapshot %s fehlgeschlagen: %s", event_id, e)
27+
log.warning("snapshot %s failed: %s", event_id, e)
2828
return None
2929

3030
def recording_frame(self, camera: str, ts: float) -> np.ndarray | None:
@@ -37,7 +37,7 @@ def recording_frame(self, camera: str, ts: float) -> np.ndarray | None:
3737
return None
3838
return cv2.imdecode(np.frombuffer(r.content, np.uint8), cv2.IMREAD_COLOR)
3939
except requests.RequestException as e:
40-
log.debug("Recording-Frame %s@%s fehlgeschlagen: %s", camera, ts, e)
40+
log.debug("recording frame %s@%s failed: %s", camera, ts, e)
4141
return None
4242

4343
def download_clip(self, event_id: str, dest: str, max_bytes: int = 80_000_000) -> bool:
@@ -58,12 +58,12 @@ def download_clip(self, event_id: str, dest: str, max_bytes: int = 80_000_000) -
5858
continue
5959
written += len(chunk)
6060
if written > max_bytes:
61-
log.debug("Clip %s abgebrochen (> %d Bytes)", event_id, max_bytes)
61+
log.debug("clip %s aborted (> %d bytes)", event_id, max_bytes)
6262
return False
6363
fh.write(chunk)
6464
return written > 1000
6565
except (requests.RequestException, OSError) as e:
66-
log.debug("Clip %s fehlgeschlagen: %s", event_id, e)
66+
log.debug("clip %s failed: %s", event_id, e)
6767
return False
6868

6969
def set_sub_label(self, event_id: str, label: str, score: float):
@@ -76,4 +76,4 @@ def set_sub_label(self, event_id: str, label: str, score: float):
7676
if r.status_code not in (200, 202):
7777
log.warning("sub_label %s -> %s: HTTP %s %s", event_id, label, r.status_code, r.text[:200])
7878
except requests.RequestException as e:
79-
log.warning("sub_label %s fehlgeschlagen: %s", event_id, e)
79+
log.warning("sub_label %s failed: %s", event_id, e)

app/main.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,8 @@ def main():
3232
try:
3333
cfg.setdefault("faceid", {}).update(json.loads(settings_f.read_text()))
3434
except (json.JSONDecodeError, OSError):
35-
log.warning("settings.json unlesbarignoriert")
36-
log.info("Lade InsightFace (buffalo_l) …")
35+
log.warning("settings.json unreadableignoring it")
36+
log.info("loading InsightFace (buffalo_l) …")
3737
engine = FaceEngine(det_size=int(cfg["faceid"].get("det_size", 640)))
3838
gallery = Gallery(data_dir,
3939
top_k=int(cfg["faceid"].get("match_top_k", 3)),

app/mqtt_listener.py

Lines changed: 21 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -85,22 +85,19 @@ def _check_frigate(self):
8585
try:
8686
r = requests.get(f"{url}/api/config", timeout=8)
8787
if r.status_code != 200:
88-
log.error("Frigate unter %s antwortet mit HTTP %s — ohne Snapshots kann "
89-
"nicht erkannt werden", url, r.status_code)
88+
log.error("Frigate at %s replied HTTP %s — without snapshots nothing can be recognised", url, r.status_code)
9089
return
9190
cams = list((r.json().get("cameras") or {}).keys())
92-
log.info("Frigate erreichbar (%s), Kameras: %s", url, ", ".join(cams) or "keine")
91+
log.info("Frigate reachable (%s), cameras: %s", url, ", ".join(cams) or "keine")
9392
if self.cameras:
9493
unknown = self.cameras - set(cams)
9594
if unknown:
96-
log.warning("Konfigurierte Kamera(s) %s gibt es in Frigate nicht — "
97-
"von diesen wird nie etwas verarbeitet", ", ".join(sorted(unknown)))
95+
log.warning("Configured camera(s) %s do not exist in Frigate — nothing from these will ever be processed", ", ".join(sorted(unknown)))
9896
except (requests.RequestException, ValueError) as e:
99-
log.error("Frigate unter %s nicht erreichbar: %s — Snapshots und damit die "
100-
"Erkennung werden fehlschlagen", url, e)
97+
log.error("Frigate at %s unreachable: %s — snapshots, and therefore recognition, will fail", url, e)
10198

10299
def _on_connect(self, client, userdata, flags, reason_code, properties):
103-
log.info("MQTT verbunden (%s), abonniere %s/events", reason_code, self.frigate_topic)
100+
log.info("MQTT connected (%s), subscribing to %s/events", reason_code, self.frigate_topic)
104101
client.subscribe(f"{self.frigate_topic}/events")
105102
client.publish(f"{self.prefix}/status", "online", retain=True)
106103
self._publish_discovery()
@@ -140,7 +137,7 @@ def _on_message(self, client, userdata, msg):
140137
try:
141138
self.queue.put_nowait({"eid": eid})
142139
except queue.Full:
143-
log.warning("Queue voll, Event %s übersprungen", eid)
140+
log.warning("queue full, skipping event %s", eid)
144141

145142
# ---------- Verarbeitung ----------
146143

@@ -150,7 +147,7 @@ def _worker(self):
150147
try:
151148
self._process(item["eid"])
152149
except Exception:
153-
log.exception("Fehler bei Event %s", item["eid"])
150+
log.exception("error while handling event %s", item["eid"])
154151

155152
def _process(self, eid: str):
156153
st = self.events.get(eid)
@@ -159,7 +156,7 @@ def _process(self, eid: str):
159156
st["attempts"] += 1
160157
img = self.frigate.snapshot(eid, crop=True)
161158
if img is None:
162-
log.info("Event %s (%s): kein Snapshot von Frigate", eid, st["camera"])
159+
log.info("event %s (%s): no snapshot from Frigate", eid, st["camera"])
163160
return
164161
found = self.engine.faces(img)
165162
face = FaceEngine.best_face(found, min_px=self.min_face_px)
@@ -172,11 +169,11 @@ def _process(self, eid: str):
172169
h, w = img.shape[:2]
173170
if found:
174171
big = max(int(f.bbox[2] - f.bbox[0]) for f in found)
175-
log.info("Event %s (%s): Versuch %d, groesstes Gesicht %dpx < min_face_px "
172+
log.info("event %s (%s): attempt %d, largest face %dpx < min_face_px "
176173
"%d (Snapshot %dx%d)", eid, st["camera"], st["attempts"], big,
177174
self.min_face_px, w, h)
178175
else:
179-
log.info("Event %s (%s): Versuch %d, kein Gesicht im Snapshot %dx%d",
176+
log.info("event %s (%s): attempt %d, no face detected in snapshot %dx%d",
180177
eid, st["camera"], st["attempts"], w, h)
181178
return
182179
emb = face.normed_embedding
@@ -192,11 +189,11 @@ def _process(self, eid: str):
192189
if self.ignore_learning and ig >= self.ignore_thr + 0.1 and ig - score >= 0.1:
193190
iid = self.gallery.add_ignore_anchor(crop_face(img, face.bbox), emb)
194191
if iid:
195-
log.info("Event %s: neuer Auto-Ignore-Anker %s (sim %.3f)", eid, iid, ig)
196-
log.info("Event %s (%s): ignoriertes Gesicht (sim %.3f)", eid, st["camera"], ig)
192+
log.info("event %s: new auto ignore anchor %s (sim %.3f)", eid, iid, ig)
193+
log.info("event %s (%s): ignored face (sim %.3f)", eid, st["camera"], ig)
197194
return
198195
crop = crop_face(img, face.bbox)
199-
log.info("Event %s (%s): Versuch %d, Match %s (%.3f)", eid, st["camera"], st["attempts"], name, score)
196+
log.info("event %s (%s): attempt %d, match %s (%.3f)", eid, st["camera"], st["attempts"], name, score)
200197

201198
if slug and score >= self.match_thr:
202199
if score > st["best_score"]:
@@ -236,7 +233,7 @@ def _poller(self):
236233
continue
237234
batch = r.json()
238235
except (requests.RequestException, ValueError) as e:
239-
log.debug("Poll fehlgeschlagen: %s", e)
236+
log.debug("poll failed: %s", e)
240237
continue
241238
since = time.time()
242239
for ev in batch:
@@ -259,12 +256,12 @@ def _poller(self):
259256
"start_time": ev.get("start_time") or time.time(),
260257
"end_time": ev.get("end_time"),
261258
}
262-
log.info("Poll: Ereignis %s (%s) nachgezogen — von MQTT nie gemeldet",
259+
log.info("poll: picked up event %s (%s) — never announced over MQTT",
263260
eid, cam)
264261
try:
265262
self.queue.put_nowait({"eid": eid})
266263
except queue.Full:
267-
log.warning("Queue vollPoll-Ereignis %s verworfen", eid)
264+
log.warning("queue fulldropped polled event %s", eid)
268265

269266
def _finalizer(self):
270267
"""Beendete Events abschließen: Unknown ablegen, 'unbekannt' melden, aufräumen."""
@@ -297,7 +294,7 @@ def _finalizer(self):
297294
new_w = int(face.bbox[2] - face.bbox[0])
298295
if new_w > old_w:
299296
crop, emb, full = crop_face(img, face.bbox), face.normed_embedding, img
300-
log.info("Event %s: hi-res Referenz aus Aufnahme (%dpx statt %dpx)",
297+
log.info("event %s: sharper reference from the recording (%dpx instead of %dpx)",
301298
eid, new_w, old_w)
302299
uid = self.gallery.save_unknown(
303300
crop, emb,
@@ -307,7 +304,7 @@ def _finalizer(self):
307304
full_bgr=full,
308305
)
309306
self._publish_recognition(eid, st, "unknown", u["guess_score"])
310-
log.info("Event %s: unbekanntes Gesicht abgelegt (%s)", eid, uid)
307+
log.info("event %s: unknown face stored (%s)", eid, uid)
311308
self.events.pop(eid, None)
312309

313310
# ---------- Publish ----------
@@ -351,8 +348,7 @@ def _frigate_cameras(self) -> set:
351348
if r.status_code == 200:
352349
return set((r.json().get("cameras") or {}).keys())
353350
except (requests.RequestException, ValueError) as e:
354-
log.warning("Kameraliste von Frigate nicht abrufbar (%s) — Sensoren entstehen "
355-
"dann erst, sobald die erste Person erkannt wird", e)
351+
log.warning("could not fetch the camera list from Frigate (%s) — sensors will appear once the first person is seen", e)
356352
return set()
357353

358354
def _ensure_discovery(self, cam: str):
@@ -377,8 +373,8 @@ def _publish_discovery(self, only: list | None = None):
377373
or set(self.cfg["faceid"].get("discovery_cameras") or [])
378374
or self._frigate_cameras())
379375
self._announced |= cams
380-
log.info("MQTT-Discovery: %d Sensor(en) angemeldet%s", len(cams),
381-
"" if cams else " — Kameras unbekannt, folgen bei der ersten Erkennung")
376+
log.info("MQTT discovery: announced %d sensor(s)%s", len(cams),
377+
"" if cams else " — cameras unknown, they follow on first recognition")
382378
device = {"identifiers": [self.prefix], "name": self.prefix.replace("-", " ").title() if self.prefix != "faceid" else "FaceID",
383379
"manufacturer": "Eigenbau", "model": "InsightFace/ArcFace"}
384380
for cam in cams:

app/webui.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -269,7 +269,7 @@ def worker():
269269
hires=bool(cfg["faceid"].get("hires_enroll", True)))
270270
backfill_state["result"] = stats
271271
except Exception as e:
272-
log.exception("Verlaufs-Scan fehlgeschlagen")
272+
log.exception("history scan failed")
273273
backfill_state["result"] = {"error": str(e)}
274274
finally:
275275
backfill_state["running"] = False

faceid-addon/CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,14 @@
33
All notable changes to FaceID. The Home Assistant app shows this file in the
44
update dialog; standalone users can watch GitHub releases.
55

6+
## 0.6.13 — 2026-07-26
7+
8+
- **Log messages are English now.** README, UI, docs and changelog were English while the
9+
service logged in German — so anyone reporting a problem had to translate their own log
10+
first, and the diagnostic lines added in 0.6.10–0.6.12 were unreadable for most of the
11+
people they were written for. All user-facing log output is now English. (Code comments
12+
stay German; they are for whoever edits the source, not for whoever runs it.)
13+
614
## 0.6.12 — 2026-07-26
715

816
- **"No face found" now says which kind.** The log distinguishes *a face was detected but

faceid-addon/app/backup_util.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,9 +55,9 @@ def loop():
5555
p = write_backup_file(data_dir, backup_dir)
5656
prune_backups(backup_dir, int(cfg_faceid.get("backup_keep", 7)))
5757
last_day = day
58-
log.info("Auto-Backup geschrieben: %s", p)
58+
log.info("auto backup written: %s", p)
5959
except Exception:
60-
log.exception("Auto-Backup fehlgeschlagen")
60+
log.exception("auto backup failed")
6161
time.sleep(300) # alle 5 Min prüfen
6262

6363
threading.Thread(target=loop, daemon=True, name="faceid-autobackup").start()

faceid-addon/app/frigate_api.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ def snapshot(self, event_id: str, crop: bool = True) -> np.ndarray | None:
2424
img = cv2.imdecode(np.frombuffer(r.content, np.uint8), cv2.IMREAD_COLOR)
2525
return img
2626
except requests.RequestException as e:
27-
log.warning("Snapshot %s fehlgeschlagen: %s", event_id, e)
27+
log.warning("snapshot %s failed: %s", event_id, e)
2828
return None
2929

3030
def recording_frame(self, camera: str, ts: float) -> np.ndarray | None:
@@ -37,7 +37,7 @@ def recording_frame(self, camera: str, ts: float) -> np.ndarray | None:
3737
return None
3838
return cv2.imdecode(np.frombuffer(r.content, np.uint8), cv2.IMREAD_COLOR)
3939
except requests.RequestException as e:
40-
log.debug("Recording-Frame %s@%s fehlgeschlagen: %s", camera, ts, e)
40+
log.debug("recording frame %s@%s failed: %s", camera, ts, e)
4141
return None
4242

4343
def download_clip(self, event_id: str, dest: str, max_bytes: int = 80_000_000) -> bool:
@@ -58,12 +58,12 @@ def download_clip(self, event_id: str, dest: str, max_bytes: int = 80_000_000) -
5858
continue
5959
written += len(chunk)
6060
if written > max_bytes:
61-
log.debug("Clip %s abgebrochen (> %d Bytes)", event_id, max_bytes)
61+
log.debug("clip %s aborted (> %d bytes)", event_id, max_bytes)
6262
return False
6363
fh.write(chunk)
6464
return written > 1000
6565
except (requests.RequestException, OSError) as e:
66-
log.debug("Clip %s fehlgeschlagen: %s", event_id, e)
66+
log.debug("clip %s failed: %s", event_id, e)
6767
return False
6868

6969
def set_sub_label(self, event_id: str, label: str, score: float):
@@ -76,4 +76,4 @@ def set_sub_label(self, event_id: str, label: str, score: float):
7676
if r.status_code not in (200, 202):
7777
log.warning("sub_label %s -> %s: HTTP %s %s", event_id, label, r.status_code, r.text[:200])
7878
except requests.RequestException as e:
79-
log.warning("sub_label %s fehlgeschlagen: %s", event_id, e)
79+
log.warning("sub_label %s failed: %s", event_id, e)

faceid-addon/app/main.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,8 @@ def main():
3232
try:
3333
cfg.setdefault("faceid", {}).update(json.loads(settings_f.read_text()))
3434
except (json.JSONDecodeError, OSError):
35-
log.warning("settings.json unlesbarignoriert")
36-
log.info("Lade InsightFace (buffalo_l) …")
35+
log.warning("settings.json unreadableignoring it")
36+
log.info("loading InsightFace (buffalo_l) …")
3737
engine = FaceEngine(det_size=int(cfg["faceid"].get("det_size", 640)))
3838
gallery = Gallery(data_dir,
3939
top_k=int(cfg["faceid"].get("match_top_k", 3)),

0 commit comments

Comments
 (0)