The ModTools template refresh introduced ~80 hardcoded English strings
(labels, placeholders, tooltips, empty-state copy, button text). Move
every one of them onto the modtools.* namespace and read via
LocalizeText so the panels translate alongside the rest of the client.
UITexts.example (versioned template) extended with the full set:
modtools.window.* Launcher box (toolbar item, tools,
selected-user state, ticket count)
modtools.userinfo.* User info card — already had the
legacy modtools.userinfo.{userName,
cfhCount, …} keys from before; added
refresh tooltip, presence pill labels
(in_room / online / offline with
matching .title tooltips), section
headings, action button labels, stat
card labels
modtools.roominfo.* Room info card — title, refresh, loading,
owner pill (here/away + tooltips), stat
labels, action buttons, moderate panel
heading + checkboxes + textarea
placeholder + caution/alert CTAs
modtools.user.message.* Send-message dialog (recipient label,
body label, placeholder, char counter,
empty state, send button)
modtools.user.modaction.* Mod Action form — header, sanctioning
label, 3-step section titles, select
placeholders, message label + optional
note, message placeholder, preview
heading, default/apply buttons, every
sendAlert error message
modtools.user.visits.* Room visits — title, header strip
heading, entry count (singular/plural),
empty state, column headers, visit
button + tooltip
modtools.user.chatlog.* User chatlog — title (with username
variant), loading state
modtools.room.chatlog.* Room chatlog title
modtools.chatlog.* Shared ChatlogView — column headers,
empty state, room-separator Visit/Tools
buttons
modtools.tickets.* Tickets window — title, tab labels
(open/mine/picked), column headers,
empty states, action buttons (pick/
handle/release), issue resolution
window (title, label, details heading,
field labels, chatlog toggle, resolve-as
heading, resolution buttons, release
back to queue), CFH chatlog title
The same 130 entries land in Nitro-Files/.../UITexts.json (runtime).
Both files validate as JSON. The runtime additions take effect on
next client reload; the template additions ship the strings to any
fresh deploy.
Notes:
- The MOD_ACTION_DEFINITIONS sanction names ("Alert", "Mute 1h",
"Ban 18h" …) stay hardcoded for now since they're keyed off
server-side action IDs that don't have an existing locale key
convention. Worth a follow-up if needed.
- help.cfh.topic.* keys (CFH topic display names) are already in
ExternalTexts.json and were already read via LocalizeText, so
they didn't need changes.
typecheck + vitest 214/214 + lint:hooks all clean.
Applies the visual language introduced in ModToolsUserView yesterday
to every other ModTools window. The design tokens used consistently:
emerald — present in current room / positive state
sky — online / informational / current selection
zinc — neutral / disabled
amber — warn-level (CFH, alerts, cautions)
rose — danger (bans, releases, abusive)
Files redesigned:
ModToolsRoomView
Identity header with FaDoorOpen, room name + ID, owner-present pill
(emerald/zinc), manual refresh button. Stat strip: user count (sky)
+ clickable owner name (zinc) opening user info. Quick actions
(Visit / Chatlog) in a 2-col grid. Moderate panel collapsed into an
amber-tinted card with the 3 toggles + textarea + two CTAs (Send
Caution=danger, Send Alert=warning). CTAs disabled until a message
is typed AND the room info has loaded.
ModToolsUserModActionView
Numbered 3-step form (CFH topic → sanction → optional message).
Live preview row showing the chosen topic + sanction as tone-coded
pills (amber/sky/rose/orange/fuchsia/zinc by action type). Primary
CTA = Default Sanction, success CTA = Apply Sanction, both
disabled until the required selections are made.
ModToolsUserSendMessageView
Recipient header with FaEnvelope and the username, autofocused
textarea, char counter, single full-width Send button gated on
non-empty message.
ModToolsUserRoomVisitsView
Header strip with entry count badge, three-column grid (time / room
name / visit button), monospace timestamps, hover row highlight,
empty state with FaDoorOpen icon.
ModToolsUserChatlogView / ModToolsChatlogView / CfhChatlogView
Loading state with spinner instead of returning null. Cards grow to
min-w-[460px] max-w-[520px] max-h-[500px] for usable chatlog area.
ChatlogView
Replace Bootstrap-ish striped table with a CSS grid (60px / 120px /
1fr). Room-info separator rendered as a sky card with Visit/Tools
pill buttons. Per-row hover + even-row tint; highlighted rows
(hasHighlighting) get an amber wash. Username is a button opening
user info via existing link event. Empty state with FaCommentDots.
ModToolsTicketsView
Tabs get icons (FaListUl / FaUserCheck / FaCheckSquare) and inline
count badges (amber/sky/zinc) so the moderator sees the queue size
at a glance. ticket bucket filtering memoized off the tickets array.
ModToolsOpenIssuesTabView / MyIssuesTabView / PickedIssuesTabView
Same CSS grid table style. Category renders as a tone-coded pill
(Open=amber, Mine=sky, All picked=zinc). Action buttons get icons
(FaHandPointer Pick, FaTools Handle, FaSignOutAlt Release). Empty
state with FaInbox.
ModToolsIssueInfoView
Card header with category + topic pills. Details rendered as a dl
grid instead of a striped table. Caller / Reported names as inline
link buttons with external-link icon. Chatlog toggle is full-width
secondary. Resolution buttons in a 3-col grid with intent colours
(success=Resolved, dark=Useless, danger=Abusive) + a separate
Release-to-queue button on its own row so it isn't confused with
the resolutions.
No behaviour changes — all composers, message events, parent state
hookups, and sanction validation paths are unchanged. This is purely
a presentation pass. typecheck + vitest 214/214 + lint:hooks all
clean.
Replace ~70 hardcoded English strings across 15 mod-tools files
with LocalizeText() calls using moderation.* keys matching the
existing ExternalTexts convention. Includes mod-tools-external-texts.json
with all required keys for ExternalTexts.json.