Symptom
On a German hub (cfg.language = "de", other plugins confirmed German - GeoIP / proxydetect report in German), +cmdlog show still prints English:
[ 2026-07-17 / 16:40:52 ] | Command: [+!#]accinfo | used by: [HUBOWNER]Aybo
The German lang file has the right values (msg1 = " | Befehl: [+!#]", msg2 = " | benutzt von: ") and loads cleanly - they are just never applied to these entries.
Root cause: formatting happens at write-time, not show-time
The onBroadcast logger bakes the current-language labels into each stored line (scripts/etc_cmdlog.lua:147):
f:write( os_date( " [ %Y-%m-%d / %H:%M:%S ]" ) .. msg1 .. s1 .. " " .. s2 .. msg2 .. user:nick() .. "\n" )
+cmdlog show (:159-164) reads the file raw and wraps it in the msg_out banner - it does not re-format. So:
- every entry is frozen in whatever language was active when it was logged,
- a log that spans a
cfg.language change is a mix of languages,
- switching to German never affects entries written earlier.
In the reporter's case all entries predate the switch, so all are English. Run one command now (hub German) and the newest line will be Befehl: / benutzt von: while the old ones stay English - that is the confirmation.
Second reader, same defect: the HTTP API
GET /v1/log/cmd (:202-216) reads the same log/cmd.log via read_log_tail, so it returns the same baked-in, possibly-mixed-language sentences. An API consumer wants fields, not a localized sentence, so this is the wrong contract there too.
Fix shape
Store the log language-neutral - the fields (timestamp, command, args, nick), no msg1/msg2 in the file - and apply the labels at read-time:
+cmdlog show: parse each line into fields, render with the current msg1/msg2. Old + new entries then both render in the active language.
GET /v1/log/cmd: return structured fields (a real contract improvement; decide the exact shape in the PR, per HTTP_API.md conventions).
- Migration: existing
log/cmd.log files hold old baked lines that will not split into fields. The parser must degrade gracefully - render an unparseable old line as-is (raw, in its frozen language) rather than dropping it or erroring. Note this in the PR and cover it with a test.
scriptversion bump (user-visible output + storage format change). Guard: plugin_lang_test.lua already asserts the msg1/msg2 keys resolve in both langs; add a unit test for the parse-and-render round-trip incl. the old-format fallback.
Not a regression / not a blocker
Pre-existing design flaw, older than and unrelated to #442 (which fixed different keys - failmsg1/failmsg2 -> msg_denied/msg_nofile) and untouched by the #447 dead-code arc. It exists on master today and does not block the pending dev->master promotion. Candidate for the post-promotion small-PR batch alongside #444 / #456 / #457 / #459.
Symptom
On a German hub (
cfg.language = "de", other plugins confirmed German - GeoIP / proxydetect report in German),+cmdlog showstill prints English:The German lang file has the right values (
msg1 = " | Befehl: [+!#]",msg2 = " | benutzt von: ") and loads cleanly - they are just never applied to these entries.Root cause: formatting happens at write-time, not show-time
The
onBroadcastlogger bakes the current-language labels into each stored line (scripts/etc_cmdlog.lua:147):+cmdlog show(:159-164) reads the file raw and wraps it in themsg_outbanner - it does not re-format. So:cfg.languagechange is a mix of languages,In the reporter's case all entries predate the switch, so all are English. Run one command now (hub German) and the newest line will be
Befehl:/benutzt von:while the old ones stay English - that is the confirmation.Second reader, same defect: the HTTP API
GET /v1/log/cmd(:202-216) reads the samelog/cmd.logviaread_log_tail, so it returns the same baked-in, possibly-mixed-language sentences. An API consumer wants fields, not a localized sentence, so this is the wrong contract there too.Fix shape
Store the log language-neutral - the fields (timestamp, command, args, nick), no
msg1/msg2in the file - and apply the labels at read-time:+cmdlog show: parse each line into fields, render with the currentmsg1/msg2. Old + new entries then both render in the active language.GET /v1/log/cmd: return structured fields (a real contract improvement; decide the exact shape in the PR, per HTTP_API.md conventions).log/cmd.logfiles hold old baked lines that will not split into fields. The parser must degrade gracefully - render an unparseable old line as-is (raw, in its frozen language) rather than dropping it or erroring. Note this in the PR and cover it with a test.scriptversionbump (user-visible output + storage format change). Guard:plugin_lang_test.luaalready asserts themsg1/msg2keys resolve in both langs; add a unit test for the parse-and-render round-trip incl. the old-format fallback.Not a regression / not a blocker
Pre-existing design flaw, older than and unrelated to #442 (which fixed different keys -
failmsg1/failmsg2->msg_denied/msg_nofile) and untouched by the #447 dead-code arc. It exists onmastertoday and does not block the pending dev->master promotion. Candidate for the post-promotion small-PR batch alongside #444 / #456 / #457 / #459.