diff options
Diffstat (limited to 'Mailman/Cgi/admin.py')
| -rw-r--r-- | Mailman/Cgi/admin.py | 216 |
1 files changed, 114 insertions, 102 deletions
diff --git a/Mailman/Cgi/admin.py b/Mailman/Cgi/admin.py index fd856bc61..63b6e3e90 100644 --- a/Mailman/Cgi/admin.py +++ b/Mailman/Cgi/admin.py @@ -64,7 +64,7 @@ def main(): try: mlist = MailList.MailList(listname) except Errors.MMListError, e: - FormatAdminOverview('No such list <em>%s</em>' % listname) + FormatAdminOverview(_('No such list <em>%s</em>') % listname) syslog('error', 'Someone tried to access the admin interface for a ' 'non-existent list: %s' % listname) return @@ -90,6 +90,15 @@ def main(): Auth.loginpage(mlist, 'admin', frontpage=1) return + CATEGORIES = [('general', _("General Options")), + ('members', _("Membership Management")), + ('privacy', _("Privacy Options")), + ('nondigest', _("Regular-member (non-digest) Options")), + ('digest', _("Digest-member Options")), + ('bounce', _("Bounce Options")), + ('archive', _("Archival Options")), + ('gateway', _("Mail-News and News-Mail gateways"))] + if category not in map(lambda x: x[0], CATEGORIES): category = 'general' @@ -118,19 +127,19 @@ def main(): # Sanity checks if not mlist.digestable and not mlist.nondigestable: - AddErrorMessage(doc, '''You have turned off delivery of + AddErrorMessage(doc, _('''You have turned off delivery of both digest and non-digest messages. This is an incompatible state of affairs. You must turn on either digest delivery or non-digest delivery or your mailing list will basically be - unusable.''') + unusable.''')) if not mlist.digestable and len(mlist.GetDigestMembers()): - AddErrorMessage(doc, '''You have digest members, + AddErrorMessage(doc, _('''You have digest members, but digests are turned off. Those people will not receive - mail.''') + mail.''')) if not mlist.nondigestable and len(mlist.GetMembers()): - AddErrorMessage(doc, '''You have regular list members + AddErrorMessage(doc, _('''You have regular list members but non-digestified mail is turned off. They will receive mail - until you fix this problem.''') + until you fix this problem.''')) FormatConfiguration(doc, mlist, category, category_suffix, cgidata) print doc.Format(bgcolor="#ffffff") @@ -144,7 +153,7 @@ def main(): def FormatAdminOverview(error=None): "Present a general welcome and itemize the (public) lists." doc = Document() - legend = "%s mailing lists - Admin Links" % mm_cfg.DEFAULT_HOST_NAME + legend = _("%s mailing lists - Admin Links") % mm_cfg.DEFAULT_HOST_NAME doc.SetTitle(legend) table = Table(border=0, width="100%") @@ -163,39 +172,39 @@ def FormatAdminOverview(error=None): if error: greeting = FontAttr(error, color="ff5060", size="+1") else: - greeting = "Welcome!" + greeting = _("Welcome!") if not advertised: welcome_items = (greeting, - "<p>" - " There currently are no publicly-advertised ", + _("<p>" + " There currently are no publicly-advertised "), Link(mm_cfg.MAILMAN_URL, "mailman"), - " mailing lists on %s." % mm_cfg.DEFAULT_HOST_NAME, + _(" mailing lists on %s.") % mm_cfg.DEFAULT_HOST_NAME, ) else: welcome_items = ( greeting, - "<p>" - " Below is the collection of publicly-advertised ", + _("<p>" + " Below is the collection of publicly-advertised "), Link(mm_cfg.MAILMAN_URL, "mailman"), - " mailing lists on %s." % mm_cfg.DEFAULT_HOST_NAME, - (' Click on a list name to visit the configuration pages' - ' for that list.' + _(" mailing lists on %s.") % mm_cfg.DEFAULT_HOST_NAME, + (_(' Click on a list name to visit the configuration pages' + ' for that list.') ) ) welcome_items = (welcome_items + - (" To visit the administrators configuration page for" - " an unadvertised list, open a URL similar to this" + (_(" To visit the administrators configuration page for" + " an unadvertised list, open a URL similar to this") + - (" one, but with a '/' and the %slist name appended.<p>" - % ((error and "right ") or "")) + (_(" one, but with a '/' and the %slist name appended.<p>") + % ((error and _("right ")) or "")) + - " General list information can be found at ", + _(" General list information can be found at "), Link(Utils.ScriptURL('listinfo'), - 'the mailing list overview page'), - "." - "<p>(Send questions and comments to ", + _('the mailing list overview page')), + "." + + _("<p>(Send questions and comments to "), Link("mailto:%s" % mm_cfg.MAILMAN_OWNER, mm_cfg.MAILMAN_OWNER), ".)<p>" @@ -207,11 +216,11 @@ def FormatAdminOverview(error=None): if advertised: table.AddRow([' ', ' ']) - table.AddRow([Bold("List"), Bold("Description")]) + table.AddRow([Bold(_("List")), Bold(_("Description"))]) for l in advertised: table.AddRow( [Link(l.GetScriptURL('admin'), Bold(l.real_name)), - l.description or Italic('[no description available]'), + l.description or Italic(_('[no description available]')), ]) doc.AddItem(table) @@ -227,24 +236,25 @@ def FormatConfiguration(doc, mlist, category, category_suffix, cgi_data): if k == category: label = v - doc.SetTitle('%s Administration (%s)' % (mlist.real_name, label)) - doc.AddItem(Center(Header(2, '%s mailing list administration<br>%s' - % (mlist.real_name, label + ' Section')))) + realname = mlist.real_name + doc.SetTitle(_('%(realname)s Administration (%(label)s)')) + doc.AddItem(Center(Header(2, _( + '%(realname)s mailing list administration<br>%(label)s Section')))) doc.AddItem('<hr>') linktable = Table(valign="top") - linktable.AddRow([Center(Bold("Configuration Categories")), - Center(Bold("Other Administrative Activities"))]) + linktable.AddRow([Center(Bold(_("Configuration Categories"))), + Center(Bold(_("Other Administrative Activities")))]) adminurl = mlist.GetScriptURL('admin') otherlinks = UnorderedList() otherlinks.AddItem(Link(mlist.GetScriptURL('admindb'), - 'Tend to pending administrative requests')) + _('Tend to pending administrative requests'))) otherlinks.AddItem(Link(mlist.GetScriptURL('listinfo'), - 'Go to the general list information page')) + _('Go to the general list information page'))) otherlinks.AddItem(Link(mlist.GetScriptURL('edithtml'), - 'Edit the HTML for the public list pages')) + _('Edit the HTML for the public list pages'))) otherlinks.AddItem(Link(mlist.GetBaseArchiveURL(), 'Go to list archives')) otherlinks.AddItem(Link('%s/logout' % adminurl, # TBD: What I really want is a blank line :/ @@ -274,12 +284,12 @@ def FormatConfiguration(doc, mlist, category, category_suffix, cgi_data): doc.AddItem(form) if category == 'general': - andpassmsg = " (You can change your password there, too.)" + andpassmsg = _(" (You can change your password there, too.)") else: andpassmsg = "" - form.AddItem("Make your changes below, and then submit them" - " using the button at the bottom.%s<p>" - % andpassmsg) + form.AddItem(_("Make your changes below, and then submit them" + " using the button at the bottom.") + + andpassmsg + '<p>') form.AddItem(FormatOptionsSection(category, mlist, cgi_data)) @@ -311,7 +321,7 @@ def FormatOptionsSection(category, mlist, cgi_data): colspan=2, bgcolor="#99ccff") def ColHeader(big_table = big_table): - big_table.AddRow([Center(Bold('Description')), Center(Bold('Value'))]) + big_table.AddRow([Center(Bold(_('Description'))), Center(Bold(_('Value')))]) big_table.AddCellInfo(max(big_table.GetCurrentRowIndex(), 0), 0, width="15%") big_table.AddCellInfo(max(big_table.GetCurrentRowIndex(), 0), 1, @@ -351,7 +361,7 @@ def AddOptionsTableItem(table, item, category, mlist, detailsp=1): varname, kind, params, dependancies, descr, elaboration = got except ValueError, msg: syslog('error', 'admin: %s' % msg) - return Italic("<malformed option>") + return Italic(_("<malformed option>")) descr = GetItemGuiDescr(mlist, category, varname, descr, detailsp) val = GetItemGuiValue(mlist, kind, varname, params) table.AddRow([descr, val]) @@ -373,7 +383,7 @@ def FormatOptionHelp(doc, varref, mlist): item = i break if not item: - bad = 'Option %s/%s not found: %s' % ( + bad = _('Option %s/%s not found: %s') % ( category, varname, os.environ.get('PATH_INFO')) AddErrorMessage(doc, bad) return @@ -386,12 +396,13 @@ def FormatOptionHelp(doc, varref, mlist): varname, kind, params, dependancies, descr = got elaboration = descr header = Table(width="100%") - legend = ('%s Mailing list Configuration Help<br><em>%s</em> Option' - % (mlist.real_name, varname)) + realname = mlist.real_name + legend = (_("""%(realname)s Mailing list Configuration Help + <br><em>%(varname)s</em> Option""")) header.AddRow([Center(Header(3, legend))]) header.AddCellInfo(max(header.GetCurrentRowIndex(), 0), 0, colspan=2, bgcolor="#99ccff") - doc.SetTitle("Mailman %s List Option Help" % varname) + doc.SetTitle(_("Mailman %(varname)s List Option Help")) doc.AddItem(header) doc.AddItem("<b>%s</b> (%s): %s<p>" % (varname, category, descr)) doc.AddItem("%s<p>" % elaboration) @@ -403,12 +414,12 @@ def FormatOptionHelp(doc, varref, mlist): form.AddItem('<p>') form.AddItem(Center(FormatSubmit())) doc.AddItem(Center(form)) - doc.AddItem("""<em><strong>Warning:</strong> changing this option here + doc.AddItem(_("""<em><strong>Warning:</strong> changing this option here could cause other screens to be out-of-sync. Be sure to reload any other pages that are displaying this option for this mailing list. You can - also """) + also """)) doc.AddItem(Link('%s/%s' % (mlist.GetScriptURL('admin'), category), - 'return to the ' + category + ' options page.')) + _('return to the %(category)s options page.'))) doc.AddItem('</em>') doc.AddItem(mlist.GetMailmanFooter()) @@ -428,7 +439,7 @@ def GetItemCharacteristics(table_entry): elif len(table_entry) == 6: varname, kind, params, dependancies, descr, elaboration = table_entry else: - raise ValueError, ("Badly formed options entry:\n %s" + raise ValueError, (_("Badly formed options entry:\n %s") % table_entry) return (varname, kind, params, dependancies, descr, elaboration) @@ -482,9 +493,9 @@ def GetItemGuiValue(mlist, kind, varname, params): if not val: val = '' container = Container() - container.AddItem('<em>Enter the text below, or...</em><br>') + container.AddItem(_('<em>Enter the text below, or...</em><br>')) container.AddItem(TextArea(varname, val, r, c)) - container.AddItem('<br><em>...specify a file to upload</em><br>') + container.AddItem(_('<br><em>...specify a file to upload</em><br>')) container.AddItem(FileUpload(varname+'_upload', r, c)) return container @@ -504,9 +515,9 @@ def GetItemGuiDescr(mlist, category, varname, descr, detailsp): else: text = '<div ALIGN="right">' + descr + '</div>' if varname[0] == '_': - text = text + '''<div ALIGN="right"><br><em><strong>Note:</strong> + text = text + _('''<div ALIGN="right"><br><em><strong>Note:</strong> setting this value performs an immediate action but does not modify - permanent state.</em></div>''' + permanent state.</em></div>''') return text @@ -514,27 +525,28 @@ def GetItemGuiDescr(mlist, category, varname, descr, detailsp): def FormatMembershipOptions(mlist, cgi_data): container = Container() header = Table(width="100%") - header.AddRow([Center(Header(2, "Membership Management"))]) + header.AddRow([Center(Header(2, _("Membership Management")))]) header.AddCellInfo(max(header.GetCurrentRowIndex(), 0), 0, colspan=2, bgcolor="#99ccff") container.AddItem(header) user_table = Table(width="90%", border='2') - user_table.AddRow([Center(Header(4, "Membership List"))]) + user_table.AddRow([Center(Header(4, _("Membership List")))]) user_table.AddCellInfo(user_table.GetCurrentRowIndex(), user_table.GetCurrentCellIndex(), bgcolor="#cccccc", colspan=8) + membercnt = len(mlist.members) + len(mlist.digest_members) + chunksz = mlist.admin_member_chunksize user_table.AddRow( - [Center(Italic("(%s members total, max. %s at a time displayed)" % - (len(mlist.members) - + len(mlist.digest_members), - mlist.admin_member_chunksize)))]) + [Center(Italic(_( + "(%(membercnt)s members total, max. %(chunksz)s at a time displayed)") + ))]) user_table.AddCellInfo(user_table.GetCurrentRowIndex(), user_table.GetCurrentCellIndex(), bgcolor="#cccccc", colspan=8) - user_table.AddRow(map(Center, ['member address', 'subscr', - 'hide', 'nomail', 'ack', 'not metoo', - 'digest', 'plain'])) + user_table.AddRow(map(Center, [_('member address'), _('subscr'), + _('hide'), _('nomail'), _('ack'), _('not metoo'), + _('digest'), _('plain')])) rowindex = user_table.GetCurrentRowIndex() for i in range(8): user_table.AddCellInfo(rowindex, i, bgcolor='#cccccc') @@ -546,15 +558,15 @@ def FormatMembershipOptions(mlist, cgi_data): else: chunk = string.atoi(cgi_data["chunk"].value) all = chunks[chunk] - footer = ("<p><em>To View other sections, " - "click on the appropriate range listed below</em>") + footer = (_("<p><em>To View other sections, " + "click on the appropriate range listed below</em>")) chunk_indices = range(len(chunks)) chunk_indices.remove(chunk) buttons = [] for ci in chunk_indices: start, end = chunks[ci][0], chunks[ci][-1] url = mlist.GetScriptURL('admin') - buttons.append("<a href=%s/members?chunk=%d> from %s to %s </a>" + buttons.append("<a href=%s/members?chunk=%d>" + _("from %s to %s") + "</a>" % (url, ci, start, end)) buttons = apply(UnorderedList, tuple(buttons)) footer = footer + buttons.Format() + "<p>" @@ -592,25 +604,25 @@ def FormatMembershipOptions(mlist, cgi_data): user_table.AddRow(cells) container.AddItem(Center(user_table)) legend = UnorderedList() - legend.AddItem('<b>subscr</b> -- Is the member subscribed?') - legend.AddItem("<b>hide</b> -- Is the member's address " - "concealed on the list of subscribers?") - legend.AddItem('<b>nomail</b> -- Is delivery to the member disabled?') - legend.AddItem('<b>ack</b> -- ' - 'Does the member get acknowledgements of their posts?') - legend.AddItem('<b>not metoo</b> -- ' - 'Does the member avoid copies of their own posts?') - legend.AddItem('<b>digest</b> -- ' - 'Does the member get messages in digests? ' - '(otherwise, individual messages)') + legend.AddItem(_('<b>subscr</b> -- Is the member subscribed?')) + legend.AddItem(_("<b>hide</b> -- Is the member's address " + "concealed on the list of subscribers?")) + legend.AddItem(_('<b>nomail</b> -- Is delivery to the member disabled?')) + legend.AddItem(_('<b>ack</b> -- ' + 'Does the member get acknowledgements of their posts?')) + legend.AddItem(_('<b>not metoo</b> -- ' + 'Does the member avoid copies of their own posts?')) + legend.AddItem(_('<b>digest</b> -- ' + 'Does the member get messages in digests? ' + '(otherwise, individual messages)')) legend.AddItem( - '<b>plain</b> -- ' - 'If getting digests, does the member get plain text digests? ' - '(otherwise, MIME)') + _('<b>plain</b> -- ' + 'If getting digests, does the member get plain text digests? ' + '(otherwise, MIME)')) container.AddItem(legend.Format()) container.AddItem(footer) t = Table(width="90%") - t.AddRow([Center(Header(4, "Mass Subscribe Members"))]) + t.AddRow([Center(Header(4, _("Mass Subscribe Members")))]) t.AddCellInfo(t.GetCurrentRowIndex(), t.GetCurrentCellIndex(), bgcolor="#cccccc", colspan=8) @@ -620,14 +632,14 @@ def FormatMembershipOptions(mlist, cgi_data): else: nochecked = 1 yeschecked = 0 - t.AddRow([("<b>1.</b> Send Welcome message to this batch? " + t.AddRow([("<b>1.</b>" + _("Send Welcome message to this batch? ") + RadioButton("send_welcome_msg_to_this_batch", 0, nochecked).Format() - + " no " + + _(" no ") + RadioButton("send_welcome_msg_to_this_batch", 1, yeschecked).Format() - + " yes ")]) - t.AddRow(["<b>2.</b> Enter one address per line: <p>"]) + + _(" yes "))]) + t.AddRow(["<b>2.</b>" + _("Enter one address per line:") + "<p>"]) container.AddItem(Center(t)) container.AddItem(Center(TextArea(name='subscribees', rows=10,cols=60,wrap=None))) @@ -640,17 +652,17 @@ def FormatPasswordStuff(): cellspacing=0, cellpadding=2, valign="top") change_pw_table.AddRow( - [Bold(Center('To Change The Administrator Password'))]) + [Bold(Center(_('To Change The Administrator Password')))]) change_pw_table.AddCellInfo(0, 0, align="left", colspan=2) old = Table(bgcolor="#99cccc", border=1, cellspacing=0, cellpadding=2, valign="top") - old.AddRow(['<div ALIGN="right"> Enter current password:</div>', + old.AddRow(['<div ALIGN="right">' + _(" Enter current password:") + '</div>', PasswordBox('adminpw')]) new = Table(bgcolor="#99cccc", border=1, cellspacing=0, cellpadding=2, valign="top") - new.AddRow(['<div ALIGN="right"> Enter new password: </div>', + new.AddRow(['<div ALIGN="right">' + _(" Enter new password:") + '</div>', PasswordBox('newpw')]) - new.AddRow(['<div ALIGN="right">Confirm new password:</div>', + new.AddRow(['<div ALIGN="right">' + _("Confirm new password:") + '</div>', PasswordBox('confirmpw')]) change_pw_table.AddRow([old, new]) change_pw_table.AddCellInfo(1, 0, align="left", valign="top") @@ -662,7 +674,7 @@ def FormatPasswordStuff(): def FormatSubmit(): submit = Table(bgcolor="#99ccff", border=0, cellspacing=0, cellpadding=2) - submit.AddRow([Bold(SubmitButton('submit', 'Submit Your Changes'))]) + submit.AddRow([Bold(SubmitButton('submit', _('Submit Your Changes')))]) submit.AddCellInfo(submit.GetCurrentRowIndex(), 0, align="middle") return submit @@ -758,25 +770,25 @@ def ChangeOptions(mlist, category, cgi_info, document): confirmed = 1 except Errors.MMBadPasswordError: AddErrorMessage(document, - 'Incorrect administrator password', + _('Incorrect administrator password'), tag='Error: ') if confirmed: new = string.strip(cgi_info['newpw'].value) confirm = string.strip(cgi_info['confirmpw'].value) if new == '' and confirm == '': AddErrorMessage(document, - 'Empty admin passwords are not allowed', + _('Empty admin passwords are not allowed'), tag='Error: ') elif new == confirm: mlist.password = crypt(new, Utils.GetRandomSeed()) # Re-authenticate (to set new cookie) mlist.WebAuthenticate(password=new, cookie='admin') else: - AddErrorMessage(document, 'Passwords did not match', + AddErrorMessage(document, _('Passwords did not match'), tag='Error: ') else: AddErrorMessage(document, - 'You must type in your new password twice', + _('You must type in your new password twice'), tag='Error: ') # # for some reason, the login page mangles important values for the list @@ -827,9 +839,9 @@ def ChangeOptions(mlist, category, cgi_info, document): if property == 'real_name' and \ string.lower(value) <> string.lower(mlist._internal_name): # then don't install this value. - document.AddItem("""<p><b>real_name</b> attribute not + document.AddItem(_("""<p><b>real_name</b> attribute not changed! It must differ from the list's name by case - only.<p>""") + only.<p>""")) continue setattr(mlist, property, value) # @@ -858,22 +870,22 @@ def ChangeOptions(mlist, category, cgi_info, document): # result[name] is set from sys.exc_info()[:2] e, v = result[name] if e is Errors.MMAlreadyAMember: - subscribe_errors.append((name, 'Already a member')) + subscribe_errors.append((name, _('Already a member'))) elif e is Errors.MMBadEmailError: if name == '': name = '<blank line>' subscribe_errors.append( - (name, "Bad/Invalid email address")) + (name, _("Bad/Invalid email address"))) elif e is Errors.MMHostileAddress: subscribe_errors.append( - (name, "Hostile Address (illegal characters)")) + (name, _("Hostile Address (illegal characters)"))) if subscribe_success: - document.AddItem(Header(5, "Successfully Subscribed:")) + document.AddItem(Header(5, _("Successfully Subscribed:"))) document.AddItem(apply(UnorderedList, tuple((subscribe_success)))) document.AddItem("<p>") # ApprovedAddMembers will already have saved the list for us. if subscribe_errors: - document.AddItem(Header(5, "Error Subscribing:")) + document.AddItem(Header(5, _("Error Subscribing:"))) items = map(lambda x: "%s -- %s" % (x[0], x[1]), subscribe_errors) document.AddItem(apply(UnorderedList, tuple((items)))) document.AddItem("<p>") @@ -894,7 +906,7 @@ def ChangeOptions(mlist, category, cgi_info, document): try: mlist.DeleteMember(user) except Errors.MMNoSuchUserError: - errors.append((user, 'Not subscribed')) + errors.append((user, _('Not subscribed'))) continue value = cgi_info.has_key('%s_digest' % user) try: @@ -910,7 +922,7 @@ def ChangeOptions(mlist, category, cgi_info, document): else: mlist.SetUserOption(user, opt_code, 0, save_list=0) if errors: - document.AddItem(Header(5, "Error Unsubscribing:")) + document.AddItem(Header(5, _("Error Unsubscribing:"))) items = map(lambda x: "%s -- %s" % (x[0], x[1]), errors) document.AddItem(apply(UnorderedList, tuple((items)))) document.AddItem("<p>") |
