diff options
| -rw-r--r-- | Mailman/Bouncer.py | 38 | ||||
| -rw-r--r-- | Mailman/Deliverer.py | 12 | ||||
| -rw-r--r-- | Mailman/Digester.py | 34 | ||||
| -rw-r--r-- | Mailman/GatewayManager.py | 28 | ||||
| -rw-r--r-- | Mailman/ListAdmin.py | 15 | ||||
| -rw-r--r-- | Mailman/MailCommandHandler.py | 230 | ||||
| -rw-r--r-- | Mailman/MailList.py | 438 | ||||
| -rw-r--r-- | Mailman/htmlformat.py | 6 |
8 files changed, 410 insertions, 391 deletions
diff --git a/Mailman/Bouncer.py b/Mailman/Bouncer.py index de489f174..b78a2eff3 100644 --- a/Mailman/Bouncer.py +++ b/Mailman/Bouncer.py @@ -59,26 +59,26 @@ class Bouncer: def GetConfigInfo(self): return [ - "Policies regarding systematic processing of bounce messages," + _("Policies regarding systematic processing of bounce messages," " to help automate recognition and handling of defunct" - " addresses.", - ('bounce_processing', mm_cfg.Toggle, ('No', 'Yes'), 0, - 'Try to figure out error messages automatically? '), + " addresses."), + ('bounce_processing', mm_cfg.Toggle, (_('No'), _('Yes')), 0, + _('Try to figure out error messages automatically? ')), ('minimum_removal_date', mm_cfg.Number, 3, 0, - 'Minimum number of days an address has been non-fatally ' - 'bad before we take action'), + _('Minimum number of days an address has been non-fatally ' + 'bad before we take action')), ('minimum_post_count_before_bounce_action', mm_cfg.Number, 3, 0, - 'Minimum number of posts to the list since members first ' - 'bounce before we consider removing them from the list'), + _('Minimum number of posts to the list since members first ' + 'bounce before we consider removing them from the list')), ('max_posts_between_bounces', mm_cfg.Number, 3, 0, - "Maximum number of messages your list gets in an hour. " - "(Yes, bounce detection finds this info useful)"), + _("Maximum number of messages your list gets in an hour. " + "(Yes, bounce detection finds this info useful)")), ('automatic_bounce_action', mm_cfg.Radio, - ("Do nothing", - "Disable and notify me", - "Disable and DON'T notify me", - "Remove and notify me"), - 0, "Action when critical or excessive bounces are detected.") + (_("Do nothing"), + _("Disable and notify me"), + _("Disable and DON'T notify me"), + _("Remove and notify me")), + 0, _("Action when critical or excessive bounces are detected.")) ] def ClearBounceInfo(self, email): @@ -186,7 +186,7 @@ class Bouncer: did = "removed" if send: if succeeded != 1: - negative="not " + negative=_("not ") else: negative="" recipient = self.GetAdminEmail() @@ -234,7 +234,7 @@ class Bouncer: # We do this here so this text won't be wrapped. note that # 'bounce.txt' has a trailing newline. Be robust about getting # the body of the message. - body = '[original message unavailable]' + body = _('[original message unavailable]') try: body = msg.body except AttributeError: @@ -254,7 +254,7 @@ class Bouncer: # send the bounce message msg = Message.UserNotification( recipient, mm_cfg.MAILMAN_OWNER, - '%s member %s bouncing - %s%s' % (self.real_name, addr, + _('%s member %s bouncing - %s%s') % (self.real_name, addr, negative, did), text) msg['MIME-Version'] = '1.0' @@ -293,7 +293,7 @@ class Bouncer: Returning success and notification status.""" if not self.IsMember(addr): - reason = "User not found." + reason = _("User not found.") syslog("bounce", "%s: NOT removed %s: %s" % (self.real_name, addr, reason)) return reason, 1 diff --git a/Mailman/Deliverer.py b/Mailman/Deliverer.py index 9d59e69f5..c7547fb62 100644 --- a/Mailman/Deliverer.py +++ b/Mailman/Deliverer.py @@ -37,11 +37,11 @@ class Deliverer: else: welcome = '' if self.umbrella_list: - umbrella = Utils.wrap('''\ + umbrella = Utils.wrap(_('''\ Note: Since this is a list of mailing lists, administrative notices like the password reminder will be sent to your membership administrative address, %s. -''' % self.GetMemberAdminEmail(name)) +''') % self.GetMemberAdminEmail(name)) else: umbrella = '' # get the text from the template @@ -62,7 +62,7 @@ your membership administrative address, %s. digmode = '' msg = Message.UserNotification( self.GetMemberAdminEmail(name), self.GetRequestEmail(), - 'Welcome to the "%s" mailing list%s' % (self.real_name, digmode), + _('Welcome to the "%s" mailing list%s') % (self.real_name, digmode), text) msg['X-No-Archive'] = 'yes' HandlerAPI.DeliverToUser(self, msg) @@ -71,7 +71,7 @@ your membership administrative address, %s. def SendUnsubscribeAck(self, name): msg = Message.UserNotification( self.GetMemberAdminEmail(name), self.GetAdminEmail(), - 'Unsubscribed from "%s" mailing list' % self.real_name, + _('Unsubscribed from "%s" mailing list') % self.real_name, Utils.wrap(self.goodbye_msg)) HandlerAPI.DeliverToUser(self, msg) @@ -85,7 +85,7 @@ your membership administrative address, %s. if user and self.passwords.has_key(user): cpuser = self.GetUserSubscribedAddress(user) recipient = self.GetMemberAdminEmail(cpuser) - subject = '%s mailing list reminder' % listfullname + subject = _('%s mailing list reminder') % listfullname adminaddr = self.GetAdminEmail() # get the text from the template text = Utils.maketext( @@ -100,7 +100,7 @@ your membership administrative address, %s. else: ok = 0 recipient = self.GetAdminEmail() - subject = '%s user %s missing password!' % (listfullname, user) + subject = _('%s user %s missing password!') % (listfullname, user) text = Utils.maketext( 'nopass.txt', {'username' : `user`, diff --git a/Mailman/Digester.py b/Mailman/Digester.py index a42c2d3f7..b3d6acb9e 100644 --- a/Mailman/Digester.py +++ b/Mailman/Digester.py @@ -42,37 +42,37 @@ class Digester: WIDTH = mm_cfg.TEXTFIELDWIDTH return [ - "Batched-delivery digest characteristics.", + _("Batched-delivery digest characteristics."), - ('digestable', mm_cfg.Toggle, ('No', 'Yes'), 1, - 'Can list members choose to receive list traffic ' - 'bunched in digests?'), + ('digestable', mm_cfg.Toggle, (_('No'), _('Yes')), 1, + _('Can list members choose to receive list traffic ' + 'bunched in digests?')), ('digest_is_default', mm_cfg.Radio, - ('Regular', 'Digest'), 0, - 'Which delivery mode is the default for new users?'), + (_('Regular'), _('Digest')), 0, + _('Which delivery mode is the default for new users?')), ('mime_is_default_digest', mm_cfg.Radio, - ('Plain', 'Mime'), 0, - 'When receiving digests, which format is default?'), + (_('Plain'), _('MIME')), 0, + _('When receiving digests, which format is default?')), ('digest_size_threshhold', mm_cfg.Number, 3, 0, - 'How big in Kb should a digest be before it gets sent out?'), + _('How big in Kb should a digest be before it gets sent out?')), # Should offer a 'set to 0' for no size threshhold. - ('digest_send_periodic', mm_cfg.Radio, ('No', 'Yes'), 1, - 'Should a digest be dispatched daily when the size threshold ' - "isn't reached?"), + ('digest_send_periodic', mm_cfg.Radio, (_('No'), _('Yes')), 1, + _('Should a digest be dispatched daily when the size threshold ' + "isn't reached?")), ('digest_header', mm_cfg.Text, (4, WIDTH), 0, - 'Header added to every digest', - "Text attached (as an initial message, before the table" - " of contents) to the top of digests. " + _('Header added to every digest'), + _("Text attached (as an initial message, before the table" + " of contents) to the top of digests. ") + Utils.maketext('headfoot.html', raw=1)), ('digest_footer', mm_cfg.Text, (4, WIDTH), 0, - 'Footer added to every digest', - "Text attached (as a final message) to the bottom of digests. " + _('Footer added to every digest'), + _("Text attached (as a final message) to the bottom of digests. ") + Utils.maketext('headfoot.html', raw=1)), ] diff --git a/Mailman/GatewayManager.py b/Mailman/GatewayManager.py index f92e77da9..4d9c0fda3 100644 --- a/Mailman/GatewayManager.py +++ b/Mailman/GatewayManager.py @@ -37,31 +37,31 @@ class GatewayManager: WIDTH = mm_cfg.TEXTFIELDWIDTH return [ - 'Mail-to-News and News-to-Mail gateway services.', + _('Mail-to-News and News-to-Mail gateway services.'), ('nntp_host', mm_cfg.String, WIDTH, 0, - 'The Internet address of the machine your News server ' - 'is running on.', - 'The News server is not part of Mailman proper. You have to ' + _('The Internet address of the machine your News server ' + 'is running on.'), + _('The News server is not part of Mailman proper. You have to ' 'already have access to a NNTP server, and that NNTP server ' 'has to recognize the machine this mailing list runs on as ' - 'a machine capable of reading and posting news.'), + 'a machine capable of reading and posting news.')), ('linked_newsgroup', mm_cfg.String, WIDTH, 0, - 'The name of the Usenet group to gateway to and/or from.'), + _('The name of the Usenet group to gateway to and/or from.')), - ('gateway_to_news', mm_cfg.Toggle, ('No', 'Yes'), 0, - 'Should new posts to the mailing list be sent to the newsgroup?'), + ('gateway_to_news', mm_cfg.Toggle, (_('No'), _('Yes')), 0, + _('Should new posts to the mailing list be sent to the newsgroup?')), - ('gateway_to_mail', mm_cfg.Toggle, ('No', 'Yes'), 0, - 'Should new posts to the newsgroup be sent to the mailing list?'), + ('gateway_to_mail', mm_cfg.Toggle, (_('No'), _('Yes')), 0, + _('Should new posts to the newsgroup be sent to the mailing list?')), - ('_mass_catchup', mm_cfg.Toggle, ('No', 'Yes'), 0, - 'Should Mailman perform a <em>catchup</em> on the newsgroup?', - '''When you tell Mailman to perform a catchup on the newsgroup, + ('_mass_catchup', mm_cfg.Toggle, (_('No'), _('Yes')), 0, + _('Should Mailman perform a <em>catchup</em> on the newsgroup?'), + _('''When you tell Mailman to perform a catchup on the newsgroup, this means that you want to start gating messages to the mailing list with the next new message found. All earlier messages on the newsgroup will be ignored. This is as if you were reading the newsgroup yourself, and you marked all current messages as <em>read</em>. By catching up, your mailing list - members will not see any of the earlier messages.''') + members will not see any of the earlier messages.''')) ] diff --git a/Mailman/ListAdmin.py b/Mailman/ListAdmin.py index 2fd758747..c97e24aaf 100644 --- a/Mailman/ListAdmin.py +++ b/Mailman/ListAdmin.py @@ -168,7 +168,7 @@ class ListAdmin: # name of the file in $PREFIX/data containing the msg text # an additional dictionary of message metadata # - msgsubject = msg.get('subject', '(no subject)') + msgsubject = msg.get('subject', _('(no subject)')) data = time.time(), sender, msgsubject, reason, filename, msgdata self.__db[id] = (HELDMSG, data) @@ -222,8 +222,8 @@ class ListAdmin: elif value == mm_cfg.REJECT: # Rejected rejection = 'Refused' - self.__refuse('Posting of your message titled "%s"' % subject, - sender, comment or '[No reason given]') + self.__refuse(_('Posting of your message titled "%s"') % subject, + sender, comment or _('[No reason given]')) else: assert value == mm_cfg.DISCARD # Discarded @@ -305,7 +305,7 @@ class ListAdmin: (self.real_name, addr)) # possibly notify the administrator if self.admin_immed_notify: - subject = 'New subscription request to list %s from %s' % ( + subject = _('New subscription request to list %s from %s') % ( self.real_name, addr) text = Utils.maketext( 'subauth.txt', @@ -322,7 +322,7 @@ class ListAdmin: stime, addr, password, digest = record if value == mm_cfg.REJECT: # refused - self.__refuse('Subscription request', addr, comment) + self.__refuse(_('Subscription request'), addr, comment) else: # subscribe assert value == mm_cfg.SUBSCRIBE @@ -344,8 +344,9 @@ class ListAdmin: # add in original message, but not wrap/filled if origmsg: text = string.join([text, - '---------- Original Message ----------', + '---------- ' + _('Original Message') + ' ----------', str(origmsg)], '\n') - subject = 'Request to mailing list %s rejected' % self.real_name + subject = _('Request to mailing list %s rejected') % self.real_name msg = Message.UserNotification(recip, adminaddr, subject, text) HandlerAPI.DeliverToUser(self, msg, {'_enqueue_immediate': 1}) + diff --git a/Mailman/MailCommandHandler.py b/Mailman/MailCommandHandler.py index 88cd8db1d..0dd81b7f7 100644 --- a/Mailman/MailCommandHandler.py +++ b/Mailman/MailCommandHandler.py @@ -33,6 +33,7 @@ from Mailman import Utils from Mailman.Handlers import HandlerAPI from Mailman.Logging.Syslog import syslog from Mailman.pythonlib.StringIO import StringIO +from Mailman.i18n import _ @@ -40,26 +41,26 @@ MAXERRORS = 5 MAXCOLUMN = 70 option_descs = { - 'hide' : '''When turned on, your email address is concealed -on the Web page that lists the members of the mailing list.''', - 'nomail' : '''When turned on, delivery to your email address is disabled, -but your address is still subscribed. This is useful if you plan on -taking a short vacation.''', - 'ack' : '''When turned on, you get a separate acknowledgement email -when you post messages to the list.''', - 'notmetoo': '''When turned on, you do *not* get copies of your own -posts to the list. Otherwise, you do get copies of your own posts - (yes, this seems a little backwards). This does not affect the contents -of digests, so if you receive postings in digests, you will always get -copies of your messages in the digest.''', - 'digest' : '''When turned on, you get postings from the list bundled -into digests. Otherwise, you get each individual message immediately as -it is posted to the list.''', - 'plain' : """When turned on, you get `plain' digests, which are actually -formatted using the older RFC934 digest format. This format can be easier -to read if you have a non-MIME compliant mail reader. When this option is -turned off, you get digests in MIME format, which are much better if you -have a mail reader that supports MIME.""", + 'hide' : _('When turned on, your email address is concealed\n' + 'on the Web page that lists the members of the mailing list.'), + 'nomail' : _('When turned on, delivery to your email address is disabled,\n' + ' but your address is still subscribed. This is useful if you plan on\n' + ' taking a short vacation.'), + 'ack' : _('When turned on, you get a separate acknowledgement email\n' + 'when you post messages to the list.'), + 'notmetoo': _('When turned on, you do *not* get copies of your own\n' + 'posts to the list. Otherwise, you do get copies of your own posts\n' + ' (yes, this seems a little backwards). This does not affect the contents\n' + 'of digests, so if you receive postings in digests, you will always get\n' + 'copies of your messages in the digest.'), + 'digest' : _('When turned on, you get postings from the list bundled\n' + 'into digests. Otherwise, you get each individual message immediately as\n' + 'it is posted to the list.'), + 'plain' : _("When turned on, you get `plain' digests, which are actually\n" + "formatted using the older RFC934 digest format. This format can be easier\n" + "to read if you have a non-MIME compliant mail reader. When this option is\n" + "turned off, you get digests in MIME format, which are much better if you\n" + "have a mail reader that supports MIME."), } option_info = {'digest' : 0, @@ -165,13 +166,13 @@ class MailCommandHandler: if mo: lines = ["confirm %s" % (mo.group(1))] else: - self.AddError('Subject line ignored:\n ' + subject) + self.AddError(_('Subject line ignored:\n ') + subject) processed = {} # For avoiding redundancies. maxlines = mm_cfg.DEFAULT_MAIL_COMMANDS_MAX_LINES for linecount in range(len(lines)): if linecount > maxlines: - self.AddError("Maximum command lines (%d) encountered," - " ignoring the rest..." % maxlines) + self.AddError(_("Maximum command lines (%d) encountered," + " ignoring the rest...") % maxlines) for line in lines[linecount:]: self.AddToResponse("> " + line, trunc=0) break @@ -186,16 +187,16 @@ class MailCommandHandler: cmd = mo.group('cmd') args = args[1:] if cmd in ['end', '--']: - self.AddToResponse('\n***** End: ' + line + '\n' - 'The rest of the message is ignored:') + self.AddToResponse('\n***** ' + _('End: ') + line + '\n' + + _('The rest of the message is ignored:')) for line in lines[linecount+1:]: self.AddToResponse(line, trunc=0, prefix='> ') break if not self.__dispatch.has_key(cmd): - self.AddError(line, prefix='Command? ') + self.AddError(line, prefix=_('Command? ')) if self.__errors >= MAXERRORS: - self.AddError('\nToo many errors encountered; ' - 'the rest of the message is ignored:') + self.AddError(_('\nToo many errors encountered; ' + 'the rest of the message is ignored:')) for line in lines[linecount+1:]: self.AddToResponse(line, trunc=0, prefix='> ') break @@ -226,25 +227,25 @@ class MailCommandHandler: sfp = StringIO() traceback.print_exc(file=sfp) tbmsg = sfp.getvalue() - errmsg = Utils.wrap('''\ + errmsg = Utils.wrap(_('''\ An unexpected Mailman error has occurred. Please forward your request to the human list administrator in charge of this list at <%s>. The traceback is attached below and will be forwarded to the -list administrator automatically.''' % admin) +list administrator automatically.''') % admin) self.AddError(errmsg, trunc=0) self.AddToResponse('\n' + tbmsg, trunc=0) # log it to the error file syslog('error', - 'Unexpected Mailman error:\n%s' % tbmsg) + _('Unexpected Mailman error:\n%s') % tbmsg) # and send the traceback to the user responsemsg = Message.UserNotification( admin, admin, 'Unexpected Mailman error', - '''\ + _('''\ An unexpected Mailman error has occurred in MailCommandHandler.ParseMailCommands(). Here is the traceback: -''' + tbmsg) +''') + tbmsg) responsemsg['X-No-Archive'] = 'yes' # TBD: This should check the return value HandlerAPI.DeliverToUser(self, responsemsg) @@ -254,7 +255,7 @@ MailCommandHandler.ParseMailCommands(). Here is the traceback: adminaddr = self.GetAdminEmail() requestaddr = self.GetRequestEmail() if self.__errors > 0: - header = Utils.wrap('''This is an automated response. + header = Utils.wrap(_('''This is an automated response. There were problems with the email commands you sent to Mailman via the administrative address <%(sender)s>. @@ -268,12 +269,12 @@ send your message to <%(admin)s>. The following is a detailed description of the problems. -''' % {'sender': requestaddr, +''') % {'sender': requestaddr, 'admin' : adminaddr, }) self.__respbuf = header + self.__respbuf # send the response - subject = 'Mailman results for %s' % self.real_name + subject = _('Mailman results for %s') % self.real_name responsemsg = Message.UserNotification(msg.GetSender(), self.GetRequestEmail(), subject, @@ -286,39 +287,39 @@ The following is a detailed description of the problems. def ProcessPasswordCmd(self, args, cmd, mail): if len(args) not in [0,2]: - self.AddError("Usage: password [<oldpw> <newpw>]") + self.AddError(_("Usage: password [<oldpw> <newpw>]")) return sender = mail.GetSender() if len(args) == 0: # Mail user's password to user user = self.FindUser(sender) if user and self.passwords.has_key(user): - self.AddToResponse("You are subscribed as %s,\n" - " with password: %s" % + self.AddToResponse(_("You are subscribed as %s,\n" + " with password: %s") % (user, self.passwords[user]), trunc=0) else: - self.AddError("Found no password for %s" %sender, trunc=0) + self.AddError(_("Found no password for %s") %sender, trunc=0) return # Try to change password try: self.ConfirmUserPassword(sender, args[0]) self.ChangeUserPassword(sender, args[1], args[1]) - self.AddToResponse('Succeeded.') + self.AddToResponse(_('Succeeded.')) except Errors.MMListNotReadyError: - self.AddError("List is not functional.") + self.AddError(_("List is not functional.")) except Errors.MMNotAMemberError: - self.AddError("%s isn't subscribed to this list." % sender, + self.AddError(_("%s isn't subscribed to this list.") % sender, trunc=0) except Errors.MMBadPasswordError: - self.AddError("You gave the wrong password.") + self.AddError(_("You gave the wrong password.")) except Errors.MMBadUserError: - self.AddError("Bad user - %s." % sender, trunc=0) + self.AddError(_("Bad user - %s.") % sender, trunc=0) def ProcessOptionsCmd(self, args, cmd, mail): sender = self.FindUser(mail.GetSender()) if not sender: - self.AddError("%s is not a member of the list." % + self.AddError(_("%s is not a member of the list.") % mail.GetSender(), trunc=0) return for option in options: @@ -327,15 +328,15 @@ The following is a detailed description of the problems. else: value = 'off' self.AddToResponse('%8s: %s' % (option, value)) - self.AddToResponse("\n" + self.AddToResponse(_("\n" "To change an option, do: " "set <option> <on|off> <password>\n" "\n" "Option explanations:\n" - "--------------------") + "--------------------")) for option in options: self.AddToResponse(option + ':') - self.AddToResponse(Utils.wrap(option_descs[option]) + '\n', + self.AddToResponse(Utils.wrap(_(option_descs[option])) + '\n', trunc=0, prefix=" ") def ProcessSetCmd(self, args, cmd, mail): @@ -345,9 +346,9 @@ The following is a detailed description of the problems. desc_text = "" for option in options: desc_text = (desc_text + - "%12s: %s\n" % (option, od[option])) - s.AddError("Usage: set <option> <on|off> <password>\n" - "Valid options are:\n" + + "%12s: %s\n" % (option, _(od[option]))) + s.AddError(_("Usage: set <option> <on|off> <password>\n" + "Valid options are:\n") + desc_text) if len(args) <> 3: ShowSetUsage() @@ -363,31 +364,31 @@ The following is a detailed description of the problems. sender = self.FindUser(mail.GetSender()) self.ConfirmUserPassword(sender, args[2]) except Errors.MMNotAMemberError: - self.AddError("%s isn't subscribed to this list." + self.AddError(_("%s isn't subscribed to this list.") % mail.GetSender(), trunc=0) return except Errors.MMBadPasswordError: - self.AddError("You gave the wrong password.") + self.AddError(_("You gave the wrong password.")) return if args[0] == 'digest': try: self.SetUserDigest(mail.GetSender(), value) - self.AddToResponse("Succeeded.") + self.AddToResponse(_("Succeeded.")) except Errors.MMAlreadyDigested: - self.AddError("You are already receiving digests.") + self.AddError(_("You are already receiving digests.")) except Errors.MMAlreadyUndigested: - self.AddError("You already have digests off.") + self.AddError(_("You already have digests off.")) except Errors.MMBadEmailError: - self.AddError("Email address '%s' not accepted by Mailman." % + self.AddError(_("Email address '%s' not accepted by Mailman.") % mail.GetSender(), trunc=0) except Errors.MMMustDigestError: - self.AddError("List only accepts digest members.") + self.AddError(_("List only accepts digest members.")) except Errors.MMCantDigestError: - self.AddError("List doesn't accept digest members.") + self.AddError(_("List doesn't accept digest members.")) except Errors.MMListNotReadyError: - self.AddError("List is not functional.") + self.AddError(_("List is not functional.")) except Errors.MMNoSuchUserError: - self.AddError("%s is not subscribed to this list." + self.AddError(_("%s is not subscribed to this list.") % mail.GetSender(), trunc=0) except Errors.MMNeedApproval: self.AddApprovalMsg(cmd) @@ -398,15 +399,15 @@ The following is a detailed description of the problems. if args[0] == 'norcv': args[0] = 'notmetoo' self.SetUserOption(sender, option_info[args[0]], value) - self.AddToResponse("Succeeded.") + self.AddToResponse(_("Succeeded.")) def ProcessListsCmd(self, args, cmd, mail): if len(args) != 0: - self.AddError("Usage: lists") + self.AddError(_("Usage: lists")) return lists = Utils.list_names() lists.sort() - self.AddToResponse("\nPublic mailing lists run by mailman@%s" + self.AddToResponse(_("\nPublic mailing lists run by mailman@%s") % self.host_name, trunc=0) for listname in lists: if listname == self._internal_name: @@ -422,60 +423,60 @@ The following is a detailed description of the problems. if not listob.advertised and listob <> self: continue self.AddToResponse(listob.real_name + ':') - self.AddToResponse('\trequests to: ' + listob.GetRequestEmail(), + self.AddToResponse(_('\trequests to: ') + listob.GetRequestEmail(), trunc=0) if listob.description: - self.AddToResponse('\tdescription: ' + listob.description, + self.AddToResponse(_('\tdescription: ') + listob.description, trunc=0) def ProcessInfoCmd(self, args, cmd, mail): if len(args) != 0: - self.AddError("Usage: info\n" + self.AddError(_("Usage: info\n" "To get info for a particular list, " "send your request to\n" "the '-request' address for that list, or " "use the 'lists' command\n" - "to get info for all the lists.") + "to get info for all the lists.")) return if self.private_roster and not self.IsMember(mail.GetSender()): - self.AddError("Private list: only members may see info.") + self.AddError(_("Private list: only members may see info.")) return - msg = Utils.wrap(''' + msg = Utils.wrap(_(''' For more complete info about the %(listname)s mailing list, including background and instructions for subscribing to and using it, visit: %(url)s -''' % {'listname': self.real_name, +''') % {'listname': self.real_name, 'url' : self.GetScriptURL('listinfo', absolute=1), }) self.AddToResponse(msg, trunc=0) if not self.info: - self.AddToResponse("No other details are available.") + self.AddToResponse(_("No other details are available.")) else: self.AddToResponse(Utils.wrap(self.info), trunc=0) def ProcessWhoCmd(self, args, cmd, mail): if len(args) != 0: - self.AddError("Usage: who\n" + self.AddError(_("Usage: who\n" "To get subscribership for a particular list, " "send your request\n" - "to the '-request' address for that list.") + "to the '-request' address for that list.")) return if self.private_roster == 2: - self.AddError("Private list: No one may see subscription list.") + self.AddError(_("Private list: No one may see subscription list.")) return if self.private_roster and not self.IsMember(mail.GetSender()): - self.AddError("Private list: only members may see list " - "of subscribers.") + self.AddError(_("Private list: only members may see list " + "of subscribers.")) return digestmembers = self.GetDigestMembers() members = self.GetMembers() if not len(digestmembers) and not len(members): - self.AddToResponse("NO MEMBERS.") + self.AddToResponse(_("NO MEMBERS.")) return def AddTab(str): @@ -485,27 +486,27 @@ background and instructions for subscribing to and using it, visit: if len(digestmembers): digestmembers.sort() - self.AddToResponse("Digest Members:\n" + + self.AddToResponse(_("Digest Members:\n") + string.join(map(AddTab, filter(NotHidden, digestmembers)), "\n"), trunc=0) if len(members): members.sort() - self.AddToResponse("Non-Digest Members:\n" + + self.AddToResponse(_("Non-Digest Members:\n") + string.join(map(AddTab, filter(NotHidden, members)), "\n"), trunc=0) def ProcessUnsubscribeCmd(self, args, cmd, mail): if not len(args): - self.AddError("Usage: unsubscribe <password> [<email-address>]") + self.AddError(_("Usage: unsubscribe <password> [<email-address>]")) return if len(args) > 2: - self.AddError("Usage: unsubscribe <password> [<email-address>]\n" + self.AddError(_("Usage: unsubscribe <password> [<email-address>]\n" "To unsubscribe from a particular list, " "send your request\n" - "to the '-request' address for that list.") + "to the '-request' address for that list.")) return if len(args) == 2: addr = args[1] @@ -514,17 +515,17 @@ background and instructions for subscribing to and using it, visit: try: self.ConfirmUserPassword(addr, args[0]) self.DeleteMember(addr, "mailcmd") - self.AddToResponse("Succeeded.") + self.AddToResponse(_("Succeeded.")) except Errors.MMListNotReadyError: - self.AddError("List is not functional.") + self.AddError(_("List is not functional.")) except (Errors.MMNoSuchUserError, Errors.MMNotAMemberError): - self.AddError("%s is not subscribed to this list." % addr, + self.AddError(_("%s is not subscribed to this list.") % addr, trunc=0) except Errors.MMBadPasswordError: - self.AddError("You gave the wrong password.") + self.AddError(_("You gave the wrong password.")) except Errors.MMBadUserError: - self.AddError('Your stored password is bogus.') - syslog('subscribe', 'User %s on list %s has no password' % + self.AddError(_('Your stored password is bogus.')) + syslog('subscribe', _('User %s on list %s has no password') % (addr, self.internal_name())) def ProcessSubscribeCmd(self, args, cmd, mail): @@ -536,8 +537,8 @@ background and instructions for subscribing to and using it, visit: if not len(args): password = Utils.MakeRandomPassword() elif len(args) > 3: - self.AddError("Usage: subscribe [password] " - "[digest|nodigest] [address=<email-address>]", + self.AddError(_("Usage: subscribe [password] " + "[digest|nodigest] [address=<email-address>]"), trunc=0) return else: @@ -553,9 +554,9 @@ background and instructions for subscribing to and using it, visit: elif not password: password = arg else: - self.AddError("Usage: subscribe [password] " + self.AddError(_("Usage: subscribe [password] " "[digest|nodigest] " - "[address=<email-address>]") + "[address=<email-address>]")) return if not password: password = Utils.MakeRandomPassword() @@ -574,27 +575,27 @@ background and instructions for subscribing to and using it, visit: # self.__NoMailCmdResponse = 1 except Errors.MMNeedApproval: - self.AddToResponse( + self.AddToResponse(_( "Your subscription request has been forwarded to the" " list administrator\n" - "at %s for review." % self.GetAdminEmail(), trunc=0) + "at %s for review.") % self.GetAdminEmail(), trunc=0) except Errors.MMBadEmailError: - self.AddError("Mailman won't accept the given email " + self.AddError(_("Mailman won't accept the given email " "address as a valid address.\n" - "(Does it have an @ in it???)") + "(Does it have an @ in it???)")) except Errors.MMListNotReadyError: - self.AddError("The list is not fully functional, and " + self.AddError(_("The list is not fully functional, and " "can not accept subscription\n" - "requests.") + "requests.")) except Errors.MMHostileAddress: - self.AddError("Your subscription is not allowed because\n" - "the email address you gave is insecure.") + self.AddError(_("Your subscription is not allowed because\n" + "the email address you gave is insecure.")) except Errors.MMAlreadyAMember: - self.AddError("You are already subscribed!") + self.AddError(_("You are already subscribed!")) except Errors.MMCantDigestError: - self.AddError("No one can subscribe to the digest of this list!") + self.AddError(_("No one can subscribe to the digest of this list!")) except Errors.MMMustDigestError: - self.AddError("This list only supports digest subscriptions!") + self.AddError(_("This list only supports digest subscriptions!")) else: # # if the list sends a welcome message, we don't need a response @@ -603,19 +604,19 @@ background and instructions for subscribing to and using it, visit: if self.send_welcome_msg: self.__NoMailCmdResponse = 1 else: - self.AddToResponse("Succeeded") + self.AddToResponse(_("Succeeded")) def ProcessConfirmCmd(self, args, cmd, mail): """Validate confirmation and carry out the subscription.""" if len(args) != 1: - self.AddError("Usage: confirm <confirmation number>\n") + self.AddError(_("Usage: confirm <confirmation number>\n")) return try: cookie = string.atoi(args[0]) except: - self.AddError("Usage: confirm <confirmation number>\n") + self.AddError(_("Usage: confirm <confirmation number>\n")) return try: self.ProcessConfirmation(cookie) @@ -626,19 +627,19 @@ background and instructions for subscribing to and using it, visit: * 1000) / 1000 if floor(expiredays) == expiredays: expiredays = int(expiredays) - self.AddError("Invalid confirmation number!\n" + self.AddError(_("Invalid confirmation number!\n" "Note that confirmation numbers expire %s days" " after initial request.\n" "Please check date and number and try again," - " from the start if necessary." + " from the start if necessary.") % expiredays, trunc=0) except Errors.MMNeedApproval, admin_addr: - self.AddToResponse("Your request has been forwarded to the list " - "administrator for approval") + self.AddToResponse(_("Your request has been forwarded to the list " + "administrator for approval")) except Errors.MMAlreadyAMember: # Some other subscription request for this address has # already succeeded. - self.AddError("You are already subscribed!") + self.AddError(_("You are already subscribed!")) else: # # if the list sends a welcome message, we don't need a response @@ -647,7 +648,7 @@ background and instructions for subscribing to and using it, visit: if self.send_welcome_msg: self.__NoMailCmdResponse = 1 else: - self.AddToResponse("Succeeded") + self.AddToResponse(_("Succeeded")) def AddApprovalMsg(self, cmd): @@ -669,3 +670,4 @@ background and instructions for subscribing to and using it, visit: 'adminaddr' : self.GetAdminEmail(), }) self.AddToResponse(text, trunc=0) + diff --git a/Mailman/MailList.py b/Mailman/MailList.py index 094d32613..79c7e16d2 100644 --- a/Mailman/MailList.py +++ b/Mailman/MailList.py @@ -355,76 +355,75 @@ class MailList(MailCommandHandler, HTMLFormatter, Deliverer, ListAdmin, WIDTH = mm_cfg.TEXTFIELDWIDTH # XXX: Should this text be migrated into the templates dir? - config_info['general'] = [ + config_info['general'] = [_( "Fundamental list characteristics, including descriptive" - " info and basic behaviors.", + " info and basic behaviors."), ('real_name', mm_cfg.String, WIDTH, 0, - 'The public name of this list (make case-changes only).', + _('The public name of this list (make case-changes only).'), - "The capitalization of this name can be changed to make it" + _("The capitalization of this name can be changed to make it" " presentable in polite company as a proper noun, or to make an" " acronym part all upper case, etc. However, the name" " will be advertised as the email address (e.g., in subscribe" " confirmation notices), so it should <em>not</em> be otherwise" " altered. (Email addresses are not case sensitive, but" - " they are sensitive to almost everything else:-)"), + " they are sensitive to almost everything else:-)")), ('owner', mm_cfg.EmailList, (3, WIDTH), 0, - "The list admin's email address - having multiple" - " admins/addresses (on separate lines) is ok."), + _("The list admin's email address - having multiple" + " admins/addresses (on separate lines) is ok.")), ('description', mm_cfg.String, WIDTH, 0, - 'A terse phrase identifying this list.', + _('A terse phrase identifying this list.'), - "This description is used when the mailing list is listed with" + _("This description is used when the mailing list is listed with" " other mailing lists, or in headers, and so forth. It should" " be as succinct as you can get it, while still identifying" - " what the list is."), + " what the list is.")), - ('info', mm_cfg.Text, (7, WIDTH), 0, + ('info', mm_cfg.Text, (7, WIDTH), 0, _( ' An introductory description - a few paragraphs - about the' ' list. It will be included, as html, at the top of the' ' listinfo page. Carriage returns will end a paragraph - see' - ' the details for more info.', + ' the details for more info.'), - "The text will be treated as html <em>except</em> that newlines" + _("The text will be treated as html <em>except</em> that newlines" " newlines will be translated to <br> - so you can use" " links, preformatted text, etc, but don't put in carriage" " returns except where you mean to separate paragraphs. And" " review your changes - bad html (like some unterminated HTML" - " constructs) can prevent display of the entire listinfo page."), + " constructs) can prevent display of the entire listinfo page.")), ('subject_prefix', mm_cfg.String, WIDTH, 0, - 'Prefix for subject line of list postings.', + _('Prefix for subject line of list postings.'), - "This text will be prepended to subject lines of messages" + _("This text will be prepended to subject lines of messages" " posted to the list, to distinguish mailing list messages in" " in mailbox summaries. Brevity is premium here, it's ok" " to shorten long mailing list names to something more concise," - " as long as it still identifies the mailing list."), + " as long as it still identifies the mailing list.")), ('welcome_msg', mm_cfg.Text, (4, WIDTH), 0, - 'List-specific text prepended to new-subscriber welcome message', + _('List-specific text prepended to new-subscriber welcome message'), - "This value, if any, will be added to the front of the" + _("This value, if any, will be added to the front of the" " new-subscriber welcome message. The rest of the" " welcome message already describes the important addresses" " and URLs for the mailing list, so you don't need to include" " any of that kind of stuff here. This should just contain" " mission-specific kinds of things, like etiquette policies" - " or team orientation, or that kind of thing."), + " or team orientation, or that kind of thing.")), ('goodbye_msg', mm_cfg.Text, (4, WIDTH), 0, - 'Text sent to people leaving the list. If empty, no special' - ' text will be added to the unsubscribe message.'), + _('Text sent to people leaving the list. If empty, no special' + ' text will be added to the unsubscribe message.')), ('reply_goes_to_list', mm_cfg.Radio, - ('Poster', 'This list', 'Explicit address'), 0, - '''Where are replies to list messages directed? <tt>Poster</tt> -is <em>strongly</em> recommended for most mailing lists.''', + (_('Poster'), _('This list'), _('Explicit address')), 0, + _('Where are replies to list messages directed? <tt>Poster</tt> is <em>strongly</em> recommended for most mailing lists.'), # Details for reply_goes_to_list - """This option controls what Mailman does to the + _("""This option controls what Mailman does to the <tt>Reply-To:</tt> header in messages flowing through this mailing list. When set to <em>Poster</em>, no <tt>Reply-To:</tt> header is added by Mailman, although if one is present in the original message, it is not stripped. @@ -433,7 +432,7 @@ causes Mailman to insert a specific <tt>Reply-To:</tt> header in all messages, overriding the header in the original message if necessary (<em>Explicit address</em> inserts the value of <a href="?VARHELP=general/reply_to_address">reply_to_address</a>). - + <p>There are many reasons not to introduce or override the <tt>Reply-To:</tt> header. One is that some posters depend on their own <tt>Reply-To:</tt> settings to convey their valid return address. Another is that modifying @@ -448,13 +447,13 @@ devoted to discussions. Examples are `patches' or `checkin' lists, where software changes are posted by a revision control system, but discussion about the changes occurs on a developers mailing list. To support these types of mailing lists, select <tt>Explicit address</tt> and set the <tt>Reply-To:</tt> -address below to point to the parallel list."""), +address below to point to the parallel list.""")), - ('reply_to_address', mm_cfg.Email, WIDTH, 0, - '''Explicit <tt>Reply-To:</tt> header.''', + ('reply_to_address', mm_cfg.Email, WIDTH, 0,_( + 'Explicit <tt>Reply-To:</tt> header.'), # Details for reply_to_address - """This is the address set in the <tt>Reply-To:</tt> header + _("""This is the address set in the <tt>Reply-To:</tt> header when the <a href="?VARHELP=general/reply_goes_to_list">reply_goes_to_list</a> option is set to <em>Explicit address</em>. @@ -471,95 +470,99 @@ Munging Considered Useful</a> for a dissenting opinion. devoted to discussions. Examples are `patches' or `checkin' lists, where software changes are posted by a revision control system, but discussion about the changes occurs on a developers mailing list. To support these types of -mailing lists, select <tt>Explicit address</tt> and set the <tt>Reply-To:</tt> -address below to point to the parallel list."""), +mailing lists, specify the explicit <tt>Reply-To:</tt> address here. You must +also specify <tt>Explicit address</tt> in the <tt>reply_goes_to_list</tt> +variable. + +<p>Note that if the original message contains a <tt>Reply-To:</tt> header, +it will not be changed.""")), ('administrivia', mm_cfg.Radio, ('No', 'Yes'), 0, - "(Administrivia filter) Check postings and intercept ones" - " that seem to be administrative requests?", + _("(Administrivia filter) Check postings and intercept ones" + " that seem to be administrative requests?"), - "Administrivia tests will check postings to see whether" + _("Administrivia tests will check postings to see whether" " it's really meant as an administrative request (like" " subscribe, unsubscribe, etc), and will add it to the" " the administrative requests queue, notifying the " - " administrator of the new request, in the process. "), + " administrator of the new request, in the process. ")), - ('umbrella_list', mm_cfg.Radio, ('No', 'Yes'), 0, + ('umbrella_list', mm_cfg.Radio, ('No', 'Yes'), 0,_( 'Send password reminders to, eg, "-owner" address instead of' - ' directly to user.', + ' directly to user.'), - "Set this to yes when this list is intended to cascade only to" + _("Set this to yes when this list is intended to cascade only to" " other mailing lists. When set, meta notices like confirmations" " and password reminders will be directed to an address derived" " from the member\'s address - it will have the value of" ' \"umbrella_member_suffix\" appended to the' - " member\'s account name."), + " member\'s account name.")), - ('umbrella_member_suffix', mm_cfg.String, WIDTH, 0, + ('umbrella_member_suffix', mm_cfg.String, WIDTH, 0,_( 'Suffix for use when this list is an umbrella for other lists,' - ' according to setting of previous "umbrella_list" setting.', + ' according to setting of previous "umbrella_list" setting.'), - 'When \"umbrella_list\" is set to indicate that this list has' + _('When \"umbrella_list\" is set to indicate that this list has' " other mailing lists as members, then administrative notices" " like confirmations and password reminders need to not be sent" " to the member list addresses, but rather to the owner of those" " member lists. In that case, the value of this setting is" " appended to the member\'s account name for such notices." " \'-owner\' is the typical choice. This setting has no" - ' effect when \"umbrella_list\" is \"No\".'), + ' effect when \"umbrella_list\" is \"No\".')), - ('send_reminders', mm_cfg.Radio, ('No', 'Yes'), 0, - 'Send monthly password reminders or no? Overrides the previous ' - 'option.'), + ('send_reminders', mm_cfg.Radio, (_('No'), _('Yes')), 0, + _('Send monthly password reminders or no? Overrides the previous ' + 'option.')), - ('send_welcome_msg', mm_cfg.Radio, ('No', 'Yes'), 0, - 'Send welcome message when people subscribe?', - "Turn this on only if you plan on subscribing people manually " - "and don't want them to know that you did so. This option " - "is most useful for transparently migrating lists from " - "some other mailing list manager to Mailman."), + ('send_welcome_msg', mm_cfg.Radio, (_('No'), _('Yes')), 0, + _('Send welcome message when people subscribe?'), + _("Turn this on only if you plan on subscribing people manually " + "and don't want them to know that you did so. This option " + "is most useful for transparently migrating lists from " + "some other mailing list manager to Mailman.")), - ('admin_immed_notify', mm_cfg.Radio, ('No', 'Yes'), 0, - 'Should administrator get immediate notice of new requests, ' - 'as well as daily notices about collected ones?', + ('admin_immed_notify', mm_cfg.Radio, (_('No'), _('Yes')), 0, + _('Should administrator get immediate notice of new requests, ' + 'as well as daily notices about collected ones?'), - "List admins are sent daily reminders of pending admin approval" + _("List admins are sent daily reminders of pending admin approval" " requests, like subscriptions to a moderated list or postings" " that are being held for one reason or another. Setting this" " option causes notices to be sent immediately on the arrival" - " of new requests, as well."), + " of new requests, as well.")), - ('admin_notify_mchanges', mm_cfg.Radio, ('No', 'Yes'), 0, - 'Should administrator get notices of subscribes/unsubscribes?'), + ('admin_notify_mchanges', mm_cfg.Radio, (_('No'), _('Yes')), 0, + _('Should administrator get notices of subscribes/unsubscribes?')), - ('dont_respond_to_post_requests', mm_cfg.Radio, ('Yes', 'No'), 0, - 'Send mail to poster when their posting is held for approval?', + ('dont_respond_to_post_requests', mm_cfg.Radio, (_('Yes'), _('No')), 0, + _('Send mail to poster when their posting is held for approval?'), - "Approval notices are sent when mail triggers certain of the" + _("Approval notices are sent when mail triggers certain of the" " limits <em>except</em> routine list moderation and spam" " filters, for which notices are <em>not</em> sent. This" - " option overrides ever sending the notice."), + " option overrides ever sending the notice.")), ('max_message_size', mm_cfg.Number, 7, 0, - 'Maximum length in Kb of a message body. Use 0 for no limit.'), + _('Maximum length in Kb of a message body. Use 0 for no limit.')), ('host_name', mm_cfg.Host, WIDTH, 0, - 'Host name this list prefers.', + _('Host name this list prefers.'), - "The host_name is the preferred name for email to mailman-related" + _("The host_name is the preferred name for email to mailman-related" " addresses on this host, and generally should be the mail" " host's exchanger address, if any. This setting can be useful" " for selecting among alternative names of a host that has" - " multiple addresses."), + " multiple addresses.")), ('web_page_url', mm_cfg.String, WIDTH, 0, - '''Base URL for Mailman web interface. The URL must end in a + _('''Base URL for Mailman web interface. The URL must end in a single "/". See also the details for an important warning when - changing this value.''', + changing this value.'''), - """This is the common root for all Mailman URLs referencing this + _("""This is the common root for all Mailman URLs referencing this mailing list. It is also used in the listinfo overview of mailing lists to identify whether or not this list resides on the virtual host identified by the overview URL; i.e. if this value @@ -570,14 +573,14 @@ address below to point to the parallel list."""), an invalid base URL will render the mailing list unusable. You will also not be able to fix this from the web interface! In that case, the site administrator will have to fix the mailing - list from the command line."""), + list from the command line.""")), ] if mm_cfg.ALLOW_OPEN_SUBSCRIBE: sub_cfentry = ('subscribe_policy', mm_cfg.Radio, - ('none', 'confirm', 'require approval', - 'confirm+approval'), 0, - "What steps are required for subscription?<br>", - "None - no verification steps (<em>Not" + (_('none'), _('confirm'), _('require approval'), + _('confirm+approval')), 0, + _("What steps are required for subscription?<br>"), + _("None - no verification steps (<em>Not" " Recommended </em>)<br>" "confirm (*) - email confirmation step" " required <br>" @@ -591,14 +594,14 @@ address below to point to the parallel list."""), " reply to in order to subscribe.<br> This" " prevents mischievous (or malicious) people" " from creating subscriptions for others" - " without their consent." + " without their consent.") ) else: sub_cfentry = ('subscribe_policy', mm_cfg.Radio, - ('confirm', 'require approval', - 'confirm+approval'), 1, - "What steps are required for subscription?<br>", - "confirm (*) - email confirmation required <br>" + (_('confirm'), _('require approval'), + _('confirm+approval')), 1, + _("What steps are required for subscription?<br>"), + _("confirm (*) - email confirmation required <br>" "require approval - require list administrator" " approval for subscriptions <br>" "confirm+approval - both confirm and approve" @@ -608,168 +611,183 @@ address below to point to the parallel list."""), " reply to in order to subscribe.<br> This" " prevents mischievous (or malicious) people" " from creating subscriptions for others" - " without their consent." + " without their consent.") ) - + # some helpful values + adminurl = self.GetScriptURL('admin') + config_info['privacy'] = [ - "List access policies, including anti-spam measures," - " covering members and outsiders." - ' (See also the <a href="%s/archive">Archival Options' - ' section</a> for separate archive-privacy settings.)' - % (self.GetScriptURL('admin')), + _("""List access policies, including anti-spam measures, covering + members and outsiders. See also the + <a href="%(admin)s/archive">Archival Options section</a> for + separate archive-privacy settings."""), - "Subscribing", + _("Subscribing"), ('advertised', mm_cfg.Radio, ('No', 'Yes'), 0, - 'Advertise this list when people ask what lists are on ' - 'this machine?'), + _("""Advertise this list when people ask what lists are on this + machine?""")), sub_cfentry, - "Membership exposure", + _("Membership exposure"), ('private_roster', mm_cfg.Radio, - ('Anyone', 'List members', 'List admin only'), 0, - 'Who can view subscription list?', + (_('Anyone'), _('List members'), _('List admin only')), 0, + _('Who can view subscription list?'), - "When set, the list of subscribers is protected by" - " member or admin password authentication."), + _('''When set, the list of subscribers is protected by + member or admin password authentication.''')), - ('obscure_addresses', mm_cfg.Radio, ('No', 'Yes'), 0, - "Show member addrs so they're not directly recognizable" - ' as email addrs?', + ('obscure_addresses', mm_cfg.Radio, (_('No'), _('Yes')), 0, + _("""Show member addrs so they're not directly recognizable + as email addrs?"""), - "Setting this option causes member email addresses to be" - " transformed when they are presented on list web pages (both" - " in text and as links), so they're not trivially" - " recognizable as email addresses. The intention is to" - " to prevent the addresses from being snarfed up by" - " automated web scanners for use by spammers."), + _("""Setting this option causes member email addresses to be + transformed when they are presented on list web pages (both in + text and as links), so they're not trivially recognizable as + email addresses. The intention is to to prevent the addresses + from being snarfed up by automated web scanners for use by + spammers.""")), - "General posting filters", + _("General posting filters"), - ('moderated', mm_cfg.Radio, ('No', 'Yes'), 0, - 'Must posts be approved by an administrator?'), + ('moderated', mm_cfg.Radio, (_('No'), _('Yes')), 0, + _('Must posts be approved by an administrator?')), - ('member_posting_only', mm_cfg.Radio, ('No', 'Yes'), 0, - 'Restrict posting privilege to list members?' - ' (<i>member_posting_only</i>)', + ('member_posting_only', mm_cfg.Radio, (_('No'), _('Yes')), 0, + _("""Restrict posting privilege to list members? + (<i>member_posting_only</i>)"""), - "Use this option if you want to restrict posting to list members." - " If you want list members to be able to" - " post, plus a handful of other posters, see the <i> posters </i>" - " setting below"), + _("""Use this option if you want to restrict posting to list + members. If you want list members to be able to post, plus a + handful of other posters, see the <i> posters </i> setting + below""")), ('posters', mm_cfg.EmailList, (5, WIDTH), 1, - 'Addresses of members accepted for posting to this' - ' list without implicit approval requirement. (See' - ' "Restrict ... to list members"' - ' for whether or not this is in addition to allowing posting' - ' by list members', + _("""Addresses of members accepted for posting to this list + without implicit approval requirement. (See "Restrict ... to list + members" for whether or not this is in addition to allowing + posting by list members"""), + + _("""Adding entries here will have one of two effects, + according to whether another option restricts posting to + members. + + <ul> + <li>If <i>member_posting_only</i> is 'yes', then entries + added here will have posting privilege in addition to list + members. + + <li>If <i>member_posting_only</i> is 'no', then + <em>only</em> the posters listed here will be able to post + without admin approval. + + </ul>""")), - "Adding entries here will have one of two effects," - " according to whether another option restricts posting to" - " members. <ul>" - " <li> If <i>member_posting_only</i> is 'yes', then entries" - " added here will have posting privilege in addition to" - " list members." - " <li> If <i>member_posting_only</i> is 'no', then <em>only</em>" - " the posters listed here will be able to post without admin" - " approval. </ul>"), + _("Spam-specific posting filters"), - "Spam-specific posting filters", + ('require_explicit_destination', mm_cfg.Radio, + (_('No'), _('Yes')), 0, + _("""Must posts have list named in destination (to, cc) field + (or be among the acceptable alias names, specified below)?"""), - ('require_explicit_destination', mm_cfg.Radio, ('No', 'Yes'), 0, - 'Must posts have list named in destination (to, cc) field' - ' (or be among the acceptable alias names, specified below)?', + _("""Many (in fact, most) spams do not explicitly name their + myriad destinations in the explicit destination addresses - in + fact often the To: field has a totally bogus address for + obfuscation. The constraint applies only to the stuff in the + address before the '@' sign, but still catches all such spams. - "Many (in fact, most) spams do not explicitly name their myriad" - " destinations in the explicit destination addresses - in fact," - " often the to field has a totally bogus address for" - " obfuscation. The constraint applies only to the stuff in" - " the address before the '@' sign, but still catches all such" - " spams." - "<p>The cost is that the list will not accept unhindered any" - " postings relayed from other addresses, unless <ol>" - " <li>The relaying address has the same name, or" - " <li>The relaying address name is included on the options that" - " specifies acceptable aliases for the list. </ol>"), + <p>The cost is that the list will not accept unhindered any + postings relayed from other addresses, unless + + <ol> + <li>The relaying address has the same name, or + + <li>The relaying address name is included on the options that + specifies acceptable aliases for the list. + + </ol>""")), ('acceptable_aliases', mm_cfg.Text, (4, WIDTH), 0, - 'Alias names (regexps) which qualify as explicit to or cc' - ' destination names for this list.', + _("""Alias names (regexps) which qualify as explicit to or cc + destination names for this list."""), - "Alternate addresses that are acceptable when" - " `require_explicit_destination' is enabled. This option" - " takes a list of regular expressions, one per line, which is" - " matched against every recipient address in the message. The" - " matching is performed with Python's re.match() function," - " meaning they are anchored to the start of the string." - " <p>For backwards compatibility with Mailman 1.1, if the regexp" - " does not contain an `@', then the pattern is matched against" - " just the local part of the recipient address. If that match" - " fails, or if the pattern does contain an `@', then the pattern" - " is matched against the entire recipient address. " - " <p>Matching against the local part is deprecated; in a future" - " release, the patterm will always be matched against the " - " entire recipient address."), + _("""Alternate addresses that are acceptable when + `require_explicit_destination' is enabled. This option takes a + list of regular expressions, one per line, which is matched + against every recipient address in the message. The matching is + performed with Python's re.match() function, meaning they are + anchored to the start of the string. + + <p>For backwards compatibility with Mailman 1.1, if the regexp + does not contain an `@', then the pattern is matched against just + the local part of the recipient address. If that match fails, or + if the pattern does contain an `@', then the pattern is matched + against the entire recipient address. + + <p>Matching against the local part is deprecated; in a future + release, the pattern will always be matched against the entire + recipient address.""")), ('max_num_recipients', mm_cfg.Number, 5, 0, - 'Ceiling on acceptable number of recipients for a posting.', + _('Ceiling on acceptable number of recipients for a posting.'), - "If a posting has this number, or more, of recipients, it is" - " held for admin approval. Use 0 for no ceiling."), + _("""If a posting has this number, or more, of recipients, it is + held for admin approval. Use 0 for no ceiling.""")), ('forbidden_posters', mm_cfg.EmailList, (5, WIDTH), 1, - 'Addresses whose postings are always held for approval.', + _('Addresses whose postings are always held for approval.'), - "Email addresses whose posts should always be held for" - " approval, no matter what other options you have set." - " See also the subsequent option which applies to arbitrary" - " content of arbitrary headers."), + _("""Email addresses whose posts should always be held for + approval, no matter what other options you have set. See also + the subsequent option which applies to arbitrary content of + arbitrary headers.""")), ('bounce_matching_headers', mm_cfg.Text, (6, WIDTH), 0, - 'Hold posts with header value matching a specified regexp.', + _('Hold posts with header value matching a specified regexp.'), + + _("""Use this option to prohibit posts according to specific + header values. The target value is a regular-expression for + matching against the specified header. The match is done + disregarding letter case. Lines beginning with '#' are ignored + as comments. - "Use this option to prohibit posts according to specific header" - " values. The target value is a regular-expression for" - " matching against the specified header. The match is done" - " disregarding letter case. Lines beginning with '#' are" - " ignored as comments." - "<p>For example:<pre>to: .*@public.com </pre> says" - " to hold all postings with a <em>to</em> mail header" - " containing '@public.com' anywhere among the addresses." - "<p>Note that leading whitespace is trimmed from the" - " regexp. This can be circumvented in a number of ways, eg" - " by escaping or bracketing it." - "<p> See also the <em>forbidden_posters</em> option for" - " a related mechanism."), + <p>For example:<pre>to: .*@public.com </pre> says to hold all + postings with a <em>To:</em> mail header containing '@public.com' + anywhere among the addresses. - ('anonymous_list', mm_cfg.Radio, ('No', 'Yes'), 0, - 'Hide the sender of a message, replacing it with the list ' - 'address (Removes From, Sender and Reply-To fields)'), - - ] + <p>Note that leading whitespace is trimmed from the regexp. This + can be circumvented in a number of ways, e.g. by escaping or + bracketing it. + + <p> See also the <em>forbidden_posters</em> option for a related + mechanism.""")), + + ('anonymous_list', mm_cfg.Radio, (_('No'), _('Yes')), 0, + _("""Hide the sender of a message, replacing it with the list + address (Removes From, Sender and Reply-To fields)""")), + ] config_info['nondigest'] = [ - "Policies concerning immediately delivered list traffic.", + _("Policies concerning immediately delivered list traffic."), - ('nondigestable', mm_cfg.Toggle, ('No', 'Yes'), 1, - 'Can subscribers choose to receive mail immediately,' - ' rather than in batched digests?'), + ('nondigestable', mm_cfg.Toggle, (_('No'), _('Yes')), 1, + _("""Can subscribers choose to receive mail immediately, + rather than in batched digests?""")), ('msg_header', mm_cfg.Text, (4, WIDTH), 0, - 'Header added to mail sent to regular list members', + _('Header added to mail sent to regular list members'), + + _("""Text prepended to the top of every immediately-delivery + message. """) + Utils.maketext('headfoot.html', raw=1)), - "Text prepended to the top of every immediately-delivery" - " message. " + Utils.maketext('headfoot.html', raw=1)), - ('msg_footer', mm_cfg.Text, (4, WIDTH), 0, - 'Footer added to mail sent to regular list members', + _('Footer added to mail sent to regular list members'), - "Text appended to the bottom of every immediately-delivery" - " message. " + Utils.maketext('headfoot.html', raw=1)), + _("""Text appended to the bottom of every immediately-delivery + message. """) + Utils.maketext('headfoot.html', raw=1)), ] config_info['bounce'] = Bouncer.GetConfigInfo(self) @@ -925,10 +943,9 @@ address below to point to the parallel list."""), else: self.InitVars() # Init any new variables, self.Load(check_version = 0) # then reload the file - if self.Locked(): - from versions import Update - Update(self, stored_state) - self.data_version = mm_cfg.DATA_FILE_VERSION + from versions import Update + Update(self, stored_state) + self.data_version = mm_cfg.DATA_FILE_VERSION if self.Locked(): self.Save() @@ -982,7 +999,7 @@ address below to point to the parallel list."""), cookie = Pending().new(name, password, digest) if remote is not None: by = " " + remote - remote = " from %s" % remote + remote = _(" from %s") % remote else: by = "" remote = "" @@ -999,7 +1016,7 @@ address below to point to the parallel list."""), }) msg = Message.UserNotification( recipient, self.GetRequestEmail(), - '%s -- confirmation of subscription -- request %d' % + _('%s -- confirmation of subscription -- request %d') % (self.real_name, cookie), text) msg['Reply-To'] = self.GetRequestEmail() @@ -1015,7 +1032,7 @@ address below to point to the parallel list."""), # requests database. self.HoldSubscription(name, password, digest) raise Errors.MMNeedApproval, \ - 'subscriptions to %s require administrator approval' % \ + _('subscriptions to %s require administrator approval') % \ self.real_name def ProcessConfirmation(self, cookie): @@ -1029,7 +1046,7 @@ address below to point to the parallel list."""), if self.subscribe_policy == 3: # confirm + approve self.HoldSubscription(email_addr, password, digest) raise Errors.MMNeedApproval, \ - 'subscriptions to %s require administrator approval' % \ + _('subscriptions to %s require administrator approval') % \ self.real_name self.ApprovedAddMember(email_addr, password, digest) finally: @@ -1136,7 +1153,7 @@ address below to point to the parallel list."""), digest) if admin_notif: adminaddr = self.GetAdminEmail() - subject = ('%s subscription notification' % + subject = (_('%s subscription notification') % self.real_name) text = Utils.maketext( "adminsubscribeack.txt", @@ -1187,7 +1204,7 @@ address below to point to the parallel list."""), else: admin_notif = 0 if admin_notif: - subject = '%s unsubscribe notification' % self.real_name + subject = _('%s unsubscribe notification') % self.real_name text = Utils.maketext( 'adminunsubscribeack.txt', {'member' : name, @@ -1229,8 +1246,7 @@ address below to point to the parallel list."""), localpart = string.split(addr, '@')[0] if (# TBD: backwards compatibility: deprecated localpart == self.internal_name() or - # Exact match against the complete list address. TBD: - # this test should be case-insensitive. + # exact match against the complete list address addr == listfullname): return 1 recips.append((addr, localpart)) diff --git a/Mailman/htmlformat.py b/Mailman/htmlformat.py index 987df1a7a..e345c43ec 100644 --- a/Mailman/htmlformat.py +++ b/Mailman/htmlformat.py @@ -539,8 +539,8 @@ def MailmanLogo(): else: # use only textual links mmlink = Link(MAILMAN_URL, - 'Delivered by Mailman<br>version %s' % mm_cfg.VERSION) - pylink = Link(PYTHON_URL, 'Python Powered') - gnulink = Link(GNU_URL, "Gnu's Not Unix") + _('Delivered by Mailman<br>version %s') % mm_cfg.VERSION) + pylink = Link(PYTHON_URL, _('Python Powered')) + gnulink = Link(GNU_URL, _("Gnu's Not Unix")) t.AddRow([mmlink, pylink, gnulink]) return t |
