i18n: localize the client-facing Closing-link ERROR wrapper via trf (fr, es); QUIT-broadcast reasons stay canonical for S2S

This commit is contained in:
Jean Chevronnet 2026-08-25 14:35:13 +00:00
parent 9b51db07f5
commit 04671733d2
No known key found for this signature in database
GPG key ID: 439666D63A9477E4
12 changed files with 54 additions and 31 deletions

View file

@ -88,6 +88,16 @@
"XLINE: {0} removed a {1}" = "XLINE: {0} eliminó un {1}" "XLINE: {0} removed a {1}" = "XLINE: {0} eliminó un {1}"
"XLINE: {0}-line on {1} expired" = "XLINE: la {0}-line sobre {1} ha expirado" "XLINE: {0}-line on {1} expired" = "XLINE: la {0}-line sobre {1} ha expirado"
# --- cierre de enlace (ERROR del lado del cliente al desconectar) ---
"Closing link: ({0})" = "Cerrando enlace: ({0})"
"Closing link: (R-lined: {0})" = "Cerrando enlace: (R-lined: {0})"
"Closing link: (SAQUIT: {0})" = "Cerrando enlace: (SAQUIT: {0})"
"Closing link (registration refused)" = "Cerrando enlace (registro rechazado)"
"Closing link: (Too many connections from your IP)" = "Cerrando enlace: (Demasiadas conexiones desde tu IP)"
"Closing link: (Excess flood)" = "Cerrando enlace: (Exceso de flood)"
"Closing link (dropped)" = "Cerrando enlace (descartado)"
"Closing link (incorrect ping reply)" = "Cerrando enlace (respuesta de ping incorrecta)"
# --- avisos / desafíos --- # --- avisos / desafíos ---
"*** Cloudflare Challenge: verification successful — you may continue." = "*** Desafío de Cloudflare: verificación exitosa — puedes continuar." "*** Cloudflare Challenge: verification successful — you may continue." = "*** Desafío de Cloudflare: verificación exitosa — puedes continuar."
"*** Correct — you may now message freely; please resend your message." = "*** Correcto — ya puedes enviar mensajes libremente; por favor reenvía tu mensaje." "*** Correct — you may now message freely; please resend your message." = "*** Correcto — ya puedes enviar mensajes libremente; por favor reenvía tu mensaje."

View file

@ -88,6 +88,16 @@
"XLINE: {0} removed a {1}" = "XLINE : {0} a supprimé un {1}" "XLINE: {0} removed a {1}" = "XLINE : {0} a supprimé un {1}"
"XLINE: {0}-line on {1} expired" = "XLINE : la {0}-line sur {1} a expiré" "XLINE: {0}-line on {1} expired" = "XLINE : la {0}-line sur {1} a expiré"
# --- fermeture de lien (ERROR côté client au moment de la déconnexion) ---
"Closing link: ({0})" = "Fermeture du lien : ({0})"
"Closing link: (R-lined: {0})" = "Fermeture du lien : (R-lined : {0})"
"Closing link: (SAQUIT: {0})" = "Fermeture du lien : (SAQUIT : {0})"
"Closing link (registration refused)" = "Fermeture du lien (enregistrement refusé)"
"Closing link: (Too many connections from your IP)" = "Fermeture du lien : (Trop de connexions depuis votre IP)"
"Closing link: (Excess flood)" = "Fermeture du lien : (Excès de flood)"
"Closing link (dropped)" = "Fermeture du lien (abandonné)"
"Closing link (incorrect ping reply)" = "Fermeture du lien (réponse au ping incorrecte)"
# --- notices / défis --- # --- notices / défis ---
"*** Cloudflare Challenge: verification successful — you may continue." = "*** Défi Cloudflare : vérification réussie — vous pouvez continuer." "*** Cloudflare Challenge: verification successful — you may continue." = "*** Défi Cloudflare : vérification réussie — vous pouvez continuer."
"*** Correct — you may now message freely; please resend your message." = "*** Correct — vous pouvez maintenant envoyer des messages librement ; veuillez renvoyer votre message." "*** Correct — you may now message freely; please resend your message." = "*** Correct — vous pouvez maintenant envoyer des messages librement ; veuillez renvoyer votre message."

View file

@ -1349,7 +1349,8 @@ impl Command for SaQuit {
.cloned() .cloned()
.unwrap_or_else(|| "Services forced quit".to_string()); .unwrap_or_else(|| "Services forced quit".to_string());
if s.uid_servprotected(tuid) { s.numeric(uid, ERR_NOPRIVILEGES, ":Cannot use an SA command on a network service"); return CmdResult::Fail; } if s.uid_servprotected(tuid) { s.numeric(uid, ERR_NOPRIVILEGES, ":Cannot use an SA command on a network service"); return CmdResult::Fail; }
s.send(tuid, format!("ERROR :Closing link: (SAQUIT: {reason})")); let m = s.trf("Closing link: (SAQUIT: {0})", &[reason.as_str()]);
s.send(tuid, format!("ERROR :{m}"));
s.remove_user(tuid, &format!("Quit: {reason}")); s.remove_user(tuid, &format!("Quit: {reason}"));
let by = oper_nick(s, uid); let by = oper_nick(s, uid);
let m = s.trf("{0} used SAQUIT on {1}: {2}", &[by.as_str(), params[0].as_str(), reason.as_str()]); let m = s.trf("{0} used SAQUIT on {1}: {2}", &[by.as_str(), params[0].as_str(), reason.as_str()]);

View file

@ -572,7 +572,8 @@ impl Command for Nick {
}); });
if let Some((nk, id, ho, ip, rn)) = info { if let Some((nk, id, ho, ip, rn)) = info {
if let Some(reason) = s.matched_rline(&nk, &id, &ho, &ip, &rn) { if let Some(reason) = s.matched_rline(&nk, &id, &ho, &ip, &rn) {
s.send(uid, format!("ERROR :Closing link: ({reason})")); let m = s.trf("Closing link: ({0})", &[reason.as_str()]);
s.send(uid, format!("ERROR :{m}"));
s.remove_user(uid, &reason); s.remove_user(uid, &reason);
} }
} }

View file

@ -569,10 +569,8 @@ impl Ircd {
for m in &mut self.modules { for m in &mut self.modules {
match m.on_user_register(&mut self.server, uid) { match m.on_user_register(&mut self.server, uid) {
ModResult::Deny => { ModResult::Deny => {
self.server.send( let m = self.server.trf("Closing link (registration refused)", &[]);
uid, self.server.send(uid, format!("ERROR :{m}"));
"ERROR :Closing link (registration refused)".to_string(),
);
self.server.remove_user(uid, "Registration refused"); self.server.remove_user(uid, "Registration refused");
return; return;
} }
@ -588,15 +586,15 @@ impl Ircd {
(u.ident.clone(), u.host.clone(), u.addr.ip().to_string()) (u.ident.clone(), u.host.clone(), u.addr.ip().to_string())
}; };
if let Some(reason) = self.server.matched_xline(&ident, &host, &ip) { if let Some(reason) = self.server.matched_xline(&ident, &host, &ip) {
self.server let m = self.server.trf("Closing link: ({0})", &[reason.as_str()]);
.send(uid, format!("ERROR :Closing link: ({reason})")); self.server.send(uid, format!("ERROR :{m}"));
self.server.remove_user(uid, &reason); self.server.remove_user(uid, &reason);
return; return;
} }
// ident: apply a confirmed username (dropping `~`) and enforce requireident // ident: apply a confirmed username (dropping `~`) and enforce requireident
if let Some(reason) = crate::modules::ident::finalize(&mut self.server, uid) { if let Some(reason) = crate::modules::ident::finalize(&mut self.server, uid) {
self.server let m = self.server.trf("Closing link: ({0})", &[reason.as_str()]);
.send(uid, format!("ERROR :Closing link: ({reason})")); self.server.send(uid, format!("ERROR :{m}"));
self.server.remove_user(uid, &reason); self.server.remove_user(uid, &reason);
return; return;
} }
@ -613,8 +611,8 @@ impl Ircd {
) )
}; };
if let Some(reason) = rl { if let Some(reason) = rl {
self.server let m = self.server.trf("Closing link: ({0})", &[reason.as_str()]);
.send(uid, format!("ERROR :Closing link: ({reason})")); self.server.send(uid, format!("ERROR :{m}"));
self.server.remove_user(uid, &reason); self.server.remove_user(uid, &reason);
return; return;
} }
@ -636,8 +634,8 @@ impl Ircd {
fn reject_link(&mut self, uid: Uid, reason: &str) { fn reject_link(&mut self, uid: Uid, reason: &str) {
self.server self.server
.numeric(uid, ERR_PASSWDMISMATCH, &format!(":{reason}")); .numeric(uid, ERR_PASSWDMISMATCH, &format!(":{reason}"));
self.server let m = self.server.trf("Closing link: ({0})", &[reason]);
.send(uid, format!("ERROR :Closing link: ({reason})")); self.server.send(uid, format!("ERROR :{m}"));
self.server.remove_user(uid, reason); self.server.remove_user(uid, reason);
} }
@ -705,8 +703,8 @@ impl Ircd {
} else { } else {
"Registration timeout" "Registration timeout"
}; };
self.server let m = self.server.trf("Closing link: ({0})", &[reason]);
.send(uid, format!("ERROR :Closing link: ({reason})")); self.server.send(uid, format!("ERROR :{m}"));
self.quit_user(uid, reason); self.quit_user(uid, reason);
} }
// republish gauges (the core owns this state; the scrape thread only reads) // republish gauges (the core owns this state; the scrape thread only reads)

View file

@ -55,7 +55,8 @@ impl Module for AutoDrop {
.get::<DropCache>() .get::<DropCache>()
.is_some_and(|c| c.cmds.contains(&cmd.to_ascii_uppercase())); .is_some_and(|c| c.cmds.contains(&cmd.to_ascii_uppercase()));
if hit { if hit {
s.send(uid, "ERROR :Closing link (dropped)".to_string()); let m = s.trf("Closing link (dropped)", &[]);
s.send(uid, format!("ERROR :{m}"));
s.remove_user(uid, "Autodropped"); s.remove_user(uid, "Autodropped");
return ModResult::Deny; return ModResult::Deny;
} }

View file

@ -68,10 +68,8 @@ pub fn on_pong(s: &mut Server, uid: Uid, params: &[String]) {
u.waitpong = None; u.waitpong = None;
} }
} else if s.conf_bool("conn_waitpong_killonbadreply", false) { } else if s.conf_bool("conn_waitpong_killonbadreply", false) {
s.send( let m = s.trf("Closing link (incorrect ping reply)", &[]);
uid, s.send(uid, format!("ERROR :{m}"));
"ERROR :Closing link (incorrect ping reply)".to_string(),
);
s.remove_user(uid, "Incorrect ping reply"); s.remove_user(uid, "Incorrect ping reply");
} }
} }

View file

@ -210,7 +210,8 @@ fn act(s: &mut Server, uid: Uid, domain: &str) {
if closes { if closes {
// pre-registration users aren't caught by add_xline's enforce sweep, so close // pre-registration users aren't caught by add_xline's enforce sweep, so close
// this connection explicitly (the ERROR flushes before the socket). // this connection explicitly (the ERROR flushes before the socket).
s.send(uid, format!("ERROR :Closing link: ({reason})")); let m = s.trf("Closing link: ({0})", &[reason.as_str()]);
s.send(uid, format!("ERROR :{m}"));
s.remove_user(uid, &reason); s.remove_user(uid, &reason);
} }
} }

View file

@ -71,7 +71,8 @@ impl Module for Filter {
"block" => s.notice_star(uid, &format!("Your message was blocked: {reason}")), "block" => s.notice_star(uid, &format!("Your message was blocked: {reason}")),
"silent" => {} "silent" => {}
"kill" => { "kill" => {
s.send(uid, format!("ERROR :Closing link: ({reason})")); let m = s.trf("Closing link: ({0})", &[reason.as_str()]);
s.send(uid, format!("ERROR :{m}"));
s.remove_user(uid, &reason); s.remove_user(uid, &reason);
} }
"kline" => { "kline" => {

View file

@ -58,7 +58,8 @@ impl Module for Flood {
if over { if over {
if !fakelag { if !fakelag {
// fakelag disabled: disconnect the flooder instead of throttling // fakelag disabled: disconnect the flooder instead of throttling
srv.send(uid, "ERROR :Closing link: (Excess flood)".to_string()); let m = srv.trf("Closing link: (Excess flood)", &[]);
srv.send(uid, format!("ERROR :{m}"));
srv.mark_quit(uid, "Excess flood".to_string()); srv.mark_quit(uid, "Excess flood".to_string());
return ModResult::Deny; return ModResult::Deny;
} }

View file

@ -481,10 +481,8 @@ impl Server {
// connflood — refuse an IP that's opening connections too fast (see modules::connflood) // connflood — refuse an IP that's opening connections too fast (see modules::connflood)
if crate::modules::connflood::over_limit(self, ip) { if crate::modules::connflood::over_limit(self, ip) {
self.send( let m = self.trf("Closing link: (Too many connections from your IP)", &[]);
uid, self.send(uid, format!("ERROR :{m}"));
"ERROR :Closing link: (Too many connections from your IP)".to_string(),
);
self.remove_user(uid, "Connection throttled"); self.remove_user(uid, "Connection throttled");
return; return;
} }
@ -494,7 +492,8 @@ impl Server {
// connectclass — assign a connection class; a deny class or per-IP cap rejects // connectclass — assign a connection class; a deny class or per-IP cap rejects
if let Some(reason) = crate::modules::connclass::assign(self, uid) { if let Some(reason) = crate::modules::connclass::assign(self, uid) {
self.send(uid, format!("ERROR :Closing link: ({reason})")); let m = self.trf("Closing link: ({0})", &[reason.as_str()]);
self.send(uid, format!("ERROR :{m}"));
self.remove_user(uid, &reason); self.remove_user(uid, &reason);
return; return;
} }

View file

@ -270,7 +270,8 @@ impl Server {
.map(|(&uid, _)| uid) .map(|(&uid, _)| uid)
.collect(); .collect();
for uid in victims { for uid in victims {
self.send(uid, format!("ERROR :Closing link: (R-lined: {reason})")); let m = self.trf("Closing link: (R-lined: {0})", &[reason]);
self.send(uid, format!("ERROR :{m}"));
self.remove_user(uid, &format!("R-lined: {reason}")); self.remove_user(uid, &format!("R-lined: {reason}"));
} }
} }
@ -365,7 +366,8 @@ impl Server {
}) })
.collect(); .collect();
for (uid, reason) in victims { for (uid, reason) in victims {
self.send(uid, format!("ERROR :Closing link: ({reason})")); let m = self.trf("Closing link: ({0})", &[reason.as_str()]);
self.send(uid, format!("ERROR :{m}"));
self.remove_user(uid, &reason); self.remove_user(uid, &reason);
} }
} }