i18n: sweep all remaining dynamic prose (oper commands, XLINE/FILTER/DNSBL notices, whois/vhost/knock/dcc/title/reputation/tline/rmode, hash, rename) through trf; +\xNN catalog escape; fr+es now 236 entries each

This commit is contained in:
Jean Chevronnet 2026-08-25 14:30:29 +00:00
parent ef96bcbd06
commit 9b51db07f5
No known key found for this signature in database
GPG key ID: 439666D63A9477E4
32 changed files with 295 additions and 128 deletions

View file

@ -66,12 +66,10 @@ impl Command for Tban {
(u.nick.clone(), u.prefix())
};
if s.channels[&key].bans.iter().any(|b| b.mask == mask) {
let m = s.trf("{0} is already banned on {1}", &[mask.as_str(), chan.as_str()]);
s.send(
uid,
format!(
":{} NOTICE {nick} :{mask} is already banned on {chan}",
s.name
),
format!(":{} NOTICE {nick} :{m}", s.name),
);
return CmdResult::Fail;
}
@ -127,12 +125,10 @@ impl Command for Knock {
.cloned()
.unwrap_or_else(|| "requesting an invite".to_string());
let who = s.users[&uid].prefix();
let m = s.trf("[Knock] {0} is knocking: {1}", &[who.as_str(), reason.as_str()]);
s.to_channel(
&key,
&format!(
":{} NOTICE {chan} :[Knock] {who} is knocking: {reason}",
s.name
),
&format!(":{} NOTICE {chan} :{m}", s.name),
None,
);
s.numeric(
@ -314,9 +310,10 @@ impl Command for Invite {
let maxinv = s.conf_num("maxinvites", 100usize);
if s.channels[&key].invites.len() >= maxinv && !s.channels[&key].invites.contains(&tuid) {
let nick = s.users.get(&uid).map(|u| u.nick.clone()).unwrap_or_default();
let m = s.trf("Channel invite list is full", &[]);
s.send(
uid,
format!(":{} NOTICE {nick} :{chan} :Channel invite list is full", s.name),
format!(":{} NOTICE {nick} :{chan} :{m}", s.name),
);
return CmdResult::Fail;
}
@ -408,12 +405,10 @@ impl Command for Uninvite {
format!(":{} NOTICE {nick} :{who} {word} {chan}", s.name),
);
if removed {
let m = s.trf("Your invite to {0} was revoked", &[chan.as_str()]);
s.send(
tuid,
format!(
":{} NOTICE {who} :Your invite to {chan} was revoked",
s.name
),
format!(":{} NOTICE {who} :{m}", s.name),
);
}
CmdResult::Ok
@ -563,7 +558,8 @@ impl Command for Rename {
s.fail(uid, "RENAME", "CANNOT_RENAME", "The channel cannot be renamed.");
return CmdResult::Fail;
}
s.snotice_c('a', &format!("{oldname} renamed to {new} by {prefix}"));
let m = s.trf("{0} renamed to {1} by {2}", &[oldname.as_str(), new.as_str(), prefix.as_str()]);
s.snotice_c('a', &m);
s.propagate_rename(&uuid, &oldname, new, &reason, None);
CmdResult::Ok
}

View file

@ -245,7 +245,9 @@ impl Command for Admin {
RPL_ADMINME,
&format!("{} :Administrative info", s.name),
);
s.numeric(uid, RPL_ADMINLOC1, &format!(":{} IRC network", s.network));
let network = s.network.clone();
let m = s.trf("{0} IRC network", &[network.as_str()]);
s.numeric(uid, RPL_ADMINLOC1, &format!(":{m}"));
s.numeric(
uid,
RPL_ADMINLOC2,

View file

@ -53,12 +53,10 @@ impl Command for SslInfo {
};
let tls = if secure { "yes" } else { "no" };
let fp = certfp.unwrap_or_else(|| "none".to_string());
let m = s.trf("SSLINFO {0}: TLS={1} certfp={2}", &[nick.as_str(), tls, fp.as_str()]);
s.send(
uid,
format!(
":{} NOTICE {asker} :SSLINFO {nick}: TLS={tls} certfp={fp}",
s.name
),
format!(":{} NOTICE {asker} :{m}", s.name),
);
CmdResult::Ok
}
@ -437,9 +435,10 @@ impl Command for Whois {
// +W showwhois — tell the target that someone looked them up
if showwhois && !is_self {
let by = s.users.get(&uid).map(|u| u.prefix()).unwrap_or_default();
let m = s.trf("{0} did a /WHOIS on you", &[by.as_str()]);
s.send(
tuid,
format!(":{} NOTICE {nick} :*** {by} did a /WHOIS on you", s.name),
format!(":{} NOTICE {nick} :*** {m}", s.name),
);
}
s.numeric(uid, RPL_ENDOFWHOIS, &format!("{nick} :End of /WHOIS list"));

View file

@ -543,12 +543,10 @@ pub(crate) fn deliver(s: &mut Server, uid: Uid, params: &[String], notice: bool)
.map(|u| u.nick.clone())
.unwrap_or_default(),
);
let m = s.trf("Cannot message {0}: a TLS connection is required (+z)", &[tn.as_str()]);
s.send(
uid,
format!(
":{} NOTICE {sn} :Cannot message {tn}: a TLS connection is required (+z)",
s.name
),
format!(":{} NOTICE {sn} :{m}", s.name),
);
}
return CmdResult::Fail;

View file

@ -398,14 +398,12 @@ impl Command for GlobOps {
.filter(|(_, u)| u.flags.oper)
.map(|(&u, _)| u)
.collect();
let m = s.trf("GLOBOPS from {0}: {1}", &[from.as_str(), params[0].as_str()]);
for o in opers {
let nick = s.users.get(&o).map(|u| u.nick.clone()).unwrap_or_default();
s.send(
o,
format!(
":{} NOTICE {nick} :*** GLOBOPS from {from}: {}",
s.name, params[0]
),
format!(":{} NOTICE {nick} :*** {m}", s.name),
);
}
CmdResult::Ok
@ -731,9 +729,10 @@ fn do_xline(s: &mut Server, uid: Uid, params: &[String], kind: XKind) -> CmdResu
if s.remove_xline(kind, &mask, &nick) {
s.propagate_delline(kind.tag(), &mask);
} else {
let m = s.trf("{0}-line not found: {1}", &[kind.tag(), mask.as_str()]);
s.send(
uid,
format!(":{} NOTICE {nick} :{}-line not found: {mask}", s.name, kind.tag()),
format!(":{} NOTICE {nick} :{m}", s.name),
);
}
return CmdResult::Ok;
@ -878,17 +877,20 @@ impl Command for Rline {
if s.remove_xline(XKind::Rline, &pattern, &nick) {
s.propagate_delline("R", &pattern);
} else {
let m = s.trf("R-line not found: {0}", &[pattern.as_str()]);
s.send(
uid,
format!(":{} NOTICE {nick} :R-line not found: {pattern}", s.name),
format!(":{} NOTICE {nick} :{m}", s.name),
);
}
return CmdResult::Ok;
}
if let Err(e) = crate::regex::Regex::new(&pattern) {
let e = e.to_string();
let m = s.trf("Invalid RLINE regex: {0}", &[e.as_str()]);
s.send(
uid,
format!(":{} NOTICE {nick} :Invalid RLINE regex: {e}", s.name),
format!(":{} NOTICE {nick} :{m}", s.name),
);
return CmdResult::Fail;
}
@ -952,7 +954,8 @@ impl Command for NickLock {
u.flags.nick_locked = true;
}
let by = oper_nick(s, uid);
s.snotice_c('v', &format!("{by} used NICKLOCK on {newnick}"));
let m = s.trf("{0} used NICKLOCK on {1}", &[by.as_str(), newnick.as_str()]);
s.snotice_c('v', &m);
CmdResult::Ok
}
}
@ -977,7 +980,8 @@ impl Command for NickUnlock {
u.flags.nick_locked = false;
}
let by = oper_nick(s, uid);
s.snotice_c('v', &format!("{by} used NICKUNLOCK on {}", params[0]));
let m = s.trf("{0} used NICKUNLOCK on {1}", &[by.as_str(), params[0].as_str()]);
s.snotice_c('v', &m);
CmdResult::Ok
}
}
@ -1049,7 +1053,8 @@ impl Command for Squit {
return CmdResult::Fail;
};
let by = oper_nick(s, uid);
s.snotice_c('l', &format!("{by} used SQUIT on {name}"));
let m = s.trf("{0} used SQUIT on {1}", &[by.as_str(), name.as_str()]);
s.snotice_c('l', &m);
s.close_link(via, &format!("SQUIT from {by}"));
CmdResult::Ok
}
@ -1209,7 +1214,9 @@ impl Command for SaMode {
let r = apply_mode(s, uid, params);
s.mode_sudo = false;
let by = oper_nick(s, uid);
s.snotice_c('v', &format!("{by} used SAMODE: {}", params.join(" ")));
let joined = params.join(" ");
let m = s.trf("{0} used SAMODE: {1}", &[by.as_str(), joined.as_str()]);
s.snotice_c('v', &m);
r
}
}
@ -1248,7 +1255,8 @@ impl Command for SaTopic {
s.to_channel(&key, &format!(":{prefix} TOPIC {chan} :{text}"), None);
s.propagate_topic(uid, chan, &text);
let by = oper_nick(s, uid);
s.snotice_c('v', &format!("{by} used SATOPIC on {chan}"));
let m = s.trf("{0} used SATOPIC on {1}", &[by.as_str(), chan.as_str()]);
s.snotice_c('v', &m);
CmdResult::Ok
}
}
@ -1313,7 +1321,8 @@ impl Command for SaKick {
s.events
.push_back(Hook::Part(tuid, key, "kicked".to_string()));
let by = oper_nick(s, uid);
s.snotice_c('v', &format!("{by} used SAKICK on {victim} in {chan}"));
let m = s.trf("{0} used SAKICK on {1} in {2}", &[by.as_str(), victim.as_str(), chan.as_str()]);
s.snotice_c('v', &m);
CmdResult::Ok
}
}
@ -1343,7 +1352,8 @@ impl Command for SaQuit {
s.send(tuid, format!("ERROR :Closing link: (SAQUIT: {reason})"));
s.remove_user(tuid, &format!("Quit: {reason}"));
let by = oper_nick(s, uid);
s.snotice_c('v', &format!("{by} used SAQUIT on {}: {reason}", params[0]));
let m = s.trf("{0} used SAQUIT on {1}: {2}", &[by.as_str(), params[0].as_str(), reason.as_str()]);
s.snotice_c('v', &m);
CmdResult::Ok
}
}
@ -1379,7 +1389,8 @@ impl Command for ChgName {
}
s.notify_peers(t, &line, |c| c.setname);
let by = oper_nick(s, uid);
s.snotice_c('v', &format!("{by} used CHGNAME on {}: {realname}", params[0]));
let m = s.trf("{0} used CHGNAME on {1}: {2}", &[by.as_str(), params[0].as_str(), realname.as_str()]);
s.snotice_c('v', &m);
CmdResult::Ok
}
}
@ -1436,7 +1447,8 @@ impl Command for ClearChan {
}
s.channels.retain(|_, c| c.keep_alive());
let by = oper_nick(s, uid);
s.snotice_c('v', &format!("{by} used CLEARCHAN on {chan}"));
let m = s.trf("{0} used CLEARCHAN on {1}", &[by.as_str(), chan.as_str()]);
s.snotice_c('v', &m);
CmdResult::Ok
}
}
@ -1553,7 +1565,8 @@ impl Command for SwhoisCmd {
}
}
let by = oper_nick(s, uid);
s.snotice_c('v', &format!("{by} used SWHOIS on {}: {text}", params[0]));
let m = s.trf("{0} used SWHOIS on {1}: {2}", &[by.as_str(), params[0].as_str(), text.as_str()]);
s.snotice_c('v', &m);
CmdResult::Ok
}
}

View file

@ -60,9 +60,10 @@ impl Command for Vhost {
match host {
Some(h) => {
s.change_host_ident(uid, None, Some(&h));
let m = s.trf("Your vhost is now {0}", &[h.as_str()]);
s.send(
uid,
format!(":{} NOTICE {nick} :Your vhost is now {h}", s.name),
format!(":{} NOTICE {nick} :{m}", s.name),
);
}
None => {

View file

@ -351,7 +351,9 @@ impl Command for Signore {
.map(|u| u.signore.len() >= max && !u.signore.contains(&mask))
.unwrap_or(true);
if full {
s.send(uid, format!(":{sn} NOTICE {nick} :Your SIGNORE list is full ({max} max)."));
let maxs = max.to_string();
let m = s.trf("Your SIGNORE list is full ({0} max).", &[maxs.as_str()]);
s.send(uid, format!(":{sn} NOTICE {nick} :{m}"));
return CmdResult::Fail;
}
if let Some(u) = s.users.get_mut(&uid) {
@ -359,12 +361,14 @@ impl Command for Signore {
u.signore.push(mask.clone());
}
}
s.send(uid, format!(":{sn} NOTICE {nick} :SIGNORE \x02{mask}\x02 added — you and they can no longer see each other's messages."));
let m = s.trf("SIGNORE \x02{0}\x02 added — you and they can no longer see each other's messages.", &[mask.as_str()]);
s.send(uid, format!(":{sn} NOTICE {nick} :{m}"));
} else {
if let Some(u) = s.users.get_mut(&uid) {
u.signore.retain(|x| x != &mask);
}
s.send(uid, format!(":{sn} NOTICE {nick} :SIGNORE \x02{mask}\x02 removed."));
let m = s.trf("SIGNORE \x02{0}\x02 removed.", &[mask.as_str()]);
s.send(uid, format!(":{sn} NOTICE {nick} :{m}"));
}
// Persist the change to the user's services account (no-op if not logged in).
s.push_signore_to_services(uid);

View file

@ -231,6 +231,20 @@ fn read_quoted(s: &str) -> Option<(String, &str)> {
't' => out.push('\t'),
'"' => out.push('"'),
'\\' => out.push('\\'),
// \xNN — a raw byte, so IRC formatting controls (e.g. \x02 bold) in a
// msgid match the literal byte the source `"\x02"` compiles to.
'x' => {
let (h1, h2) = (chars.next()?.1, chars.next()?.1);
match u8::from_str_radix(&format!("{h1}{h2}"), 16) {
Ok(b) => out.push(b as char),
Err(_) => {
out.push('\\');
out.push('x');
out.push(h1);
out.push(h2);
}
}
}
other => {
out.push('\\');
out.push(other);

View file

@ -175,8 +175,11 @@ impl Ircd {
busy.store(0, Ordering::Relaxed);
let ms = start.elapsed().as_millis() as u64;
if slow_ms != 0 && ms >= slow_ms {
self.server
.snotice(&format!("slow event: a command took {ms}ms on the core thread"));
let ms_s = ms.to_string();
let m = self
.server
.trf("slow event: a command took {0}ms on the core thread", &[ms_s.as_str()]);
self.server.snotice(&m);
}
}
}
@ -260,11 +263,16 @@ impl Ircd {
.map(|u| u.nick.clone())
.unwrap_or_default();
let line = match hash {
Some(h) => format!(
":{} NOTICE {nick} :{algo} hashed password: {h}",
self.server.name
),
None => format!(":{} NOTICE {nick} :Could not hash with '{algo}'", self.server.name),
Some(h) => {
let m = self
.server
.trf("{0} hashed password: {1}", &[algo.as_str(), h.as_str()]);
format!(":{} NOTICE {nick} :{m}", self.server.name)
}
None => {
let m = self.server.trf("Could not hash with '{0}'", &[algo.as_str()]);
format!(":{} NOTICE {nick} :{m}", self.server.name)
}
};
self.server.send(uid, line);
}

View file

@ -340,7 +340,8 @@ impl Server {
}
fn reject_link(&mut self, uid: Uid, why: &str) {
self.link_out(uid, format!("ERROR :Link denied: {why}"));
let m = self.trf("Link denied: {0}", &[why]);
self.link_out(uid, format!("ERROR :{m}"));
eprintln!("[link] rejected {uid}: {why}");
self.close_link(uid, why);
}

View file

@ -726,7 +726,8 @@ impl ChanMode for ListMode {
for (m, setter, ts) in rows {
s.numeric(uid, entry_num, &format!("{chan} {m} {setter} {ts}"));
}
s.numeric(uid, end_num, &format!("{chan} :End of channel {noun}"));
let m = s.trf("End of channel {0}", &[noun]);
s.numeric(uid, end_num, &format!("{chan} :{m}"));
return Applied::No;
};
// autoop (+w) embeds a status prefix to grant on join, applied under server

View file

@ -285,12 +285,14 @@ impl Module for AntiMixedUtf8 {
// Notify the sender even for punitive actions: the writer flushes queued
// lines before a disconnect.
let block_msg = srv.amu.block_msg.clone();
let m = srv.trf(
"{0} (Flagged by the spam filter; network operators have been notified.)",
&[block_msg.as_str()],
);
srv.send(
uid,
format!(
":{} NOTICE {nick} :*** {} (Flagged by the spam filter; network operators have been notified.)",
srv.name, srv.amu.block_msg
),
format!(":{} NOTICE {nick} :*** {m}", srv.name),
);
let action = srv.amu.action.to_ascii_lowercase();

View file

@ -90,7 +90,8 @@ impl Module for BlockAmsg {
let notify_opers = matches!(action.as_str(), "killopers" | "noticeopers" | "zlineopers");
if notify_opers {
let mask = srv.users.get(&uid).map(|u| u.prefix()).unwrap_or_default();
srv.snotice(&format!("User {mask} had an /amsg or /ame blocked"));
let m = srv.trf("User {0} had an /amsg or /ame blocked", &[mask.as_str()]);
srv.snotice(&m);
}
let reason = "Attempted to global message (/amsg or /ame)";
match action.as_str() {

View file

@ -158,9 +158,10 @@ impl Command for VerifyChallenge {
.unwrap_or_default();
let fail = |s: &mut Server, why: &str| {
let m = s.trf("Cloudflare Challenge: {0}", &[why]);
s.send(
uid,
format!(":{} NOTICE {nick} :*** Cloudflare Challenge: {why}", s.name),
format!(":{} NOTICE {nick} :*** {m}", s.name),
);
CmdResult::Fail
};

View file

@ -289,7 +289,9 @@ fn pick(
if let Some(max) = c.limit {
if class_count(s, &c.name, uid) >= max {
if c.maxconnwarn {
s.snotice_c('c', &format!("connect class {} is full ({max})", c.name));
let max_s = max.to_string();
let m = s.trf("connect class {0} is full ({1})", &[c.name.as_str(), max_s.as_str()]);
s.snotice_c('c', &m);
}
continue; // full — try the next class
}
@ -355,7 +357,11 @@ pub fn assign(s: &mut Server, uid: Uid) -> Option<String> {
};
let warn = |s: &Server, why: &str| {
if class.maxconnwarn {
s.snotice_c('c', &format!("connect class {} refused {ip}: {why}", class.name));
let m = s.trf(
"connect class {0} refused {1}: {2}",
&[class.name.as_str(), ip.as_str(), why],
);
s.snotice_c('c', &m);
}
};
if let Some(max) = class.localmax {

View file

@ -45,9 +45,10 @@ pub fn grant(s: &mut Server, uid: Uid, title: &str, vhost: &str) {
s.change_host_ident(uid, None, Some(vhost));
}
let nick = nick(s, uid);
let m = s.trf("TITLE: you are now known as \"{0}\".", &[title]);
s.send(
uid,
format!(":{} NOTICE {nick} :*** TITLE: you are now known as \"{title}\".", s.name),
format!(":{} NOTICE {nick} :*** {m}", s.name),
);
}

View file

@ -117,19 +117,21 @@ impl Module for DccAllow {
return ModResult::Passthru;
}
let tnick = s.users.get(&tuid).map(|u| u.nick.clone()).unwrap_or_default();
let m1 = s.trf(
"Your DCC to {0} was blocked; they must /DCCALLOW +{1} first.",
&[tnick.as_str(), sender.as_str()],
);
s.send(
uid,
format!(
":{} NOTICE {sender} :*** Your DCC to {tnick} was blocked; they must /DCCALLOW +{sender} first.",
s.name
),
format!(":{} NOTICE {sender} :*** {m1}", s.name),
);
let m2 = s.trf(
"{0} tried to send you {1} — blocked. /DCCALLOW +{2} to allow it, then ask them to resend.",
&[sender.as_str(), what.as_str(), sender.as_str()],
);
s.send(
tuid,
format!(
":{} NOTICE {tnick} :*** {sender} tried to send you {what} — blocked. /DCCALLOW +{sender} to allow it, then ask them to resend.",
s.name
),
format!(":{} NOTICE {tnick} :*** {m2}", s.name),
);
ModResult::Deny
}

View file

@ -185,14 +185,20 @@ impl Command for FilterCmd {
let filter = match SpamFilter::new(pattern.clone(), engine.clone(), action.clone(), duration, reason) {
Ok(f) => f,
Err(e) => {
s.send(uid, format!(":{} NOTICE {nick} :FILTER rejected ({e})", s.name));
let e_s = e.to_string();
let m = s.trf("FILTER rejected ({0})", &[e_s.as_str()]);
s.send(uid, format!(":{} NOTICE {nick} :{m}", s.name));
return CmdResult::Fail;
}
};
let f = s.ext.get_or_insert_with::<Filters>(Filters::default);
f.0.retain(|r| r.pattern != pattern);
f.0.push(filter);
s.snotice_c('f', &format!("{nick} added FILTER {pattern} (engine={engine} action={action})"));
let m = s.trf(
"{0} added FILTER {1} (engine={2} action={3})",
&[nick.as_str(), pattern.as_str(), engine.as_str(), action.as_str()],
);
s.snotice_c('f', &m);
}
}
}

View file

@ -28,7 +28,9 @@ impl Command for GlobopsCmd {
return CmdResult::Fail;
}
let nick = s.users.get(&uid).map(|u| u.nick.clone()).unwrap_or_default();
s.snotice_c('g', &format!("GLOBOPS from {nick}: {}", params.join(" ")));
let body = params.join(" ");
let m = s.trf("GLOBOPS from {0}: {1}", &[nick.as_str(), body.as_str()]);
s.snotice_c('g', &m);
CmdResult::Ok
}
}

View file

@ -102,7 +102,8 @@ pub fn apply(s: &mut Server, uid: Uid, type_id: Option<&str>) {
return;
};
let Some(r) = with_resolved(s, |m| m.get(&id).cloned()) else {
s.snotice_c('o', &format!("oper type '{id}' is not defined — granting full access"));
let m = s.trf("oper type '{0}' is not defined — granting full access", &[id.as_str()]);
s.snotice_c('o', &m);
return;
};
if !r.modes.is_empty() {

View file

@ -199,23 +199,16 @@ impl Command for MkPasswd {
}
match make(&algo, &pass) {
Some(hashed) => {
s.send(
uid,
format!(
":{} NOTICE {nick} :{algo} hashed password: {hashed}",
s.name
),
);
let m = s.trf("{0} hashed password: {1}", &[algo.as_str(), hashed.as_str()]);
s.send(uid, format!(":{} NOTICE {nick} :{m}", s.name));
CmdResult::Ok
}
None => {
s.send(
uid,
format!(
":{} NOTICE {nick} :Unknown hash '{algo}' (try md5, sha1, sha256, sha512, pbkdf2, bcrypt)",
s.name
),
let m = s.trf(
"Unknown hash '{0}' (try md5, sha1, sha256, sha512, pbkdf2, bcrypt)",
&[algo.as_str()],
);
s.send(uid, format!(":{} NOTICE {nick} :{m}", s.name));
CmdResult::Fail
}
}

View file

@ -289,13 +289,13 @@ impl Command for ReputationCmd {
e.score = val.min(cap);
e.last_seen = n;
save(s);
s.send(
uid,
format!(
":{} NOTICE {anick} :REPUTATION {nick} ({k}) set to {val}",
s.name
),
let ks = k.to_string();
let vals = val.to_string();
let m = s.trf(
"REPUTATION {0} ({1}) set to {2}",
&[nick.as_str(), ks.as_str(), vals.as_str()],
);
s.send(uid, format!(":{} NOTICE {anick} :{m}", s.name));
} else {
let score = score_of(s, tuid);
s.send(

View file

@ -99,13 +99,13 @@ impl Command for RMode {
.map(|u| u.nick.clone())
.unwrap_or_default();
let plural = if removed == 1 { "y" } else { "ies" };
s.send(
uid,
format!(
":{} NOTICE {nick} :RMODE: removed {removed} +{mode} entr{plural} from {chan}",
s.name
),
let removeds = removed.to_string();
let modes = mode.to_string();
let m = s.trf(
"RMODE: removed {0} +{1} entr{2} from {3}",
&[removeds.as_str(), modes.as_str(), plural, chan.as_str()],
);
s.send(uid, format!(":{} NOTICE {nick} :{m}", s.name));
CmdResult::Ok
}
}

View file

@ -61,7 +61,8 @@ pub fn handle(s: &mut Server, action: &str, params: &str) -> Result<String, RpcE
std::thread::spawn(move || {
crate::socketengine::connect_link(&addr, tx, counter, max_line)
});
s.snotice_c('l', &format!("RPC initiated a link to {}", b.name));
let m = s.trf("RPC initiated a link to {0}", &[b.name.as_str()]);
s.snotice_c('l', &m);
Ok(obj(&[("result", "true".into())]))
}
"disconnect" => {

View file

@ -221,13 +221,8 @@ impl Command for SecGroupsCmd {
.map(|u| u.nick.clone())
.unwrap_or_default(),
);
s.send(
uid,
format!(
":{} NOTICE {anick} :{tnick} is in security groups: {list}",
s.name
),
);
let m = s.trf("{0} is in security groups: {1}", &[tnick.as_str(), list.as_str()]);
s.send(uid, format!(":{} NOTICE {anick} :{m}", s.name));
CmdResult::Ok
}
}

View file

@ -36,10 +36,10 @@ pub fn maybe_show(s: &mut Server, uid: Uid, cmd: &str) -> bool {
s.send(uid, format!(":{} NOTICE {nick} :{line}", s.name));
}
}
None => s.send(
uid,
format!(":{} NOTICE {nick} :*** {cmd}: file not available.", s.name),
),
None => {
let m = s.trf("{0}: file not available.", &[cmd]);
s.send(uid, format!(":{} NOTICE {nick} :*** {m}", s.name));
}
}
true
}

View file

@ -97,13 +97,13 @@ impl Module for SolveMsg {
answer: Some(ans),
});
}
s.send(
uid,
format!(
":{} NOTICE {nick} :*** To cut spam, answer this to send your message — what is {a} {sym} {b} ?",
s.name
),
let as_ = a.to_string();
let bs = b.to_string();
let m = s.trf(
"To cut spam, answer this to send your message — what is {0} {1} {2} ?",
&[as_.as_str(), sym, bs.as_str()],
);
s.send(uid, format!(":{} NOTICE {nick} :*** {m}", s.name));
ModResult::Deny
}
}

View file

@ -48,13 +48,14 @@ impl Command for TLine {
.get(&uid)
.map(|u| u.nick.clone())
.unwrap_or_default();
s.send(
uid,
format!(
":{} NOTICE {nick} :*** TLINE: {mask} matches {matched} of {total} local users ({pct}%)",
s.name
),
let matcheds = matched.to_string();
let totals = total.to_string();
let pcts = pct.to_string();
let m = s.trf(
"TLINE: {0} matches {1} of {2} local users ({3}%)",
&[mask.as_str(), matcheds.as_str(), totals.as_str(), pcts.as_str()],
);
s.send(uid, format!(":{} NOTICE {nick} :*** {m}", s.name));
CmdResult::Ok
}
}

View file

@ -438,7 +438,8 @@ impl Server {
self.send(t, line.clone());
}
if self.conf_bool("seenicks", false) {
self.snotice_c('n', &format!("{old} is now known as {newnick}"));
let m = self.trf("{0} is now known as {1}", &[old.as_str(), newnick]);
self.snotice_c('n', &m);
}
// WATCH/MONITOR: the old nick is now gone, the new one is here
self.watch_notify_offline(&old);

View file

@ -304,7 +304,8 @@ impl Server {
crate::server::long_date(expires)
)
};
self.snotice_c('x', &format!("XLINE: {setter} added a {detail}: {reason}"));
let m = self.trf("XLINE: {0} added a {1}: {2}", &[setter, detail.as_str(), reason]);
self.snotice_c('x', &m);
self.save_xlines();
self.enforce_xlines();
}
@ -335,7 +336,8 @@ impl Server {
Some(e) if e != 0 => format!("timed {tag}-line on {mask} (already expired)"),
_ => format!("permanent {tag}-line on {mask}"),
};
self.snotice_c('x', &format!("XLINE: {remover} removed a {detail}"));
let m = self.trf("XLINE: {0} removed a {1}", &[remover, detail.as_str()]);
self.snotice_c('x', &m);
self.save_xlines();
}
removed
@ -383,7 +385,8 @@ impl Server {
}
self.xlines.retain(|x| x.expires == 0 || x.expires > n);
for (kind, mask) in &expired {
self.snotice_c('x', &format!("XLINE: {}-line on {mask} expired", kind.tag()));
let m = self.trf("XLINE: {0}-line on {1} expired", &[kind.tag(), mask.as_str()]);
self.snotice_c('x', &m);
}
self.save_xlines(); // an expiry changed the set — persist it
}