diff --git a/lang/fr.json b/lang/fr.json index 3c7050e..2e74b39 100644 --- a/lang/fr.json +++ b/lang/fr.json @@ -2,5 +2,382 @@ "Your language is \u0002{lang}\u0002. Available: {list}. Change it with \u0002SET LANGUAGE \u0002.": "Votre langue est \u0002{lang}\u0002. Disponibles : {list}. Changez-la avec \u0002SET LANGUAGE \u0002.", "\u0002{code}\u0002 isn't an available language. Available: {list}.": "\u0002{code}\u0002 n'est pas une langue disponible. Disponibles : {list}.", "Your language is now \u0002{lang}\u0002.": "Votre langue est maintenant \u0002{lang}\u0002.", - "Sorry, that didn't work. Please try again in a moment.": "Désolé, une erreur est survenue. Veuillez réessayer dans un instant." + "Sorry, that didn't work. Please try again in a moment.": "Désolé, cela n'a pas fonctionné. Veuillez réessayer dans un instant.", + "GroupServ manages user groups: a \u0002!name\u0002 owning member accounts. Add a group to a channel's access (\u0002/msg ChanServ ACCESS #chan ADD !name op\u0002) and each member holding the group's \u0002c\u0002 flag inherits it.": "GroupServ gère les groupes d'utilisateurs : un \u0002!name\u0002 possédant des comptes membres. Ajoutez un groupe à l'accès d'un salon (\u0002/msg ChanServ ACCESS #chan ADD !name op\u0002) et chaque membre détenant le flag \u0002c\u0002 du groupe en hérite.", + "create a group you found": "créez un groupe que vous fondez", + "Syntax: \u0002REGISTER \u0002\nCreates a group with you as founder. A group name starts with '!', e.g. !staff.": "Syntaxe : \u0002REGISTER \u0002\nCrée un groupe dont vous êtes le fondateur. Un nom de groupe commence par '!', par exemple !staff.", + "delete a group you founded": "supprimez un groupe que vous avez fondé", + "Syntax: \u0002DROP \u0002\nDeletes a group. Founder only.": "Syntaxe : \u0002DROP \u0002\nSupprime un groupe. Fondateur uniquement.", + "show a group's founder and size": "affichez le fondateur et la taille d'un groupe", + "Syntax: \u0002INFO \u0002\nShows a group's founder and member count.": "Syntaxe : \u0002INFO \u0002\nAffiche le fondateur et le nombre de membres d'un groupe.", + "list groups you belong to": "listez les groupes auxquels vous appartenez", + "Syntax: \u0002LIST\u0002\nLists the groups you belong to. Operators see every group.": "Syntaxe : \u0002LIST\u0002\nListe les groupes dont vous êtes membre. Les opérateurs voient tous les groupes.", + "add a member": "ajoutez un membre", + "Syntax: \u0002ADD \u0002\nAdds a plain member (no flags). To let them inherit the group's channel access, give them the \u0002c\u0002 flag with FLAGS. Needs the founder or the 'f' flag.": "Syntaxe : \u0002ADD \u0002\nAjoute un simple membre (sans flags). Pour qu'il hérite de l'accès du groupe aux salons, attribuez-lui le flag \u0002c\u0002 avec FLAGS. Nécessite le fondateur ou le flag 'f'.", + "remove a member": "retirez un membre", + "Syntax: \u0002DEL \u0002\nRemoves a member. Needs the founder or the 'f' flag.": "Syntaxe : \u0002DEL \u0002\nRetire un membre. Nécessite le fondateur ou le flag 'f'.", + "view or change group flags": "affichez ou modifiez les flags d'un groupe", + "Syntax: \u0002FLAGS [account [+/-flags]]\u0002\nLists, shows, or changes group-access flags (F founder, f manage, i invite, c inherit the group's channel access, s set, m memo). Changing needs the founder or the 'f' flag.": "Syntaxe : \u0002FLAGS [compte [+/-flags]]\u0002\nAffiche, consulte ou modifie les flags d'accès du groupe (F fondateur, f gérer, i inviter, c hériter de l'accès du groupe aux salons, s set, m mémo). La modification nécessite le fondateur ou le flag 'f'.", + "I don't know \u0002{other}\u0002. Try \u0002HELP\u0002.": "Je ne connais pas \u0002{other}\u0002. Essayez \u0002HELP\u0002.", + "You need to be logged in. Identify to NickServ first.": "Vous devez être connecté. Identifiez-vous d'abord auprès de NickServ.", + "Syntax: ADD ": "Syntaxe : ADD ", + "\u0002{name}\u0002 isn't registered.": "\u0002{name}\u0002 n'est pas enregistré.", + "You need the founder or the \u0002f\u0002 flag to manage \u0002{name}\u0002.": "Vous devez être fondateur ou détenir le flag \u0002f\u0002 pour gérer \u0002{name}\u0002.", + "\u0002{target}\u0002 isn't registered.": "\u0002{target}\u0002 n'est pas enregistré.", + "Added \u0002{canonical}\u0002 to \u0002{name}\u0002.": "\u0002{canonical}\u0002 a été ajouté à \u0002{name}\u0002.", + "Syntax: DEL ": "Syntaxe : DEL ", + "Removed \u0002{target}\u0002 from \u0002{name}\u0002.": "\u0002{target}\u0002 a été retiré de \u0002{name}\u0002.", + "\u0002{target}\u0002 isn't in \u0002{name}\u0002.": "\u0002{target}\u0002 n'est pas membre de \u0002{name}\u0002.", + "Syntax: DROP ": "Syntaxe : DROP ", + "Only \u0002{name}\u0002's founder can drop it.": "Seul le fondateur de \u0002{name}\u0002 peut le supprimer.", + "Group \u0002{name}\u0002 has been dropped.": "Le groupe \u0002{name}\u0002 a été supprimé.", + "Syntax: FLAGS [account [+/-flags]]": "Syntaxe : FLAGS [account [+/-flags]]", + "Flags for \u0002{name}\u0002:": "Flags pour \u0002{name}\u0002 :", + " \u0002{founder}\u0002 (founder): \u0002F\u0002": " \u0002{founder}\u0002 (fondateur) : \u0002F\u0002", + " \u0002{account}\u0002: \u0002{flags}\u0002": " \u0002{account}\u0002 : \u0002{flags}\u0002", + "(member)": "(membre)", + "\u0002{target}\u0002 in \u0002{name}\u0002: \u0002{flags}\u0002": "\u0002{target}\u0002 dans \u0002{name}\u0002 : \u0002{flags}\u0002", + "You need the founder or the \u0002f\u0002 flag to change \u0002{name}\u0002.": "Vous devez être fondateur ou détenir le flag \u0002f\u0002 pour modifier \u0002{name}\u0002.", + "\u0002{bad}\u0002 isn't a valid group flag. Valid: \u0002{valid}\u0002.": "\u0002{bad}\u0002 n'est pas un flag de groupe valide. Valides : \u0002{valid}\u0002.", + "\u0002{canonical}\u0002 in \u0002{name}\u0002 now holds \u0002{flags}\u0002.": "\u0002{canonical}\u0002 dans \u0002{name}\u0002 détient désormais \u0002{flags}\u0002.", + "Syntax: INFO ": "Syntaxe : INFO ", + "Information for \u0002{name}\u0002:": "Informations sur \u0002{name}\u0002 :", + " Founder : \u0002{founder}\u0002": " Fondateur : \u0002{founder}\u0002", + " Members : {count}": " Membres : {count}", + "No groups to show.": "Aucun groupe à afficher.", + " \u0002{n}\u0002": " \u0002{n}\u0002", + "End of list ({count} group(s)).": "Fin de la liste ({count} groupe(s)).", + "Syntax: REGISTER ": "Syntaxe : REGISTER ", + "A group name starts with \u0002!\u0002, e.g. \u0002!staff\u0002.": "Un nom de groupe commence par \u0002!\u0002, par exemple \u0002!staff\u0002.", + "Group registration is temporarily disabled. Please try again later.": "L'enregistrement de groupes est temporairement désactivé. Veuillez réessayer plus tard.", + "You've reached the maximum of {max} registered groups.": "Vous avez atteint le maximum de {max} groupes enregistrés.", + "Group \u0002{name}\u0002 registered — you're the founder.": "Groupe \u0002{name}\u0002 enregistré — vous en êtes le fondateur.", + "\u0002{name}\u0002 is already registered.": "\u0002{name}\u0002 est déjà enregistré.", + "MemoServ delivers messages to registered users, online or not. You must be identified to use it.": "MemoServ délivre des messages aux utilisateurs enregistrés, connectés ou non. Vous devez être identifié pour l'utiliser.", + "You must identify to NickServ before using MemoServ.": "Vous devez vous identifier auprès de NickServ avant d'utiliser MemoServ.", + "I don't know the command \u0002{other}\u0002. Try \u0002HELP\u0002.": "Je ne connais pas la commande \u0002{other}\u0002. Essayez \u0002HELP\u0002.", + "leave a memo for an account": "laisser un mémo à un compte", + "Syntax: \u0002SEND \u0002\nLeaves a memo on a registered account's mailbox.": "Syntaxe : \u0002SEND \u0002\nLaisse un mémo dans la boîte d'un compte enregistré.", + "leave a memo and get a read receipt": "laisser un mémo et recevoir un accusé de lecture", + "Syntax: \u0002RSEND \u0002\nLike SEND, but memos you back when the recipient reads it.": "Syntaxe : \u0002RSEND \u0002\nComme SEND, mais vous renvoie un mémo lorsque le destinataire le lit.", + "list your memos": "lister vos mémos", + "Syntax: \u0002LIST\u0002\nLists the memos in your mailbox.": "Syntaxe : \u0002LIST\u0002\nListe les mémos de votre boîte.", + "read a memo": "lire un mémo", + "Syntax: \u0002READ |NEW|ALL\u0002\nReads a memo by number, your unread ones, or all of them.": "Syntaxe : \u0002READ |NEW|ALL\u0002\nLit un mémo par numéro, vos mémos non lus, ou tous.", + "delete a memo": "supprimer un mémo", + "Syntax: \u0002DEL |ALL\u0002\nDeletes a memo by number, or your whole mailbox.": "Syntaxe : \u0002DEL |ALL\u0002\nSupprime un mémo par numéro, ou toute votre boîte.", + "recall a memo you sent": "rappeler un mémo que vous avez envoyé", + "Syntax: \u0002CANCEL \u0002\nRecalls the last memo you sent them, as long as they haven't read it yet.": "Syntaxe : \u0002CANCEL \u0002\nRappelle le dernier mémo que vous leur avez envoyé, tant qu'ils ne l'ont pas encore lu.", + "see if a memo was read": "vérifier si un mémo a été lu", + "Syntax: \u0002CHECK \u0002\nReports whether the last memo you sent them has been read.": "Syntaxe : \u0002CHECK \u0002\nIndique si le dernier mémo que vous leur avez envoyé a été lu.", + "your mailbox summary": "le résumé de votre boîte", + "Syntax: \u0002INFO\u0002\nShows how many memos you have, how many are unread, and your capacity.": "Syntaxe : \u0002INFO\u0002\nAffiche combien de mémos vous avez, combien sont non lus, et votre capacité.", + "memo every account (admin)": "envoyer un mémo à tous les comptes (admin)", + "Syntax: \u0002SENDALL \u0002\nLeaves a memo on every registered account. Requires the admin privilege.": "Syntaxe : \u0002SENDALL \u0002\nLaisse un mémo sur chaque compte enregistré. Nécessite le privilège admin.", + "memo every operator (admin)": "envoyer un mémo à tous les opérateurs (admin)", + "Syntax: \u0002STAFF \u0002\nLeaves a memo on every operator's account. Requires the admin privilege.": "Syntaxe : \u0002STAFF \u0002\nLaisse un mémo sur le compte de chaque opérateur. Nécessite le privilège admin.", + "block memos from an account": "bloquer les mémos d'un compte", + "Syntax: \u0002IGNORE ADD | DEL | LIST\u0002\nMemos from an ignored account are silently dropped.": "Syntaxe : \u0002IGNORE ADD | DEL | LIST\u0002\nLes mémos d'un compte ignoré sont supprimés silencieusement.", + "your memo preferences": "vos préférences de mémos", + "Syntax: \u0002SET NOTIFY {ON|OFF}\u0002, \u0002SET LIMIT |NONE\u0002\nControls new-memo notifications and your mailbox size cap.": "Syntaxe : \u0002SET NOTIFY {ON|OFF}\u0002, \u0002SET LIMIT |NONE\u0002\nContrôle les notifications de nouveaux mémos et la limite de taille de votre boîte.", + "Syntax: {cmd} ": "Syntaxe : {cmd} ", + "\u0002{target}\u0002's mailbox is full — they'll need to clear some memos first.": "La boîte de \u0002{target}\u0002 est pleine — ils devront d'abord supprimer quelques mémos.", + "Memo sent to \u0002{target}\u0002.": "Mémo envoyé à \u0002{target}\u0002.", + "You have no new memos.": "Vous n'avez aucun nouveau mémo.", + "You have no memos.": "Vous n'avez aucun mémo.", + "Syntax: READ |NEW|ALL": "Syntaxe : READ |NEW|ALL", + "You have no memo #\u0002{n}\u0002.": "Vous n'avez aucun mémo #\u0002{n}\u0002.", + "Memo #\u0002{num}\u0002 from \u0002{from}\u0002 ({when}):": "Mémo #\u0002{num}\u0002 de \u0002{from}\u0002 ({when}) :", + " {text}": " {text}", + "Access denied — STAFF needs the \u0002admin\u0002 privilege.": "Accès refusé — STAFF nécessite le privilège \u0002admin\u0002.", + "Syntax: STAFF ": "Syntaxe : STAFF ", + "Memo sent to \u0002{sent}\u0002 operator(s).": "Mémo envoyé à \u0002{sent}\u0002 opérateur(s).", + "You have \u0002{total}\u0002 memo(s), \u0002{unread}\u0002 unread, of a maximum \u0002{max}\u0002.": "Vous avez \u0002{total}\u0002 mémo(s), \u0002{unread}\u0002 non lu(s), sur un maximum de \u0002{max}\u0002.", + "Deleted all \u0002{count}\u0002 memo(s).": "Tous les \u0002{count}\u0002 mémo(s) supprimé(s).", + "Syntax: DEL |ALL": "Syntaxe : DEL |ALL", + "Memo #\u0002{n}\u0002 deleted.": "Mémo #\u0002{n}\u0002 supprimé.", + "Your memos ({total} total, {unread} new). \u0002*\u0002 marks unread:": "Vos mémos ({total} au total, {unread} nouveaux). \u0002*\u0002 marque les non lus :", + " {num}{flag} from \u0002{from}\u0002 ({when}): {preview}": " {num}{flag} de \u0002{from}\u0002 ({when}) : {preview}", + "Syntax: CANCEL ": "Syntaxe : CANCEL ", + "Your last unread memo to \u0002{target}\u0002 has been cancelled.": "Votre dernier mémo non lu à \u0002{target}\u0002 a été annulé.", + "You have no unread memo to \u0002{target}\u0002 to cancel.": "Vous n'avez aucun mémo non lu à \u0002{target}\u0002 à annuler.", + "Access denied — SENDALL needs the \u0002admin\u0002 privilege.": "Accès refusé — SENDALL nécessite le privilège \u0002admin\u0002.", + "Syntax: SENDALL ": "Syntaxe : SENDALL ", + "Memo sent to \u0002{sent}\u0002 account(s).": "Mémo envoyé à \u0002{sent}\u0002 compte(s).", + "Syntax: CHECK ": "Syntaxe : CHECK ", + "Your last memo to \u0002{target}\u0002 (sent {when}) has been \u0002read\u0002.": "Votre dernier mémo à \u0002{target}\u0002 (envoyé {when}) a été \u0002lu\u0002.", + "Your last memo to \u0002{target}\u0002 (sent {when}) has \u0002not\u0002 been read yet.": "Votre dernier mémo à \u0002{target}\u0002 (envoyé {when}) n'a \u0002pas\u0002 encore été lu.", + "You have no memo on record to \u0002{target}\u0002.": "Vous n'avez aucun mémo enregistré pour \u0002{target}\u0002.", + "Syntax: SET NOTIFY {ON|OFF}": "Syntaxe : SET NOTIFY {ON|OFF}", + "New-memo notification is now \u0002{state}\u0002.": "La notification de nouveau mémo est maintenant \u0002{state}\u0002.", + "The limit must be a number from 0 to {max}, or NONE.": "La limite doit être un nombre de 0 à {max}, ou NONE.", + "Your mailbox limit is now \u0002{v}\u0002.": "La limite de votre boîte est maintenant \u0002{v}\u0002.", + "Your mailbox limit is now the network default (\u0002{max}\u0002).": "La limite de votre boîte est maintenant la valeur par défaut du réseau (\u0002{max}\u0002).", + "Syntax: SET NOTIFY {ON|OFF} | SET LIMIT |NONE": "Syntaxe : SET NOTIFY {ON|OFF} | SET LIMIT |NONE", + "Syntax: IGNORE ADD ": "Syntaxe : IGNORE ADD ", + "Your memo-ignore list is full (max {max}).": "Votre liste d'ignorés de mémos est pleine (max {max}).", + "Now ignoring memos from \u0002{target}\u0002.": "Vous ignorez désormais les mémos de \u0002{target}\u0002.", + "You're already ignoring \u0002{target}\u0002.": "Vous ignorez déjà \u0002{target}\u0002.", + "Syntax: IGNORE DEL ": "Syntaxe : IGNORE DEL ", + "No longer ignoring \u0002{target}\u0002.": "Vous n'ignorez plus \u0002{target}\u0002.", + "You weren't ignoring \u0002{target}\u0002.": "Vous n'ignoriez pas \u0002{target}\u0002.", + "Your memo-ignore list is empty.": "Votre liste d'ignorés de mémos est vide.", + "You're ignoring memos from: {names}": "Vous ignorez les mémos de : {names}", + "Syntax: IGNORE ADD | DEL | LIST": "Syntaxe : IGNORE ADD | DEL | LIST", + "GroupServ manages user groups: a \\x02!name\\x02 owning member accounts. Add a group to a channel's access (\\x02/msg ChanServ ACCESS #chan ADD !name op\\x02) and each member holding the group's \\x02c\\x02 flag inherits it.": "GroupServ gère les groupes d'utilisateurs : un \\x02!name\\x02 qui possède des comptes membres. Ajoutez un groupe à l'accès d'un salon (\\x02/msg ChanServ ACCESS #chan ADD !name op\\x02) et chaque membre détenant le flag \\x02c\\x02 du groupe en hérite.", + "Syntax: \\x02REGISTER \\x02\nCreates a group with you as founder. A group name starts with '!', e.g. !staff.": "Syntaxe : \\x02REGISTER \\x02\nCrée un groupe dont vous êtes le fondateur. Un nom de groupe commence par '!', par ex. !staff.", + "Syntax: \\x02DROP \\x02\nDeletes a group. Founder only.": "Syntaxe : \\x02DROP \\x02\nSupprime un groupe. Fondateur uniquement.", + "Syntax: \\x02INFO \\x02\nShows a group's founder and member count.": "Syntaxe : \\x02INFO \\x02\nAffiche le fondateur et le nombre de membres d'un groupe.", + "Syntax: \\x02LIST\\x02\nLists the groups you belong to. Operators see every group.": "Syntaxe : \\x02LIST\\x02\nListe les groupes auxquels vous appartenez. Les opérateurs voient tous les groupes.", + "Syntax: \\x02ADD \\x02\nAdds a plain member (no flags). To let them inherit the group's channel access, give them the \\x02c\\x02 flag with FLAGS. Needs the founder or the 'f' flag.": "Syntaxe : \\x02ADD \\x02\nAjoute un simple membre (sans flags). Pour qu'il hérite de l'accès du groupe aux salons, attribuez-lui le flag \\x02c\\x02 avec FLAGS. Nécessite le fondateur ou le flag 'f'.", + "Syntax: \\x02DEL \\x02\nRemoves a member. Needs the founder or the 'f' flag.": "Syntaxe : \\x02DEL \\x02\nRetire un membre. Nécessite le fondateur ou le flag 'f'.", + "Syntax: \\x02FLAGS [account [+/-flags]]\\x02\nLists, shows, or changes group-access flags (F founder, f manage, i invite, c inherit the group's channel access, s set, m memo). Changing needs the founder or the 'f' flag.": "Syntaxe : \\x02FLAGS [account [+/-flags]]\\x02\nListe, affiche ou modifie les flags d'accès de groupe (F fondateur, f gérer, i inviter, c hériter de l'accès du groupe aux salons, s set, m memo). La modification nécessite le fondateur ou le flag 'f'.", + "I don't know \\x02{other}\\x02. Try \\x02HELP\\x02.": "Je ne connais pas \\x02{other}\\x02. Essayez \\x02HELP\\x02.", + "\\x02{name}\\x02 isn't registered.": "\\x02{name}\\x02 n'est pas enregistré.", + "Only \\x02{name}\\x02's founder can drop it.": "Seul le fondateur de \\x02{name}\\x02 peut le supprimer.", + "Group \\x02{name}\\x02 has been dropped.": "Le groupe \\x02{name}\\x02 a été supprimé.", + "You need the founder or the \\x02f\\x02 flag to manage \\x02{name}\\x02.": "Vous devez être le fondateur ou détenir le flag \\x02f\\x02 pour gérer \\x02{name}\\x02.", + "\\x02{target}\\x02 isn't registered.": "\\x02{target}\\x02 n'est pas enregistré.", + "Added \\x02{canonical}\\x02 to \\x02{name}\\x02.": "\\x02{canonical}\\x02 a été ajouté à \\x02{name}\\x02.", + "A group name starts with \\x02!\\x02, e.g. \\x02!staff\\x02.": "Un nom de groupe commence par \\x02!\\x02, par ex. \\x02!staff\\x02.", + "Group \\x02{name}\\x02 registered — you're the founder.": "Groupe \\x02{name}\\x02 enregistré — vous en êtes le fondateur.", + "\\x02{name}\\x02 is already registered.": "\\x02{name}\\x02 est déjà enregistré.", + "Flags for \\x02{name}\\x02:": "Flags pour \\x02{name}\\x02 :", + " \\x02{founder}\\x02 (founder): \\x02F\\x02": " \\x02{founder}\\x02 (fondateur) : \\x02F\\x02", + " \\x02{account}\\x02: \\x02{flags}\\x02": " \\x02{account}\\x02 : \\x02{flags}\\x02", + "\\x02{target}\\x02 in \\x02{name}\\x02: \\x02{flags}\\x02": "\\x02{target}\\x02 dans \\x02{name}\\x02 : \\x02{flags}\\x02", + "\\x02{target}\\x02 isn't in \\x02{name}\\x02.": "\\x02{target}\\x02 n'est pas dans \\x02{name}\\x02.", + "You need the founder or the \\x02f\\x02 flag to change \\x02{name}\\x02.": "Vous devez être le fondateur ou détenir le flag \\x02f\\x02 pour modifier \\x02{name}\\x02.", + "\\x02{bad}\\x02 isn't a valid group flag. Valid: \\x02{valid}\\x02.": "\\x02{bad}\\x02 n'est pas un flag de groupe valide. Valides : \\x02{valid}\\x02.", + "\\x02{canonical}\\x02 in \\x02{name}\\x02 now holds \\x02{flags}\\x02.": "\\x02{canonical}\\x02 dans \\x02{name}\\x02 détient désormais \\x02{flags}\\x02.", + "Information for \\x02{name}\\x02:": "Informations pour \\x02{name}\\x02 :", + " Founder : \\x02{founder}\\x02": " Fondateur : \\x02{founder}\\x02", + "Removed \\x02{target}\\x02 from \\x02{name}\\x02.": "\\x02{target}\\x02 a été retiré de \\x02{name}\\x02.", + " \\x02{n}\\x02": " \\x02{n}\\x02", + "HostServ gives you a virtual host (vhost). Activate an assigned one, pick one from the menu, or request one from an operator.": "HostServ vous fournit un hôte virtuel (vhost). Activez celui qui vous est attribué, choisissez-en un dans le menu, ou demandez-en un à un opérateur.", + "activate your vhost": "activer votre vhost", + "Syntax: \u0002ON\u0002\nActivates your assigned vhost on your host.": "Syntaxe : \u0002ON\u0002\nActive le vhost qui vous est attribué sur votre hôte.", + "restore your normal host": "rétablir votre hôte normal", + "Syntax: \u0002OFF\u0002\nRestores your normal host.": "Syntaxe : \u0002OFF\u0002\nRétablit votre hôte normal.", + "request a vhost": "demander un vhost", + "Syntax: \u0002REQUEST \u0002\nAsks an operator to approve a vhost for you.": "Syntaxe : \u0002REQUEST \u0002\nDemande à un opérateur d'approuver un vhost pour vous.", + "show the vhost menu": "afficher le menu des vhosts", + "Syntax: \u0002OFFERLIST\u0002\nShows the self-serve vhost menu.": "Syntaxe : \u0002OFFERLIST\u0002\nAffiche le menu des vhosts en libre-service.", + "take a vhost from the menu": "prendre un vhost dans le menu", + "Syntax: \u0002TAKE \u0002\nTakes a vhost from the menu (see OFFERLIST).": "Syntaxe : \u0002TAKE \u0002\nPrend un vhost dans le menu (voir OFFERLIST).", + "assign a vhost (operator)": "attribuer un vhost (opérateur)", + "Syntax: \u0002SET [duration]\u0002\nAssigns a vhost to an account. Operators only.": "Syntaxe : \u0002SET [duration]\u0002\nAttribue un vhost à un compte. Opérateurs uniquement.", + "remove a vhost (operator)": "supprimer un vhost (opérateur)", + "Syntax: \u0002DEL \u0002\nRemoves an account's vhost. Operators only.": "Syntaxe : \u0002DEL \u0002\nSupprime le vhost d'un compte. Opérateurs uniquement.", + "list vhosts (operator)": "lister les vhosts (opérateur)", + "Syntax: \u0002LIST\u0002\nLists assigned vhosts. Operators only.": "Syntaxe : \u0002LIST\u0002\nListe les vhosts attribués. Opérateurs uniquement.", + "pending requests (operator)": "demandes en attente (opérateur)", + "Syntax: \u0002WAITING\u0002\nLists pending vhost requests. Operators only.": "Syntaxe : \u0002WAITING\u0002\nListe les demandes de vhost en attente. Opérateurs uniquement.", + "approve a request (operator)": "approuver une demande (opérateur)", + "Syntax: \u0002ACTIVATE \u0002\nApproves a pending vhost request. Operators only.": "Syntaxe : \u0002ACTIVATE \u0002\nApprouve une demande de vhost en attente. Opérateurs uniquement.", + "reject a request (operator)": "refuser une demande (opérateur)", + "Syntax: \u0002REJECT \u0002\nRejects a pending vhost request. Operators only.": "Syntaxe : \u0002REJECT \u0002\nRefuse une demande de vhost en attente. Opérateurs uniquement.", + "add a menu vhost (operator)": "ajouter un vhost au menu (opérateur)", + "Syntax: \u0002OFFER \u0002\nAdds a vhost to the self-serve menu. Operators only.": "Syntaxe : \u0002OFFER \u0002\nAjoute un vhost au menu en libre-service. Opérateurs uniquement.", + "remove a menu vhost (operator)": "retirer un vhost du menu (opérateur)", + "Syntax: \u0002OFFERDEL \u0002\nRemoves a menu entry (see OFFERLIST). Operators only.": "Syntaxe : \u0002OFFERDEL \u0002\nRetire une entrée du menu (voir OFFERLIST). Opérateurs uniquement.", + "forbid a vhost pattern (operator)": "interdire un motif de vhost (opérateur)", + "Syntax: \u0002FORBID \u0002\nForbids vhosts matching a pattern. Operators only.": "Syntaxe : \u0002FORBID \u0002\nInterdit les vhosts correspondant à un motif. Opérateurs uniquement.", + "remove a forbidden pattern (operator)": "retirer un motif interdit (opérateur)", + "Syntax: \u0002FORBIDDEL \u0002\nRemoves a forbidden pattern (see FORBIDLIST). Operators only.": "Syntaxe : \u0002FORBIDDEL \u0002\nRetire un motif interdit (voir FORBIDLIST). Opérateurs uniquement.", + "Your vhost already applies to all your grouped nicks — nothing to sync.": "Votre vhost s'applique déjà à tous vos pseudos groupés — rien à synchroniser.", + "\u0002{host}\u0002 isn't a valid host (letters, digits, hyphens and dots).": "\u0002{host}\u0002 n'est pas un hôte valide (lettres, chiffres, traits d'union et points).", + "\u0002{host}\u0002 is already in use. Please choose another.": "\u0002{host}\u0002 est déjà utilisé. Veuillez en choisir un autre.", + "assigning vhosts": "attribuer des vhosts", + "You need to identify to NickServ first.": "Vous devez d'abord vous identifier auprès de NickServ.", + "Your vhost \u0002{host}\u0002 is now active.": "Votre vhost \u0002{host}\u0002 est désormais actif.", + "You have no vhost assigned.": "Aucun vhost ne vous est attribué.", + "Your vhost is off; your normal host is restored.": "Votre vhost est désactivé ; votre hôte normal est rétabli.", + "Syntax: SET [duration]": "Syntaxe : SET [duration]", + "\u0002{account}\u0002 isn't registered.": "\u0002{account}\u0002 n'est pas enregistré.", + " (expires in {d})": " (expire dans {d})", + "Vhost \u0002{host}\u0002 assigned to \u0002{account}\u0002{when}.": "Vhost \u0002{host}\u0002 attribué à \u0002{account}\u0002{when}.", + "Syntax: DEL ": "Syntaxe : DEL ", + "Vhost for \u0002{account}\u0002 removed.": "Vhost de \u0002{account}\u0002 supprimé.", + "\u0002{account}\u0002 has no vhost.": "\u0002{account}\u0002 n'a aucun vhost.", + "No vhosts have been assigned.": "Aucun vhost n'a été attribué.", + "Assigned vhosts ({count}):": "Vhosts attribués ({count}) :", + ", temporary": ", temporaire", + " \u0002{account}\u0002 — {host} (by {setter}{temp})": " \u0002{account}\u0002 — {host} (par {setter}{temp})", + "Syntax: REQUEST ": "Syntaxe : REQUEST ", + "\u0002{host}\u0002 isn't allowed here. Please choose another.": "\u0002{host}\u0002 n'est pas autorisé ici. Veuillez en choisir un autre.", + "Please wait \u0002{wait}\u0002s before requesting another vhost.": "Veuillez patienter \u0002{wait}\u0002 s avant de demander un autre vhost.", + "Requested vhost \u0002{host}\u0002 — an operator will review it.": "Vhost \u0002{host}\u0002 demandé — un opérateur l'examinera.", + "No vhost requests are waiting.": "Aucune demande de vhost en attente.", + "Pending vhost requests ({count}):": "Demandes de vhost en attente ({count}) :", + " \u0002{account}\u0002 — {host}": " \u0002{account}\u0002 — {host}", + "Approve with \u0002ACTIVATE\u0002 or turn down with \u0002REJECT\u0002 .": "Approuvez avec \u0002ACTIVATE\u0002 ou refusez avec \u0002REJECT\u0002 .", + "Syntax: ACTIVATE ": "Syntaxe : ACTIVATE ", + "Syntax: REJECT ": "Syntaxe : REJECT ", + "\u0002{account}\u0002 has no pending vhost request.": "\u0002{account}\u0002 n'a aucune demande de vhost en attente.", + "Rejected \u0002{account}\u0002's vhost request.": "Demande de vhost de \u0002{account}\u0002 refusée.", + "Can't activate: {msg}": "Activation impossible : {msg}", + "Can't activate: \u0002{host}\u0002 is on the forbidden list.": "Activation impossible : \u0002{host}\u0002 figure sur la liste des interdits.", + "Activated vhost \u0002{host}\u0002 for \u0002{account}\u0002.": "Vhost \u0002{host}\u0002 activé pour \u0002{account}\u0002.", + "Syntax: OFFER ": "Syntaxe : OFFER ", + "\u0002{host}\u0002 isn't a valid host.": "\u0002{host}\u0002 n'est pas un hôte valide.", + "\u0002{host}\u0002 is now on the vhost menu.": "\u0002{host}\u0002 figure désormais au menu des vhosts.", + "That vhost is already on the menu.": "Ce vhost est déjà au menu.", + "No vhosts are on offer.": "Aucun vhost n'est proposé.", + "Vhosts on offer ({count}):": "Vhosts proposés ({count}) :", + " {n}. {host}": " {n}. {host}", + "Take one with \u0002TAKE\u0002 .": "Prenez-en un avec \u0002TAKE\u0002 .", + "Syntax: OFFERDEL (see OFFERLIST)": "Syntaxe : OFFERDEL (voir OFFERLIST)", + "Removed \u0002{host}\u0002 from the menu.": "\u0002{host}\u0002 retiré du menu.", + "There's no offer #\u0002{n}\u0002.": "Il n'y a aucune offre n°\u0002{n}\u0002.", + "Syntax: TAKE (see OFFERLIST)": "Syntaxe : TAKE (voir OFFERLIST)", + "There's no offer #\u0002{n}\u0002. See \u0002OFFERLIST\u0002.": "Il n'y a aucune offre n°\u0002{n}\u0002. Voir \u0002OFFERLIST\u0002.", + "You now have the vhost \u0002{host}\u0002.": "Vous avez désormais le vhost \u0002{host}\u0002.", + "Syntax: FORBID ": "Syntaxe : FORBID ", + "Forbidden vhost pattern added: {pattern}": "Motif de vhost interdit ajouté : {pattern}", + "That pattern is already forbidden.": "Ce motif est déjà interdit.", + "\u0002{pattern}\u0002 isn't a valid regular expression.": "\u0002{pattern}\u0002 n'est pas une expression régulière valide.", + "No vhost patterns are forbidden.": "Aucun motif de vhost n'est interdit.", + "Forbidden vhost patterns ({count}):": "Motifs de vhost interdits ({count}) :", + " {n}. {p}": " {n}. {p}", + "Syntax: FORBIDDEL (see FORBIDLIST)": "Syntaxe : FORBIDDEL (voir FORBIDLIST)", + "Removed forbidden pattern: {pattern}": "Motif interdit supprimé : {pattern}", + "There's no forbidden pattern #\u0002{n}\u0002.": "Il n'y a aucun motif interdit n°\u0002{n}\u0002.", + "Auto-vhost template: \u0002{tmpl}\u0002. Users apply it with \u0002DEFAULT\u0002.": "Modèle de vhost automatique : \u0002{tmpl}\u0002. Les utilisateurs l'appliquent avec \u0002DEFAULT\u0002.", + "No auto-vhost template is set.": "Aucun modèle de vhost automatique n'est défini.", + "Auto-vhost template cleared.": "Modèle de vhost automatique effacé.", + "The template must contain \u0002$account\u0002 and form a valid host, e.g. \u0002$account.users.example\u0002.": "Le modèle doit contenir \u0002$account\u0002 et former un hôte valide, par ex. \u0002$account.users.example\u0002.", + "Auto-vhost template set to \u0002{template}\u0002.": "Modèle de vhost automatique défini sur \u0002{template}\u0002.", + "This network has no auto-vhost template.": "Ce réseau n'a aucun modèle de vhost automatique.", + "Your account name has no usable characters for a vhost.": "Votre nom de compte ne contient aucun caractère utilisable pour un vhost.", + "Sorry, a vhost couldn't be generated for your account.": "Désolé, aucun vhost n'a pu être généré pour votre compte.", + "HelpServ is the help desk and the network's help index. Open a ticket with \u0002REQUEST\u0002; operators work the queue.": "HelpServ est le service d'assistance et l'index d'aide du réseau. Ouvrez un ticket avec \u0002REQUEST\u0002 ; les opérateurs traitent la file.", + "open a help-desk ticket": "ouvrir un ticket d'assistance", + "Syntax: \u0002REQUEST \u0002\nOpens a ticket for the staff. Also \u0002HELPME\u0002.": "Syntaxe : \u0002REQUEST \u0002\nOuvre un ticket pour le personnel. Aussi \u0002HELPME\u0002.", + "withdraw your ticket": "retirer votre ticket", + "Syntax: \u0002CANCEL\u0002\nWithdraws your own newest open ticket.": "Syntaxe : \u0002CANCEL\u0002\nRetire votre ticket ouvert le plus récent.", + "list the ticket queue": "lister la file des tickets", + "Syntax: \u0002LIST [ALL]\u0002\nOperators: list open tickets, or every ticket with ALL.": "Syntaxe : \u0002LIST [ALL]\u0002\nOpérateurs : liste les tickets ouverts, ou tous les tickets avec ALL.", + "read a ticket": "lire un ticket", + "Syntax: \u0002VIEW \u0002\nOperators: read a ticket in full. Also \u0002READ\u0002.": "Syntaxe : \u0002VIEW \u0002\nOpérateurs : lit un ticket en entier. Aussi \u0002READ\u0002.", + "claim a ticket": "prendre en charge un ticket", + "Syntax: \u0002TAKE \u0002\nOperators: claim a specific ticket. Also \u0002ASSIGN\u0002.": "Syntaxe : \u0002TAKE \u0002\nOpérateurs : prend en charge un ticket précis. Aussi \u0002ASSIGN\u0002.", + "claim the oldest ticket": "prendre en charge le ticket le plus ancien", + "Syntax: \u0002NEXT\u0002\nOperators: claim the oldest unassigned ticket.": "Syntaxe : \u0002NEXT\u0002\nOpérateurs : prend en charge le plus ancien ticket non attribué.", + "resolve a ticket": "résoudre un ticket", + "Syntax: \u0002CLOSE \u0002\nOperators: resolve a ticket. Also \u0002RESOLVE\u0002.": "Syntaxe : \u0002CLOSE \u0002\nOpérateurs : résout un ticket. Aussi \u0002RESOLVE\u0002.", + "For a service's own commands, type \u0002HELP \u0002. Services: {services}.": "Pour les commandes propres à un service, tapez \u0002HELP \u0002. Services : {services}.", + "For the extended ban types you can use, type \u0002HELP EXTBANS\u0002.": "Pour les types de bannissements étendus utilisables, tapez \u0002HELP EXTBANS\u0002.", + "I don't know \u0002{name}\u0002. Try \u0002REQUEST\u0002 , \u0002HELP\u0002, or a service name (e.g. \u0002NickServ\u0002).": "Je ne connais pas \u0002{name}\u0002. Essayez \u0002REQUEST\u0002 , \u0002HELP\u0002, ou un nom de service (par ex. \u0002NickServ\u0002).", + "You took ticket \u0002#{id}\u0002: {msg}": "Vous avez pris le ticket \u0002#{id}\u0002 : {msg}", + "Ticket \u0002#{id}\u0002 isn't open (or doesn't exist).": "Le ticket \u0002#{id}\u0002 n'est pas ouvert (ou n'existe pas).", + "working the help queue": "traiter la file d'assistance", + "Your request \u0002#{id}\u0002 has been cancelled.": "Votre demande \u0002#{id}\u0002 a été annulée.", + "You have no open request to cancel.": "Vous n'avez aucune demande ouverte à annuler.", + "Syntax: CLOSE ": "Syntaxe : CLOSE ", + "Ticket \u0002#{id}\u0002 closed.": "Ticket \u0002#{id}\u0002 fermé.", + "Extended bans (\u0002extbans\u0002) match users by more than nick!user@host.": "Les bannissements étendus (\u0002extbans\u0002) ciblent les utilisateurs au-delà de nick!user@host.", + "Use one where a ban mask goes: \u0002/mode #chan +b \u0002 (also +e/+I), or in \u0002ChanServ AKICK\u0002 (matching types only).": "Utilisez-en un là où va un masque de bannissement : \u0002/mode #chan +b \u0002 (aussi +e/+I), ou dans \u0002ChanServ AKICK\u0002 (types de correspondance uniquement).", + "Write them by name or letter — \u0002account:bad\u0002 is the same as \u0002R:bad\u0002 — and prefix \u0002!\u0002 to invert (match everyone except).": "Écrivez-les par nom ou par lettre — \u0002account:bad\u0002 équivaut à \u0002R:bad\u0002 — et préfixez \u0002!\u0002 pour inverser (cibler tout le monde sauf).", + "\u0002Extban types\u0002 (your network's exact set is confirmed on link):": "\u0002Types d'extban\u0002 (l'ensemble exact de votre réseau est confirmé à la connexion) :", + "\u0002Matching\u0002 — match who a user is (work in AKICK and bans):": "\u0002Correspondance\u0002 — cible qui est un utilisateur (fonctionne dans AKICK et les bannissements) :", + "\u0002Acting\u0002 — restrict what a user can do (bans only):": "\u0002Action\u0002 — restreint ce qu'un utilisateur peut faire (bannissements uniquement) :", + "ChanServ accepts only the extbans this network offers and hasn't disabled.": "ChanServ n'accepte que les extbans que ce réseau propose et n'a pas désactivés.", + " \u0002{name}\u0002 (\u0002{letter}\u0002) — {desc}": " \u0002{name}\u0002 (\u0002{letter}\u0002) — {desc}", + " \u0002{name}\u0002 (\u0002{letter}\u0002)": " \u0002{name}\u0002 (\u0002{letter}\u0002)", + " \u0002{name}\u0002 — {desc}": " \u0002{name}\u0002 — {desc}", + "No open tickets.": "Aucun ticket ouvert.", + "No tickets.": "Aucun ticket.", + " (closed)": " (fermé)", + " (taken by {handler})": " (pris par {handler})", + "\u0002#{id}\u0002 {requester} — {short}{state}": "\u0002#{id}\u0002 {requester} — {short}{state}", + "{count} ticket(s). \u0002VIEW\u0002 for detail.": "{count} ticket(s). \u0002VIEW\u0002 pour le détail.", + "No unassigned tickets are waiting.": "Aucun ticket non attribué en attente.", + "Tell us what you need help with: REQUEST ": "Dites-nous ce pour quoi vous avez besoin d'aide : REQUEST ", + "Thanks — your request (\u0002#{id}\u0002) is in the queue. A staff member will be with you.": "Merci — votre demande (\u0002#{id}\u0002) est dans la file. Un membre du personnel va vous répondre.", + "You just opened a ticket — please wait a moment before opening another.": "Vous venez d'ouvrir un ticket — veuillez patienter un instant avant d'en ouvrir un autre.", + "Syntax: TAKE ": "Syntaxe : TAKE ", + "No such ticket. Syntax: VIEW ": "Ticket introuvable. Syntaxe : VIEW ", + "closed": "fermé", + "taken": "pris en charge", + "open": "ouvert", + "Ticket \u0002#{id}\u0002 ({state}):": "Ticket \u0002#{id}\u0002 ({state}) :", + " From : \u0002{requester}\u0002": " De : \u0002{requester}\u0002", + " Handler : \u0002{handler}\u0002": " Agent : \u0002{handler}\u0002", + " Opened : {when}": " Ouvert : {when}", + " Message : {msg}": " Message : {msg}", + "InfoServ holds the network's information bulletins: public ones show on connect, oper ones on login.": "InfoServ gère les bulletins d'information du réseau : les publics s'affichent à la connexion, ceux des opérateurs à l'authentification.", + "post a public bulletin": "publier un bulletin public", + "Syntax: \u0002POST \u0002\nAdds a public bulletin, shown to everyone on connect. Admin only. Also \u0002ADD\u0002.": "Syntaxe : \u0002POST \u0002\nAjoute un bulletin public, affiché à tout le monde à la connexion. Réservé aux administrateurs. Aussi \u0002ADD\u0002.", + "show public bulletins": "afficher les bulletins publics", + "Syntax: \u0002LIST\u0002\nShows the public bulletins. Open to everyone.": "Syntaxe : \u0002LIST\u0002\nAffiche les bulletins publics. Ouvert à tous.", + "remove a public bulletin": "supprimer un bulletin public", + "Syntax: \u0002DEL \u0002\nRemoves a public bulletin by its listed number. Admin only. Also \u0002REMOVE\u0002.": "Syntaxe : \u0002DEL \u0002\nSupprime un bulletin public d'après son numéro dans la liste. Réservé aux administrateurs. Aussi \u0002REMOVE\u0002.", + "post an oper bulletin": "publier un bulletin opérateur", + "Syntax: \u0002OPOST \u0002\nAdds an oper bulletin, shown to operators on login. Admin only.": "Syntaxe : \u0002OPOST \u0002\nAjoute un bulletin opérateur, affiché aux opérateurs à l'authentification. Réservé aux administrateurs.", + "show oper bulletins": "afficher les bulletins opérateur", + "Syntax: \u0002OLIST\u0002\nShows the oper bulletins. Operators only.": "Syntaxe : \u0002OLIST\u0002\nAffiche les bulletins opérateur. Réservé aux opérateurs.", + "remove an oper bulletin": "supprimer un bulletin opérateur", + "Syntax: \u0002ODEL \u0002\nRemoves an oper bulletin by its listed number. Admin only.": "Syntaxe : \u0002ODEL \u0002\nSupprime un bulletin opérateur d'après son numéro dans la liste. Réservé aux administrateurs.", + "I don't know \u0002{other}\u0002. Try \u0002LIST\u0002 or \u0002HELP\u0002.": "Je ne connais pas \u0002{other}\u0002. Essayez \u0002LIST\u0002 ou \u0002HELP\u0002.", + "Access denied — posting bulletins is for services operators.": "Accès refusé — la publication de bulletins est réservée aux opérateurs des services.", + "Syntax: {cmd} ": "Syntaxe : {cmd} ", + "Added a \u0002{which}\u0002 bulletin.": "Bulletin \u0002{which}\u0002 ajouté.", + "Access denied — that command is for services operators.": "Accès refusé — cette commande est réservée aux opérateurs des services.", + "Syntax: {cmd} ": "Syntaxe : {cmd} ", + "Removed \u0002{which}\u0002 bulletin \u0002{n}\u0002.": "Bulletin \u0002{which}\u0002 \u0002{n}\u0002 supprimé.", + "There's no \u0002{which}\u0002 bulletin \u0002{n}\u0002.": "Il n'y a pas de bulletin \u0002{which}\u0002 \u0002{n}\u0002.", + "Access denied — oper bulletins are for services operators.": "Accès refusé — les bulletins opérateur sont réservés aux opérateurs des services.", + "There are no {which} bulletins.": "Il n'y a aucun bulletin {which}.", + "{num}. {text} — by {by}": "{num}. {text} — par {by}", + "End of {which} bulletins ({count} shown).": "Fin des bulletins {which} ({count} affichés).", + "ReportServ takes abuse reports. Anyone can \u0002REPORT\u0002; operators review the queue.": "ReportServ recueille les signalements d'abus. Tout le monde peut utiliser \u0002REPORT\u0002 ; les opérateurs examinent la file.", + "file an abuse report": "signaler un abus", + "Syntax: \u0002REPORT \u0002\nTells the staff about a problem. Rate-limited.": "Syntaxe : \u0002REPORT \u0002\nSignale un problème à l'équipe. Débit limité.", + "list reports": "lister les signalements", + "Syntax: \u0002LIST [ALL]\u0002\nOperators: list open reports, or every report with ALL.": "Syntaxe : \u0002LIST [ALL]\u0002\nOpérateurs : liste les signalements ouverts, ou tous avec ALL.", + "read a report": "lire un signalement", + "Syntax: \u0002VIEW \u0002\nOperators: read a report in full. Also \u0002READ\u0002.": "Syntaxe : \u0002VIEW \u0002\nOpérateurs : lit un signalement en entier. Aussi \u0002READ\u0002.", + "resolve a report": "résoudre un signalement", + "Syntax: \u0002CLOSE \u0002\nOperators: mark a report resolved. Also \u0002RESOLVE\u0002.": "Syntaxe : \u0002CLOSE \u0002\nOpérateurs : marque un signalement comme résolu. Aussi \u0002RESOLVE\u0002.", + "delete a report": "supprimer un signalement", + "Syntax: \u0002DEL \u0002\nOperators: delete a report outright. Also \u0002REMOVE\u0002.": "Syntaxe : \u0002DEL \u0002\nOpérateurs : supprime définitivement un signalement. Aussi \u0002REMOVE\u0002.", + "I don't know \u0002{other}\u0002. Try \u0002REPORT\u0002 or \u0002HELP\u0002.": "Je ne connais pas \u0002{other}\u0002. Essayez \u0002REPORT\u0002 ou \u0002HELP\u0002.", + "reviewing reports": "examiner les signalements", + "Syntax: REPORT ": "Syntaxe : REPORT ", + "Please say what the problem is: REPORT ": "Veuillez indiquer quel est le problème : REPORT ", + "Thanks — your report (\u0002#{id}\u0002) about \u0002{target}\u0002 has been sent to the staff.": "Merci — votre signalement (\u0002#{id}\u0002) concernant \u0002{target}\u0002 a été transmis à l'équipe.", + "You just filed a report — please wait a moment before filing another.": "Vous venez de déposer un signalement — veuillez patienter un instant avant d'en déposer un autre.", + "No such report. Syntax: VIEW ": "Signalement introuvable. Syntaxe : VIEW ", + "Report \u0002#{id}\u0002 ({state}):": "Signalement \u0002#{id}\u0002 ({state}) :", + " By : \u0002{by}\u0002": " Par : \u0002{by}\u0002", + " About : \u0002{target}\u0002": " Cible : \u0002{target}\u0002", + " Filed : {when}": " Déposé : {when}", + " Reason : {reason}": " Motif : {reason}", + "Report \u0002#{n}\u0002 closed.": "Signalement \u0002#{n}\u0002 fermé.", + "Report \u0002#{n}\u0002 isn't open (or doesn't exist).": "Le signalement \u0002#{n}\u0002 n'est pas ouvert (ou n'existe pas).", + "Syntax: DEL ": "Syntaxe : DEL ", + "Report \u0002#{n}\u0002 deleted.": "Signalement \u0002#{n}\u0002 supprimé.", + "There's no report \u0002#{n}\u0002.": "Il n'y a pas de signalement \u0002#{n}\u0002.", + "No open reports.": "Aucun signalement ouvert.", + "No reports.": "Aucun signalement.", + "\u0002#{id}\u0002 {reporter} → \u0002{target}\u0002: {short}{flag}": "\u0002#{id}\u0002 {reporter} → \u0002{target}\u0002 : {short}{flag}", + "{n} report(s). \u0002VIEW\u0002 for detail.": "{n} signalement(s). \u0002VIEW\u0002 pour le détail.", + "StatServ reports statistics: \u0002SERVER\u0002 for network-wide counters (operators), or a \u0002#channel\u0002 for its activity (founder).": "StatServ fournit des statistiques : \u0002SERVER\u0002 pour les compteurs à l'échelle du réseau (opérateurs), ou un \u0002#channel\u0002 pour son activité (fondateur).", + "network-wide statistics": "statistiques à l'échelle du réseau", + "Syntax: \u0002SERVER\u0002\nShows network-wide counters. Operators only. Also \u0002GLOBAL\u0002.": "Syntaxe : \u0002SERVER\u0002\nAffiche les compteurs à l'échelle du réseau. Opérateurs uniquement. Aussi \u0002GLOBAL\u0002.", + "a channel's statistics": "les statistiques d'un salon", + "Syntax: \u0002<#channel>\u0002\nShows a channel's activity statistics. Available to the channel's founder.": "Syntaxe : \u0002<#channel>\u0002\nAffiche les statistiques d'activité d'un salon. Disponible pour le fondateur du salon.", + "I don't know \u0002{other}\u0002. Try \u0002SERVER\u0002, a \u0002#channel\u0002, or \u0002HELP\u0002.": "Je ne connais pas \u0002{other}\u0002. Essayez \u0002SERVER\u0002, un \u0002#channel\u0002, ou \u0002HELP\u0002.", + "\u0002{chan}\u0002 isn't registered.": "\u0002{chan}\u0002 n'est pas enregistré.", + "Only \u0002{chan}\u0002's founder can see its stats.": "Seul le fondateur de \u0002{chan}\u0002 peut voir ses statistiques.", + "No activity recorded for \u0002{chan}\u0002 yet.": "Aucune activité encore enregistrée pour \u0002{chan}\u0002.", + "\u0002{chan}\u0002 — \u0002{lines}\u0002 line(s) seen.": "\u0002{chan}\u0002 — \u0002{lines}\u0002 ligne(s) vue(s).", + "Top talkers:": "Les plus bavards :", + " {n}. \u0002{nick}\u0002 — {count}": " {n}. \u0002{nick}\u0002 — {count}", + "Network statistics are for services operators.": "Les statistiques du réseau sont réservées aux opérateurs des services.", + "Network statistics:": "Statistiques du réseau :", + " (no activity counters yet)": " (aucun compteur d'activité pour le moment)", + " games:": " jeux :", + " {ty}: {games} games, {n} players": " {ty} : {games} parties, {n} joueurs" } \ No newline at end of file diff --git a/modules/chanfix/src/fix.rs b/modules/chanfix/src/fix.rs index 3cf264b..3ccb2c1 100644 --- a/modules/chanfix/src/fix.rs +++ b/modules/chanfix/src/fix.rs @@ -1,4 +1,4 @@ -use echo_api::{NetView, Sender, ServiceCtx, Store}; +use echo_api::{t, NetView, Sender, ServiceCtx, Store}; // A channel with this many ops isn't opless and needs no fix. const OP_THRESHOLD: usize = 3; @@ -16,17 +16,17 @@ pub fn handle(me: &str, from: &Sender, chan: Option<&str>, ctx: &mut ServiceCtx, }; // Defer to ChanServ for anything it owns. if db.channel(chan).is_some() { - ctx.notice(me, from.uid, format!("\x02{chan}\x02 is registered — use \x02ChanServ\x02 to manage it.")); + ctx.notice(me, from.uid, t!(ctx, "\x02{chan}\x02 is registered — use \x02ChanServ\x02 to manage it.", chan = chan)); return; } if net.op_count(chan) >= OP_THRESHOLD { - ctx.notice(me, from.uid, format!("\x02{chan}\x02 already has ops — nothing to fix.")); + ctx.notice(me, from.uid, t!(ctx, "\x02{chan}\x02 already has ops — nothing to fix.", chan = chan)); return; } let scores = net.chanfix_scores(chan); let highscore = scores.first().map(|(_, s)| *s).unwrap_or(0); if highscore < MIN_FIX_SCORE { - ctx.notice(me, from.uid, format!("\x02{chan}\x02 doesn't have enough op-time history to fix yet.")); + ctx.notice(me, from.uid, t!(ctx, "\x02{chan}\x02 doesn't have enough op-time history to fix yet.", chan = chan)); return; } let threshold = ((highscore as f64 * FIX_STEP) as u32).max(1); @@ -47,8 +47,8 @@ pub fn handle(me: &str, from: &Sender, chan: Option<&str>, ctx: &mut ServiceCtx, } } if opped == 0 { - ctx.notice(me, from.uid, format!("None of \x02{chan}\x02's trusted regulars are here right now.")); + ctx.notice(me, from.uid, t!(ctx, "None of \x02{chan}\x02's trusted regulars are here right now.", chan = chan)); } else { - ctx.notice(me, from.uid, format!("Reopped \x02{opped}\x02 trusted regular(s) in \x02{chan}\x02.")); + ctx.notice(me, from.uid, t!(ctx, "Reopped \x02{opped}\x02 trusted regular(s) in \x02{chan}\x02.", opped = opped, chan = chan)); } } diff --git a/modules/chanfix/src/lib.rs b/modules/chanfix/src/lib.rs index 0c570d0..820a87e 100644 --- a/modules/chanfix/src/lib.rs +++ b/modules/chanfix/src/lib.rs @@ -6,7 +6,7 @@ //! SCORES <#channel> shows the standings; CHANFIX <#channel> performs the fix. //! `lib.rs` holds the dispatcher; each command lives in its own file. -use echo_api::{HelpEntry, NetView, Sender, Service, ServiceCtx, Store}; +use echo_api::{t, HelpEntry, NetView, Sender, Service, ServiceCtx, Store}; #[path = "scores.rs"] mod scores; @@ -58,7 +58,7 @@ impl Service for ChanFix { Some("SCORES") => scores::handle(me, from, args.get(1).copied(), ctx, net), Some("CHANFIX") | Some("FIX") => fix::handle(me, from, args.get(1).copied(), ctx, net, db), Some("HELP") | None => echo_api::help(me, from, ctx, BLURB, TOPICS, args.get(1).copied()), - Some(other) => ctx.notice(me, from.uid, format!("I don't know \x02{other}\x02. Try \x02SCORES\x02 or \x02CHANFIX\x02 <#channel>.")), + Some(other) => ctx.notice(me, from.uid, t!(ctx, "I don't know \x02{other}\x02. Try \x02SCORES\x02 or \x02CHANFIX\x02 <#channel>.", other = other)), } } } diff --git a/modules/chanfix/src/scores.rs b/modules/chanfix/src/scores.rs index 5f4e991..15dc1a5 100644 --- a/modules/chanfix/src/scores.rs +++ b/modules/chanfix/src/scores.rs @@ -1,4 +1,4 @@ -use echo_api::{NetView, Sender, ServiceCtx}; +use echo_api::{t, NetView, Sender, ServiceCtx}; // SCORES <#channel>: show the op-time standings ChanFix would reop from. pub fn handle(me: &str, from: &Sender, chan: Option<&str>, ctx: &mut ServiceCtx, net: &dyn NetView) { @@ -8,11 +8,11 @@ pub fn handle(me: &str, from: &Sender, chan: Option<&str>, ctx: &mut ServiceCtx, }; let scores = net.chanfix_scores(chan); if scores.is_empty() { - ctx.notice(me, from.uid, format!("No op-time recorded for \x02{chan}\x02 yet.")); + ctx.notice(me, from.uid, t!(ctx, "No op-time recorded for \x02{chan}\x02 yet.", chan = chan)); return; } for (id, score) in scores.iter().take(15) { - ctx.notice(me, from.uid, format!(" \x02{score}\x02 {id}")); + ctx.notice(me, from.uid, t!(ctx, " \x02{score}\x02 {id}", score = score, id = id)); } - ctx.notice(me, from.uid, format!("Top {} of {} scored identit{} for \x02{chan}\x02.", scores.len().min(15), scores.len(), if scores.len() == 1 { "y" } else { "ies" })); + ctx.notice(me, from.uid, t!(ctx, "Top {shown} of {total} scored identit{suffix} for \x02{chan}\x02.", shown = scores.len().min(15), total = scores.len(), suffix = if scores.len() == 1 { "y" } else { "ies" }, chan = chan)); } diff --git a/modules/gameserv/src/lib.rs b/modules/gameserv/src/lib.rs index 6e2feb6..c61130a 100644 --- a/modules/gameserv/src/lib.rs +++ b/modules/gameserv/src/lib.rs @@ -136,7 +136,7 @@ impl GameServ { return; }; let Some(tuid) = net.uid_by_nick(target).map(str::to_string) else { - ctx.notice(me, from.uid, format!("\x02{target}\x02 is not online.")); + ctx.notice(me, from.uid, t!(ctx, "\x02{target}\x02 is not online.", target = target)); return; }; let meid = Self::ident(from).to_string(); @@ -164,7 +164,7 @@ impl GameServ { // flooding a victim with offers to exhaust the victim's slots. let mine = self.games.values().filter(|g| g.acc_a == meid || (g.acc_b == meid && g.status == Status::Active)).count(); if mine >= MAX_GAMES_PER_USER { - ctx.notice(me, from.uid, format!("You have too many games in progress (max {MAX_GAMES_PER_USER}). Finish or resign one first.")); + ctx.notice(me, from.uid, t!(ctx, "You have too many games in progress (max {max}). Finish or resign one first.", max = MAX_GAMES_PER_USER)); return; } let id = self.nextid; @@ -180,8 +180,8 @@ impl GameServ { target.to_string(), ); self.games.insert(id, g); - ctx.notice(me, from.uid, format!("Challenge \x02#{id}\x02 ({}) sent to \x02{target}\x02.", gt.wire())); - ctx.notice(me, &tuid, format!("{} challenges you to {} (game #{id}). \x02/msg GamesServ ACCEPT {id}\x02", from.nick, gt.wire())); + ctx.notice(me, from.uid, t!(ctx, "Challenge \x02#{id}\x02 ({game}) sent to \x02{target}\x02.", id = id, game = gt.wire(), target = target)); + ctx.notice(me, &tuid, t!(ctx, "{challenger} challenges you to {game} (game #{id}). \x02/msg GamesServ ACCEPT {id}\x02", challenger = from.nick, game = gt.wire(), id = id)); let g = &self.games[&id]; push_one(g, Side::A, "pending", me, net, ctx); // challenger: waiting push_one(g, Side::B, "offer", me, net, ctx); // target: can accept/decline @@ -201,7 +201,7 @@ impl GameServ { g.status = Status::Active; g.nick_b = from.nick.to_string(); let glyph = g.glyph(Side::B); - ctx.notice(me, from.uid, format!("Game \x02#{id}\x02 started. You are \x02{glyph}\x02.")); + ctx.notice(me, from.uid, t!(ctx, "Game \x02#{id}\x02 started. You are \x02{glyph}\x02.", id = id, glyph = glyph)); push_state(&self.games[&id], me, net, ctx); } @@ -217,7 +217,7 @@ impl GameServ { }; let g = self.games.remove(&id).unwrap(); if let Some(auid) = net.uid_by_nick(&g.nick_a).map(str::to_string) { - ctx.notice(me, &auid, format!("{} declined your challenge #{id}.", from.nick)); + ctx.notice(me, &auid, t!(ctx, "{nick} declined your challenge #{id}.", nick = from.nick, id = id)); } ctx.notice(me, from.uid, "Declined."); } @@ -276,7 +276,7 @@ impl GameServ { return; } }; - ctx.notice(me, from.uid, format!("You resigned game #{id}.")); + ctx.notice(me, from.uid, t!(ctx, "You resigned game #{id}.", id = id)); self.finish(id, winner, me, net, ctx); } @@ -330,7 +330,7 @@ impl GameServ { for id in ids { let g = &self.games[&id]; let opp = if g.acc_a == meid { &g.nick_b } else { &g.nick_a }; - ctx.notice(me, from.uid, format!("#{} {} vs {} [{}]", g.id, g.gtype().wire(), opp, g.status.wire())); + ctx.notice(me, from.uid, t!(ctx, "#{id} {game} vs {opp} [{status}]", id = g.id, game = g.gtype().wire(), opp = opp, status = g.status.wire())); } } @@ -345,15 +345,15 @@ impl GameServ { }; let counters = net.stat_counters(); push_stats(&counters, &who, from.nick, me, net, ctx, None); // machine lines for the UI - ctx.notice(me, from.uid, format!("\x02{who}\x02 — classement Jeux")); + ctx.notice(me, from.uid, t!(ctx, "\x02{who}\x02 — classement Jeux", who = who)); let mut any = false; for gt in TYPES { let s = read_stats(&counters, gt, &who); if s.any() { any = true; - ctx.notice(me, from.uid, format!( - " \x02{}\x02 \x02{}\x02 — {} pts ({}V {}D {}N)", - gt.label(), s.rank(), s.points(), s.wins, s.losses, s.draws + ctx.notice(me, from.uid, t!(ctx, + " \x02{game}\x02 \x02{rank}\x02 — {pts} pts ({wins}V {losses}D {draws}N)", + game = gt.label(), rank = s.rank(), pts = s.points(), wins = s.wins, losses = s.losses, draws = s.draws )); } } @@ -392,13 +392,15 @@ impl GameServ { all.sort_by_key(|(_, s)| std::cmp::Reverse(s.points())); push_tag(me, net, from.nick, &format!("GS$TOPSTART {}", gt.wire()), ctx); if all.is_empty() { - ctx.notice(me, from.uid, format!("Classement \x02{}\x02 vide. Sois le premier à gagner !", gt.label())); + ctx.notice(me, from.uid, t!(ctx, "Classement \x02{game}\x02 vide. Sois le premier à gagner !", game = gt.label())); return; } - ctx.notice(me, from.uid, format!("\x02Classement {} :\x02", gt.label())); + ctx.notice(me, from.uid, t!(ctx, "\x02Classement {game} :\x02", game = gt.label())); for (rank, (acc, s)) in all.iter().take(10).enumerate() { let rank = rank + 1; - ctx.notice(me, from.uid, format!("{rank:2}. {acc:<16} {} {} pts", s.rank(), s.points())); + let pos = format!("{rank:2}"); + let name = format!("{acc:<16}"); + ctx.notice(me, from.uid, t!(ctx, "{pos}. {name} {tier} {pts} pts", pos = pos, name = name, tier = s.rank(), pts = s.points())); push_tag(me, net, from.nick, &format!("GS$TOPROW {} {rank} {acc} {} {}", gt.wire(), s.rank(), s.points()), ctx); } } @@ -481,7 +483,7 @@ impl Service for GameServ { Some("STATS") => self.do_stats(&me, from, args, ctx, net), Some("TOP") => self.do_top(&me, from, args, ctx, net), Some("HELP") | None => echo_api::help(&me, from, ctx, BLURB, TOPICS, args.get(1).copied()), - Some(other) => ctx.notice(&me, from.uid, format!("I don't know \x02{other}\x02. Try \x02HELP\x02.")), + Some(other) => ctx.notice(&me, from.uid, t!(ctx, "I don't know \x02{other}\x02. Try \x02HELP\x02.", other = other)), } } }