diff --git a/lang/es.conf b/lang/es.conf index a9854fc..fa016fb 100644 --- a/lang/es.conf +++ b/lang/es.conf @@ -10,6 +10,27 @@ "This server was created at unix {0}" = "Este servidor fue creado el (unix) {0}" "There are {0} users on 1 server" = "Hay {0} usuarios en 1 servidor" +# --- rehash / configuración (avisos del servidor) --- +"Server configuration reloaded." = "Configuración del servidor recargada." +"admin {0} has changed the configuration of the server." = "el administrador {0} ha cambiado la configuración del servidor." +"{0} is rehashing the server config file." = "{0} está recargando el archivo de configuración del servidor." +"{0} tried to reload the server configuration, but the config file could not be read — no changes were made." = "{0} intentó recargar la configuración del servidor, pero no se pudo leer el archivo de configuración — no se hicieron cambios." +"Could not read {0} — the running configuration was kept." = "No se pudo leer {0} — se mantuvo la configuración en curso." + +# --- avisos de operador: conexión / oper / canal (prosa dinámica) --- +"The server is rehashing its configuration." = "El servidor está recargando su configuración." +"Server configuration reloaded via RPC." = "Configuración del servidor recargada vía RPC." +"Client connecting: {0} ({1}@{2})" = "Conexión de cliente: {0} ({1}@{2})" +", port: {0}" = ", puerto: {0}" +", sni: {0}" = ", sni: {0}" +", account: {0}" = ", cuenta: {0}" +"Client exiting: {0} ({1})" = "Desconexión de cliente: {0} ({1})" +"{0} is now an IRC operator" = "{0} ahora es operador IRC" +"Client {0} is now logged in as {1}" = "El cliente {0} ahora ha iniciado sesión como {1}" +"{0} used oper override to join {1}" = "{0} usó anulación de oper para entrar a {1}" +"{0} created channel {1}" = "{0} creó el canal {1}" +"{0} used OJOIN to enter {1}" = "{0} usó OJOIN para entrar a {1}" + # --- avisos / desafíos --- "*** 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." diff --git a/lang/fr.conf b/lang/fr.conf index 4111f0d..5acd99e 100644 --- a/lang/fr.conf +++ b/lang/fr.conf @@ -10,6 +10,27 @@ "This server was created at unix {0}" = "Ce serveur a été créé le (unix) {0}" "There are {0} users on 1 server" = "Il y a {0} utilisateurs sur 1 serveur" +# --- rehash / configuration (notices serveur) --- +"Server configuration reloaded." = "Configuration du serveur rechargée." +"admin {0} has changed the configuration of the server." = "l'administrateur {0} a modifié la configuration du serveur." +"{0} is rehashing the server config file." = "{0} recharge le fichier de configuration du serveur." +"{0} tried to reload the server configuration, but the config file could not be read — no changes were made." = "{0} a tenté de recharger la configuration du serveur, mais le fichier de configuration n'a pas pu être lu — aucune modification n'a été effectuée." +"Could not read {0} — the running configuration was kept." = "Impossible de lire {0} — la configuration en cours a été conservée." + +# --- notices opérateur : connexion / oper / salon (prose dynamique) --- +"The server is rehashing its configuration." = "Le serveur recharge sa configuration." +"Server configuration reloaded via RPC." = "Configuration du serveur rechargée via RPC." +"Client connecting: {0} ({1}@{2})" = "Connexion du client : {0} ({1}@{2})" +", port: {0}" = ", port : {0}" +", sni: {0}" = ", sni : {0}" +", account: {0}" = ", compte : {0}" +"Client exiting: {0} ({1})" = "Déconnexion du client : {0} ({1})" +"{0} is now an IRC operator" = "{0} est maintenant opérateur IRC" +"Client {0} is now logged in as {1}" = "Le client {0} est maintenant connecté en tant que {1}" +"{0} used oper override to join {1}" = "{0} a utilisé le contournement oper pour rejoindre {1}" +"{0} created channel {1}" = "{0} a créé le salon {1}" +"{0} used OJOIN to enter {1}" = "{0} a utilisé OJOIN pour entrer dans {1}" + # --- notices / défis --- "*** 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." diff --git a/src/accounts.rs b/src/accounts.rs index f363f01..d96d58e 100644 --- a/src/accounts.rs +++ b/src/accounts.rs @@ -43,7 +43,8 @@ impl Server { // connected. A SASL-at-connect login runs before registration completes, so // it's already reflected in the "Client connecting: … account: …" notice. if registered { - self.snotice_c('c', &format!("Client {nick} is now logged in as {account}")); + let m = self.trf("Client {0} is now logged in as {1}", &[nick.as_str(), account]); + self.snotice_c('c', &m); } } diff --git a/src/channels.rs b/src/channels.rs index 82b10f2..27f5807 100644 --- a/src/channels.rs +++ b/src/channels.rs @@ -941,7 +941,8 @@ impl Server { .get(&uid) .map(|u| u.nick.clone()) .unwrap_or_default(); - self.snotice_c('v', &format!("{nick} used oper override to join {name}")); + let m = self.trf("{0} used oper override to join {1}", &[nick.as_str(), name]); + self.snotice_c('v', &m); } let is_new = !self.channels.contains_key(&key); let ch = self @@ -971,7 +972,8 @@ impl Server { .get(&uid) .map(|u| u.nick.clone()) .unwrap_or_default(); - self.snotice_c('j', &format!("{who} created channel {name}")); + let m = self.trf("{0} created channel {1}", &[who.as_str(), name]); + self.snotice_c('j', &m); } // JOIN broadcast — extended-join clients also get the account + realname diff --git a/src/coremods/core_rehash.rs b/src/coremods/core_rehash.rs index 680230e..fe90153 100644 --- a/src/coremods/core_rehash.rs +++ b/src/coremods/core_rehash.rs @@ -48,27 +48,23 @@ impl Command for Rehash { match Config::try_load(&path) { Some(fresh) => { // announce to everyone connected, not just opers - s.announce(&format!( - "admin {who} has changed the configuration of the server." - )); - s.announce(&format!("{who} is rehashing the server config file.")); + let m = s.trf("admin {0} has changed the configuration of the server.", &[who.as_str()]); + s.announce(&m); + let m = s.trf("{0} is rehashing the server config file.", &[who.as_str()]); + s.announce(&m); s.apply_config(fresh); s.announce("Server configuration reloaded."); s.numeric(uid, RPL_REHASHING, &format!("{path} :Rehashing")); } None => { // Unreadable config — keep what's running (do NOT reset to defaults). - s.announce(&format!( - "{who} tried to reload the server configuration, but the config file \ - could not be read — no changes were made." - )); - s.send( - uid, - format!( - ":{} NOTICE {who} :*** Could not read {path} — the running configuration was kept.", - s.name - ), + let m = s.trf( + "{0} tried to reload the server configuration, but the config file could not be read — no changes were made.", + &[who.as_str()], ); + s.announce(&m); + let m = s.trf("Could not read {0} — the running configuration was kept.", &[path.as_str()]); + s.send(uid, format!(":{} NOTICE {who} :*** {m}", s.name)); } } CmdResult::Ok diff --git a/src/modules/ojoin.rs b/src/modules/ojoin.rs index 9e516ba..11089cb 100644 --- a/src/modules/ojoin.rs +++ b/src/modules/ojoin.rs @@ -49,7 +49,8 @@ impl Command for OjoinCmd { if s.conf_bool("ojoin_op", true) { crate::coremods::core_mode::svs_set_chan_modes(s, &chan, "+o", &[nick.clone()]); } - s.snotice_c('v', &format!("{nick} used OJOIN to enter {chan}")); + let m = s.trf("{0} used OJOIN to enter {1}", &[nick.as_str(), chan.as_str()]); + s.snotice_c('v', &m); CmdResult::Ok } } diff --git a/src/modules/snoop.rs b/src/modules/snoop.rs index e65e354..9adbfad 100644 --- a/src/modules/snoop.rs +++ b/src/modules/snoop.rs @@ -14,22 +14,36 @@ impl Module for Snoop { fn on_user_connect(&mut self, srv: &mut Server, uid: Uid) { // `conf_bool`/`snotice_c` are `&self`, so we can hold the `&User` borrow and // reference its fields directly instead of cloning them out. - let Some(u) = srv.users.get(&uid) else { - return; + let (nick, ident, host, port, sni, account) = { + let Some(u) = srv.users.get(&uid) else { + return; + }; + ( + u.nick.clone(), + u.ident.clone(), + u.host.clone(), + u.port, + u.sni.clone(), + u.account.clone(), + ) }; if srv.conf_bool("snoop_stderr", false) { - eprintln!("[snoop] connect {} ({}@{})", u.nick, u.ident, u.host); + eprintln!("[snoop] connect {nick} ({ident}@{host})"); } - // port is always shown; sni/account only when present, so plaintext or - // anonymous connects don't carry empty fields. - let mut extra = format!(", port: {}", u.port); - if let Some(sni) = &u.sni { - extra.push_str(&format!(", sni: {sni}")); + // port is always shown; sni/account only when present. Prose + field labels come + // from the locale catalog so a translated build reads naturally. + let mut msg = srv.trf( + "Client connecting: {0} ({1}@{2})", + &[nick.as_str(), ident.as_str(), host.as_str()], + ); + let port_s = port.to_string(); + msg.push_str(&srv.trf(", port: {0}", &[port_s.as_str()])); + if let Some(sni) = &sni { + msg.push_str(&srv.trf(", sni: {0}", &[sni.as_str()])); } - if let Some(acct) = &u.account { - extra.push_str(&format!(", account: {acct}")); + if let Some(acct) = &account { + msg.push_str(&srv.trf(", account: {0}", &[acct.as_str()])); } - let msg = format!("Client connecting: {} ({}@{}){extra}", u.nick, u.ident, u.host); srv.snotice_c('c', &msg); } fn on_join(&mut self, srv: &mut Server, uid: Uid, chan: &str) { @@ -56,6 +70,7 @@ impl Module for Snoop { if srv.conf_bool("snoop_stderr", false) { eprintln!("[snoop] quit uid={uid} ({reason})"); } - srv.snotice_c('q', &format!("Client exiting: {nick} ({reason})")); + let m = srv.trf("Client exiting: {0} ({1})", &[nick.as_str(), reason]); + srv.snotice_c('q', &m); } } diff --git a/src/server.rs b/src/server.rs index 64648c1..239926d 100644 --- a/src/server.rs +++ b/src/server.rs @@ -1070,6 +1070,10 @@ impl Server { return; }; let nick = u.nick.clone(); + // Localize the prose for the recipient; the log/chanlog/syslog tees keep the + // English source. Static snotice/announce text auto-translates here (like the + // numeric chokepoint); already-templated dynamic text passes through unchanged. + let msg = self.catalog.tr(msg); let mut tags: Vec = Vec::new(); if u.caps.server_time { tags.push(format!("time={}", iso_time(now()))); diff --git a/src/users.rs b/src/users.rs index bd66f46..50520fd 100644 --- a/src/users.rs +++ b/src/users.rs @@ -331,7 +331,8 @@ impl Server { .unwrap_or_default(); self.numeric(uid, RPL_YOUREOPER, ":You are now an IRC operator"); self.send(uid, format!(":{} MODE {nick} :+os", self.name)); - self.snotice_c('o', &format!("{nick} is now an IRC operator")); + let m = self.trf("{0} is now an IRC operator", &[nick.as_str()]); + self.snotice_c('o', &m); // operprefix: give this oper the ! prefix in every channel they're already in crate::modules::operprefix::grant_all(self, uid); // opermodes: extra umodes on oper-up