summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBarry Warsaw2009-02-12 20:36:21 -0500
committerBarry Warsaw2009-02-12 20:36:21 -0500
commit62f4c909f90535986614a411db982bdcccaec3a1 (patch)
tree2fe5dd3316cea73f63cb34230d848758050eade3
parent2b28803e7165e91d812cd9e9e3804a6d9bdce8a1 (diff)
downloadmailman-62f4c909f90535986614a411db982bdcccaec3a1.tar.gz
mailman-62f4c909f90535986614a411db982bdcccaec3a1.tar.zst
mailman-62f4c909f90535986614a411db982bdcccaec3a1.zip
Much clean up of the language code, though more can be done. Factor out the
language manager stuff into a separate Language class, and be clearer in the APIs about whether we want a language code or a Language instance. The impetus to this was to get rid of Utils.GetCharSet(), which is done.
-rw-r--r--.bzrignore1
-rw-r--r--src/mailman/Archiver/HyperArch.py54
-rw-r--r--src/mailman/Utils.py14
-rw-r--r--src/mailman/app/bounces.py8
-rw-r--r--src/mailman/app/moderator.py14
-rw-r--r--src/mailman/app/notifications.py6
-rw-r--r--src/mailman/app/replybot.py2
-rw-r--r--src/mailman/bin/add_members.py4
-rw-r--r--src/mailman/bin/checkdbs.py16
-rw-r--r--src/mailman/bin/config_list.py11
-rw-r--r--src/mailman/bin/create_list.py6
-rw-r--r--src/mailman/chains/hold.py16
-rw-r--r--src/mailman/config/config.py2
-rw-r--r--src/mailman/constants.py5
-rw-r--r--src/mailman/database/mailinglist.py20
-rw-r--r--src/mailman/database/preferences.py19
-rw-r--r--src/mailman/docs/languages.txt6
-rw-r--r--src/mailman/docs/requests.txt6
-rw-r--r--src/mailman/docs/users.txt4
-rw-r--r--src/mailman/email/message.py12
-rw-r--r--src/mailman/i18n.py18
-rw-r--r--src/mailman/interfaces/languages.py2
-rw-r--r--src/mailman/languages/language.py47
-rw-r--r--src/mailman/languages/manager.py2
-rw-r--r--src/mailman/mta/smtp_direct.py8
-rw-r--r--src/mailman/pipeline/acknowledge.py13
-rw-r--r--src/mailman/pipeline/cook_headers.py12
-rw-r--r--src/mailman/pipeline/decorate.py3
-rw-r--r--src/mailman/pipeline/docs/replybot.txt5
-rw-r--r--src/mailman/pipeline/moderate.py15
-rw-r--r--src/mailman/pipeline/scrubber.py18
-rw-r--r--src/mailman/queue/__init__.py4
-rw-r--r--src/mailman/queue/command.py3
-rw-r--r--src/mailman/queue/digest.py8
-rw-r--r--src/mailman/styles/default.py6
35 files changed, 228 insertions, 162 deletions
diff --git a/.bzrignore b/.bzrignore
index 8672761e7..19610a565 100644
--- a/.bzrignore
+++ b/.bzrignore
@@ -16,3 +16,4 @@ develop-eggs
parts
./bin
eggs
+diff.txt
diff --git a/src/mailman/Archiver/HyperArch.py b/src/mailman/Archiver/HyperArch.py
index 26f32bdd0..d78831e8e 100644
--- a/src/mailman/Archiver/HyperArch.py
+++ b/src/mailman/Archiver/HyperArch.py
@@ -80,14 +80,14 @@ if sys.platform == 'darwin':
-def html_quote(s, lang=None):
+def html_quote(s, langcode=None):
repls = ( ('&', '&'),
("<", '&lt;'),
(">", '&gt;'),
('"', '&quot;'))
for thing, repl in repls:
s = s.replace(thing, repl)
- return Utils.uncanonstr(s, lang)
+ return Utils.uncanonstr(s, langcode)
def url_quote(s):
@@ -107,7 +107,7 @@ def sizeof(filename, lang):
if e.errno <> errno.ENOENT: raise
return _('size not available')
if size < 1000:
- with i18n.using_language(lang):
+ with i18n.using_language(lang.code):
out = _(' %(size)i bytes ')
return out
elif size < 1000000:
@@ -124,7 +124,7 @@ def CGIescape(arg, lang=None):
s = Utils.websafe(arg)
else:
s = Utils.websafe(str(arg))
- return Utils.uncanonstr(s.replace('"', '&quot;'), lang)
+ return Utils.uncanonstr(s.replace('"', '&quot;'), lang.code)
# Parenthesized human name
paren_name_pat = re.compile(r'([(].*[)])')
@@ -184,7 +184,7 @@ def quick_maketext(templatefile, dict=None, lang=None, mlist=None):
template = _templatecache.get(filepath)
if filepath is None or template is None:
# Use the basic maketext, with defaults to get the raw template
- template, filepath = Utils.findtext(templatefile, lang=lang,
+ template, filepath = Utils.findtext(templatefile, lang=lang.code,
raw=True, mlist=mlist)
_templatefilepathcache[cachekey] = filepath
_templatecache[filepath] = template
@@ -196,16 +196,14 @@ def quick_maketext(templatefile, dict=None, lang=None, mlist=None):
text = Template(template).safe_substitute(**dict)
except UnicodeError:
# Try again after coercing the template to unicode
- utemplate = unicode(template,
- Utils.GetCharSet(lang),
- 'replace')
+ utemplate = unicode(template, lang.charset, 'replace')
text = Template(utemplate).safe_substitute(**dict)
except (TypeError, ValueError):
# The template is really screwed up
pass
# Make sure the text is in the given character set, or html-ify any bogus
# characters.
- return Utils.uncanonstr(text, lang)
+ return Utils.uncanonstr(text, lang.code)
@@ -256,7 +254,7 @@ class Article(pipermail.Article):
# article (for this list) could be different from the site-wide
# preferred language, so we need to ensure no side-effects will
# occur. Think what happens when executing bin/arch.
- with i18n.using_language(lang):
+ with i18n.using_language(lang.code):
if self.author == self.email:
self.author = self.email = re.sub('@', _(' at '),
self.email)
@@ -269,7 +267,7 @@ class Article(pipermail.Article):
self.ctype = ctype.lower()
self.cenc = cenc.lower()
self.decoded = {}
- cset = Utils.GetCharSet(mlist.preferred_language)
+ cset = mlist.preferred_language.charset
cset_out = Charset(cset).output_charset or cset
charset = message.get_content_charset(cset_out)
if charset:
@@ -282,7 +280,7 @@ class Article(pipermail.Article):
body = message.get_payload(decode=True)
except binascii.Error:
body = None
- if body and charset != Utils.GetCharSet(self._lang):
+ if body and charset != self._lang.charset:
# decode body
try:
body = unicode(body, charset)
@@ -337,7 +335,7 @@ class Article(pipermail.Article):
self._mlist = mlist
def quote(self, buf):
- return html_quote(buf, self._lang)
+ return html_quote(buf, self._lang.code)
def decode_headers(self):
"""MIME-decode headers.
@@ -359,7 +357,7 @@ class Article(pipermail.Article):
self.decoded['email'] = email
if subject:
if as_boolean(config.archiver.pipermail.obscure_email_addresses):
- with i18n.using_language(self._lang):
+ with i18n.using_language(self._lang.code):
atmark = _(' at ')
subject = re.sub(r'([-+,.\w]+)@([-+.\w]+)',
'\g<1>' + atmark + '\g<2>', subject)
@@ -388,7 +386,7 @@ class Article(pipermail.Article):
ustr = make_header(pairs).__unicode__()
except (LookupError, UnicodeError, ValueError, HeaderParseError):
# assume list's language
- cset = Utils.GetCharSet(self._mlist.preferred_language)
+ cset = self._mlist.preferred_language.charset
if cset == 'us-ascii':
cset = 'iso-8859-1' # assume this for English list
ustr = unicode(field, cset, 'replace')
@@ -397,7 +395,7 @@ class Article(pipermail.Article):
def as_html(self):
d = self.__dict__.copy()
# avoid i18n side-effects
- with i18n.using_language(self._lang):
+ with i18n.using_language(self._lang.code):
d["prev"], d["prev_wsubj"] = self._get_prev()
d["next"], d["next_wsubj"] = self._get_next()
@@ -420,7 +418,7 @@ class Article(pipermail.Article):
d['listurl'] = self._mlist.script_url('listinfo')
d['listname'] = self._mlist.real_name
d['encoding'] = ''
- charset = Utils.GetCharSet(self._lang)
+ charset = self._lang.charset
d["encoding"] = html_charset % charset
self._add_decoded(d)
@@ -506,12 +504,12 @@ class Article(pipermail.Article):
if d['_message_id']:
headers.append('Message-ID: %(_message_id)s')
body = EMPTYSTRING.join(self.body)
- cset = Utils.GetCharSet(self._lang)
+ cset = self._lang.charset
# Coerce the body to Unicode and replace any invalid characters.
if not isinstance(body, unicode):
body = unicode(body, cset, 'replace')
if as_boolean(config.archiver.pipermail.obscure_email_addresses):
- with i18n.using_language(self._lang):
+ with i18n.using_language(self._lang.code):
atmark = _(' at ')
body = re.sub(r'([-+,.\w]+)@([-+.\w]+)',
'\g<1>' + atmark + '\g<2>', body)
@@ -577,7 +575,7 @@ class HyperArchive(pipermail.T):
self.maillist = maillist
self._lock_file = None
self.lang = maillist.preferred_language
- self.charset = Utils.GetCharSet(maillist.preferred_language)
+ self.charset = maillist.preferred_language.charset
if hasattr(self.maillist,'archive_volume_frequency'):
if self.maillist.archive_volume_frequency == 0:
@@ -612,8 +610,8 @@ class HyperArchive(pipermail.T):
mlist = self.maillist
# Convenience
def quotetime(s):
- return html_quote(i18n.ctime(s), self.lang)
- with i18n.using_language(mlist.preferred_language):
+ return html_quote(i18n.ctime(s), self.lang.code)
+ with i18n.using_language(mlist.preferred_language.code):
d = {"lastdate": quotetime(self.lastdate),
"archivedate": quotetime(self.archivedate),
"listinfo": mlist.script_url('listinfo'),
@@ -640,9 +638,9 @@ class HyperArchive(pipermail.T):
mlist = self.maillist
# Convenience
def quotetime(s):
- return html_quote(i18n.ctime(s), self.lang)
- with i18n.using_language(mlist.preferred_language):
- d = {"listname": html_quote(mlist.real_name, self.lang),
+ return html_quote(i18n.ctime(s), self.lang.code)
+ with i18n.using_language(mlist.preferred_language.code):
+ d = {"listname": html_quote(mlist.real_name, self.lang.code),
"archtype": self.type,
"archive": self.volNameToDesc(self.archive),
"listinfo": mlist.script_url('listinfo'),
@@ -682,7 +680,7 @@ class HyperArchive(pipermail.T):
'meta': '',
}
# Avoid i18n side-effects
- with i18n.using_language(mlist.preferred_language):
+ with i18n.using_language(mlist.preferred_language.code):
if not self.archives:
d["noarchive_msg"] = _(
'<P>Currently, there are no archives. </P>')
@@ -704,7 +702,7 @@ class HyperArchive(pipermail.T):
accum.append(self.html_TOC_entry(a))
d["archive_listing"] = EMPTYSTRING.join(accum)
# The TOC is always in the charset of the list's preferred language
- d['meta'] += html_charset % Utils.GetCharSet(mlist.preferred_language)
+ d['meta'] += html_charset % mlist.preferred_language.charset
# The site can disable public access to the mbox file.
if as_boolean(config.archiver.pipermail.public_mbox):
template = 'archtoc.html'
@@ -1096,7 +1094,7 @@ class HyperArchive(pipermail.T):
# TK: Prepare for unicode obscure.
atmark = _(' at ')
if lines and isinstance(lines[0], unicode):
- atmark = unicode(atmark, Utils.GetCharSet(self.lang), 'replace')
+ atmark = unicode(atmark, self.lang.charset, 'replace')
source = lines[:]
dest = lines
last_line_was_quoted = 0
diff --git a/src/mailman/Utils.py b/src/mailman/Utils.py
index 74582a7ad..866fa89ad 100644
--- a/src/mailman/Utils.py
+++ b/src/mailman/Utils.py
@@ -425,7 +425,7 @@ def findtext(templatefile, raw_dict=None, raw=False, lang=None, mlist=None):
if lang is not None:
languages.add(lang)
if mlist is not None:
- languages.add(mlist.preferred_language)
+ languages.add(mlist.preferred_language.code)
languages.add(config.mailman.default_language)
assert None not in languages, 'None in languages'
# Calculate the locations to scan
@@ -471,7 +471,8 @@ def findtext(templatefile, raw_dict=None, raw=False, lang=None, mlist=None):
else:
template = fp.read()
fp.close()
- template = unicode(template, GetCharSet(lang), 'replace')
+ charset = config.languages[lang].charset
+ template = unicode(template, charset, 'replace')
text = template
if raw_dict is not None:
text = expand(template, raw_dict)
@@ -485,13 +486,6 @@ def maketext(templatefile, dict=None, raw=False, lang=None, mlist=None):
-# XXX Replace this with direct calls. For now, existing uses of GetCharSet()
-# are too numerous to change.
-def GetCharSet(lang):
- return config.languages[lang].charset
-
-
-
# Figure out epoch seconds of midnight at the start of today (or the given
# 3-tuple date of (year, month, day).
def midnight(date=None):
@@ -512,7 +506,7 @@ def uncanonstr(s, lang=None):
if lang is None:
charset = 'us-ascii'
else:
- charset = GetCharSet(lang)
+ charset = config.languages[lang].charset
# See if the string contains characters only in the desired character
# set. If so, return it unchanged, except for coercing it to a byte
# string.
diff --git a/src/mailman/app/bounces.py b/src/mailman/app/bounces.py
index aa7f51c77..cea91b2e2 100644
--- a/src/mailman/app/bounces.py
+++ b/src/mailman/app/bounces.py
@@ -29,7 +29,7 @@ import logging
from email.mime.message import MIMEMessage
from email.mime.text import MIMEText
-from mailman import Utils
+from mailman.Utils import oneline
from mailman.email.message import Message, UserNotification
from mailman.i18n import _
@@ -45,8 +45,7 @@ def bounce_message(mlist, msg, e=None):
# to.
return
subject = msg.get('subject', _('(no subject)'))
- subject = Utils.oneline(subject,
- Utils.GetCharSet(mlist.preferred_language))
+ subject = oneline(subject, mlist.preferred_language.charset)
if e is None:
notice = _('[No bounce details are available]')
else:
@@ -57,8 +56,7 @@ def bounce_message(mlist, msg, e=None):
# BAW: Be sure you set the type before trying to attach, or you'll get
# a MultipartConversionError.
bmsg.set_type('multipart/mixed')
- txt = MIMEText(notice,
- _charset=Utils.GetCharSet(mlist.preferred_language))
+ txt = MIMEText(notice, _charset=mlist.preferred_language.charset)
bmsg.attach(txt)
bmsg.attach(MIMEMessage(msg))
bmsg.send(mlist)
diff --git a/src/mailman/app/moderator.py b/src/mailman/app/moderator.py
index 1f66e00ac..ffe0f779e 100644
--- a/src/mailman/app/moderator.py
+++ b/src/mailman/app/moderator.py
@@ -165,7 +165,7 @@ def handle_message(mlist, id, action,
member = mlist.members.get_member(addresses[0])
if member:
language = member.preferred_language
- with i18n.using_language(language):
+ with i18n.using_language(language.code):
fmsg = UserNotification(
addresses, mlist.bounces_address,
_('Forward of moderated message'),
@@ -234,14 +234,14 @@ def handle_subscription(mlist, id, action, comment=None):
_refuse(mlist, _('Subscription request'),
data['address'],
comment or _('[No reason given]'),
- lang=data['language'])
+ lang=config.languages[data['language']])
elif action is Action.accept:
key, data = requestdb.get_request(id)
enum_value = data['delivery_mode'].split('.')[-1]
delivery_mode = DeliveryMode(enum_value)
address = data['address']
realname = data['realname']
- language = data['language']
+ language = config.languages[data['language']]
password = data['password']
try:
add_member(mlist, address, realname, password,
@@ -329,16 +329,16 @@ def _refuse(mlist, request, recip, comment, origmsg=None, lang=None):
realname = mlist.real_name
if lang is None:
member = mlist.members.get_member(recip)
- if member:
- lang = member.preferred_language
+ lang = (member.preferred_language if member
+ else mlist.preferred_language)
text = Utils.maketext(
'refuse.txt',
{'listname' : mlist.fqdn_listname,
'request' : request,
'reason' : comment,
'adminaddr': mlist.owner_address,
- }, lang=lang, mlist=mlist)
- with i18n.using_language(lang):
+ }, lang=lang.code, mlist=mlist)
+ with i18n.using_language(lang.code):
# add in original message, but not wrap/filled
if origmsg:
text = NL.join(
diff --git a/src/mailman/app/notifications.py b/src/mailman/app/notifications.py
index b1d77dc6f..fcbfe95be 100644
--- a/src/mailman/app/notifications.py
+++ b/src/mailman/app/notifications.py
@@ -73,7 +73,7 @@ def send_welcome_message(mlist, address, language, delivery_mode, text=''):
'optionsurl' : options_url,
'request_address' : mlist.request_address,
'welcome' : welcome,
- }, lang=language, mlist=mlist)
+ }, lang=language.code, mlist=mlist)
if delivery_mode is not DeliveryMode.regular:
digmode = _(' (Digest mode)')
else:
@@ -124,9 +124,9 @@ def send_admin_subscription_notice(mlist, address, full_name, language):
:param language: the language of the address's realname
:type language: string
"""
- with i18n.using_language(mlist.preferred_language):
+ with i18n.using_language(mlist.preferred_language.code):
subject = _('$mlist.real_name subscription notification')
- full_name = full_name.encode(Utils.GetCharSet(language), 'replace')
+ full_name = full_name.encode(language.charset, 'replace')
text = Utils.maketext(
'adminsubscribeack.txt',
{'listname' : mlist.real_name,
diff --git a/src/mailman/app/replybot.py b/src/mailman/app/replybot.py
index 0537f6645..b558e96aa 100644
--- a/src/mailman/app/replybot.py
+++ b/src/mailman/app/replybot.py
@@ -80,7 +80,7 @@ def autorespond_to_sender(mlist, sender, lang=None):
'owneremail': mlist.owner_address,
},
lang=lang)
- with i18n.using_language(lang):
+ with i18n.using_language(lang.code):
msg = Message.UserNotification(
sender, mlist.owner_address,
_('Last autoresponse notification for today'),
diff --git a/src/mailman/bin/add_members.py b/src/mailman/bin/add_members.py
index 9c87f4af9..540c0facb 100644
--- a/src/mailman/bin/add_members.py
+++ b/src/mailman/bin/add_members.py
@@ -22,12 +22,12 @@ import codecs
from cStringIO import StringIO
from email.utils import parseaddr
-from mailman import Message
from mailman import Utils
from mailman import i18n
from mailman.app.membership import add_member
from mailman.config import config
from mailman.core import errors
+from mailman.email.message import UserNotification
from mailman.interfaces.member import AlreadySubscribedError, DeliveryMode
from mailman.options import SingleMailingListOptions
@@ -175,7 +175,7 @@ def main():
if admin_notify:
subject = _('$mlist.real_name subscription notification')
- msg = Message.UserNotification(
+ msg = UserNotification(
mlist.owner, mlist.no_reply_address, subject,
outfp.getvalue(), mlist.preferred_language)
msg.send(mlist)
diff --git a/src/mailman/bin/checkdbs.py b/src/mailman/bin/checkdbs.py
index 2ce08aab7..10d34aa22 100644
--- a/src/mailman/bin/checkdbs.py
+++ b/src/mailman/bin/checkdbs.py
@@ -22,11 +22,11 @@ import optparse
from email.Charset import Charset
from mailman import MailList
-from mailman import Message
from mailman import Utils
from mailman import i18n
from mailman.app.requests import handle_request
from mailman.configuration import config
+from mailman.email.message import UserNotification
from mailman.version import MAILMAN_VERSION
_ = i18n._
@@ -59,7 +59,7 @@ Check for pending admin requests and mail the list owners if necessary."""))
def pending_requests(mlist):
# Must return a byte string
- lcset = Utils.GetCharSet(mlist.preferred_language)
+ lcset = mlist.preferred_language.charset
pending = []
first = True
requestsdb = config.db.get_list_requests(mlist)
@@ -101,7 +101,7 @@ Cause: $reason"""))
pending.append('')
# Coerce all items in pending to a Unicode so we can join them
upending = []
- charset = Utils.GetCharSet(mlist.preferred_language)
+ charset = mlist.preferred_language.charset
for s in pending:
if isinstance(s, unicode):
upending.append(s)
@@ -112,7 +112,7 @@ Cause: $reason"""))
# example, the request was pended while the list's language was French,
# but then it was changed to English before checkdbs ran.
text = NL.join(upending)
- charset = Charset(Utils.GetCharSet(mlist.preferred_language))
+ charset = Charset(mlist.preferred_language.charset)
incodec = charset.input_codec or 'ascii'
outcodec = charset.output_codec or 'ascii'
if isinstance(text, unicode):
@@ -185,10 +185,10 @@ def main():
subject = _('$count $realname moderator request(s) waiting')
else:
subject = _('$realname moderator request check result')
- msg = Message.UserNotification(mlist.GetOwnerEmail(),
- mlist.GetBouncesEmail(),
- subject, text,
- mlist.preferred_language)
+ msg = UserNotification(mlist.GetOwnerEmail(),
+ mlist.GetBouncesEmail(),
+ subject, text,
+ mlist.preferred_language)
msg.send(mlist, **{'tomoderators': True})
finally:
mlist.Unlock()
diff --git a/src/mailman/bin/config_list.py b/src/mailman/bin/config_list.py
index a5cec9480..89a9892cd 100644
--- a/src/mailman/bin/config_list.py
+++ b/src/mailman/bin/config_list.py
@@ -20,10 +20,10 @@ import sys
import time
import optparse
-from mailman import errors
from mailman import MailList
-from mailman import Utils
+from mailman import errors
from mailman import i18n
+from mailman.Utils import wrap
from mailman.configuration import config
from mailman.version import MAILMAN_VERSION
@@ -100,9 +100,8 @@ def do_output(listname, outfile, parser):
except errors.MMListError:
parser.error(_('No such list: $listname'))
# Preamble for the config info. PEP 263 charset and capture time.
- language = mlist.preferred_language
- charset = Utils.GetCharSet(language)
- i18n.set_language(language)
+ charset = mlist.preferred_language.charset
+ i18n.set_language(mlist.preferred_language.code)
if not charset:
charset = 'us-ascii'
when = time.ctime(time.time())
@@ -132,7 +131,7 @@ def do_list_categories(mlist, k, subcat, outfp):
label, gui = mlist.GetConfigCategories()[k]
if info is None:
return
- charset = Utils.GetCharSet(mlist.preferred_language)
+ charset = mlist.preferred_language.charset
print >> outfp, '##', k.capitalize(), _('options')
print >> outfp, '#'
# First, massage the descripton text, which could have obnoxious
diff --git a/src/mailman/bin/create_list.py b/src/mailman/bin/create_list.py
index 8058a7d67..59be836a2 100644
--- a/src/mailman/bin/create_list.py
+++ b/src/mailman/bin/create_list.py
@@ -17,12 +17,12 @@
import sys
-from mailman import Message
from mailman import Utils
from mailman import i18n
from mailman.app.lifecycle import create_list
from mailman.config import config
from mailman.core import errors
+from mailman.email.message import UserNotification
from mailman.interfaces.listmanager import ListAlreadyExistsError
from mailman.options import SingleMailingListOptions
@@ -121,8 +121,8 @@ def main():
# Set the I18N language to the list's preferred language so the header
# will match the template language. Stashing and restoring the old
# translation context is just (healthy? :) paranoia.
- with i18n.using_language(mlist.preferred_language):
- msg = Message.UserNotification(
+ with i18n.using_language(mlist.preferred_language.code):
+ msg = UserNotification(
owner_mail, mlist.no_reply_address,
_('Your new mailing list: $fqdn_listname'),
text, mlist.preferred_language)
diff --git a/src/mailman/chains/hold.py b/src/mailman/chains/hold.py
index 162834791..dd5b69db0 100644
--- a/src/mailman/chains/hold.py
+++ b/src/mailman/chains/hold.py
@@ -33,7 +33,7 @@ from email.utils import formatdate, make_msgid
from zope.interface import implements
from mailman import i18n
-from mailman.Utils import maketext, oneline, wrap, GetCharSet
+from mailman.Utils import maketext, oneline, wrap
from mailman.app.moderator import hold_message
from mailman.app.replybot import autorespond_to_sender, can_acknowledge
from mailman.chains.base import TerminalChainBase
@@ -86,7 +86,7 @@ class HoldChain(TerminalChainBase):
language = (member.preferred_language
if member else mlist.preferred_language)
# A substitution dictionary for the email templates.
- charset = GetCharSet(mlist.preferred_language)
+ charset = mlist.preferred_language.charset
original_subject = msg.get('subject')
if original_subject is None:
original_subject = _('(no subject)')
@@ -122,12 +122,12 @@ class HoldChain(TerminalChainBase):
# posting was held.
subject = _(
'Your message to $mlist.fqdn_listname awaits moderator approval')
- send_language = msgdata.get('lang', language)
+ send_language_code = msgdata.get('lang', language.code)
text = maketext('postheld.txt', substitutions,
- lang=send_language, mlist=mlist)
+ lang=send_language_code, mlist=mlist)
adminaddr = mlist.bounces_address
nmsg = UserNotification(msg.sender, adminaddr, subject, text,
- send_language)
+ config.languages[send_language_code])
nmsg.send(mlist)
# Now the message for the list moderators. This one should appear to
# come from <list>-owner since we really don't need to do bounce
@@ -135,9 +135,9 @@ class HoldChain(TerminalChainBase):
if mlist.admin_immed_notify:
# Now let's temporarily set the language context to that which the
# administrators are expecting.
- with i18n.using_language(mlist.preferred_language):
+ with i18n.using_language(mlist.preferred_language.code):
language = mlist.preferred_language
- charset = GetCharSet(language)
+ charset = language.charset
# We need to regenerate or re-translate a few values in the
# substitution dictionary.
#d['reason'] = _(reason) # XXX reason
@@ -160,7 +160,7 @@ discard the held message. Do this if the message is spam. If you reply to
this message and include an Approved: header with the list password in it, the
message will be approved for posting to the list. The Approved: header can
also appear in the first line of the body of the reply.""")),
- _charset=GetCharSet(language))
+ _charset=language.charset)
dmsg['Subject'] = 'confirm ' + token
dmsg['Sender'] = mlist.request_address
dmsg['From'] = mlist.request_address
diff --git a/src/mailman/config/config.py b/src/mailman/config/config.py
index 4af4ada4e..8ce5d3886 100644
--- a/src/mailman/config/config.py
+++ b/src/mailman/config/config.py
@@ -149,7 +149,7 @@ class Configuration(object):
for language in languages:
if language.enabled:
code = language.name.split('.')[1]
- self.languages.add_language(
+ self.languages.add(
code, language.charset, language.description)
# The default language must always be available.
assert self._config.mailman.default_language in self.languages
diff --git a/src/mailman/constants.py b/src/mailman/constants.py
index 39c4547f8..2cd48270c 100644
--- a/src/mailman/constants.py
+++ b/src/mailman/constants.py
@@ -17,7 +17,7 @@
"""Various constants and enumerations."""
-from __future__ import unicode_literals
+from __future__ import absolute_import, unicode_literals
__metaclass__ = type
__all__ = [
@@ -27,6 +27,7 @@ __all__ = [
from zope.interface import implements
+from mailman.config import config
from mailman.interfaces.member import DeliveryMode, DeliveryStatus
from mailman.interfaces.preferences import IPreferences
@@ -37,7 +38,7 @@ class SystemDefaultPreferences:
acknowledge_posts = False
hide_address = True
- preferred_language = 'en'
+ preferred_language = config.languages['en']
receive_list_copy = True
receive_own_postings = True
delivery_mode = DeliveryMode.regular
diff --git a/src/mailman/database/mailinglist.py b/src/mailman/database/mailinglist.py
index e380a71b1..605c51cd6 100644
--- a/src/mailman/database/mailinglist.py
+++ b/src/mailman/database/mailinglist.py
@@ -151,7 +151,7 @@ class MailingList(Model):
personalize = Enum()
pipeline = Unicode()
post_id = Int()
- preferred_language = Unicode()
+ _preferred_language = Unicode(name='preferred_language')
private_roster = Bool()
real_name = Unicode()
reject_these_nonmembers = Pickle()
@@ -200,6 +200,10 @@ class MailingList(Model):
self.digest_members = roster.DigestMemberRoster(self)
self.subscribers = roster.Subscribers(self)
+ def __repr__(self):
+ return '<mailing list "{0}" at {1:#x}>'.format(
+ self.fqdn_listname, id(self))
+
@property
def fqdn_listname(self):
"""See `IMailingList`."""
@@ -267,6 +271,14 @@ class MailingList(Model):
cookie = cookie))
return '{0}@{1}'.format(local_part, self.host_name)
- def __repr__(self):
- return '<mailing list "{0}" at {1:#x}>'.format(
- self.fqdn_listname, id(self))
+ @property
+ def preferred_language(self):
+ return config.languages[self._preferred_language]
+
+ @preferred_language.setter
+ def preferred_language(self, language):
+ # Accept both a language code and a `Language` instance.
+ try:
+ self._preferred_language = language.code
+ except AttributeError:
+ self._preferred_language = language
diff --git a/src/mailman/database/preferences.py b/src/mailman/database/preferences.py
index f3ee55673..31f9ce280 100644
--- a/src/mailman/database/preferences.py
+++ b/src/mailman/database/preferences.py
@@ -28,6 +28,7 @@ __all__ = [
from storm.locals import *
from zope.interface import implements
+from mailman.config import config
from mailman.database.model import Model
from mailman.database.types import Enum
from mailman.interfaces.preferences import IPreferences
@@ -40,7 +41,7 @@ class Preferences(Model):
id = Int(primary=True)
acknowledge_posts = Bool()
hide_address = Bool()
- preferred_language = Unicode()
+ _preferred_language = Unicode(name='preferred_language')
receive_list_copy = Bool()
receive_own_postings = Bool()
delivery_mode = Enum()
@@ -48,3 +49,19 @@ class Preferences(Model):
def __repr__(self):
return '<Preferences object at {0:#x}>'.format(id(self))
+
+ @property
+ def preferred_language(self):
+ if self._preferred_language is None:
+ return None
+ return config.languages[self._preferred_language]
+
+ @preferred_language.setter
+ def preferred_language(self, language):
+ if language is None:
+ self._preferred_language = None
+ # Accept both a language code and a `Language` instance.
+ try:
+ self._preferred_language = language.code
+ except AttributeError:
+ self._preferred_language = language
diff --git a/src/mailman/docs/languages.txt b/src/mailman/docs/languages.txt
index a429345a5..87c68f034 100644
--- a/src/mailman/docs/languages.txt
+++ b/src/mailman/docs/languages.txt
@@ -27,8 +27,8 @@ Adding a new language requires three pieces of information, the 2-character
language code, the English description of the language, and the character set
used by the language.
- >>> mgr.add_language('en', 'us-ascii', 'English')
- >>> mgr.add_language('it', 'iso-8859-1', 'Italian')
+ >>> mgr.add('en', 'us-ascii', 'English')
+ >>> mgr.add('it', 'iso-8859-1', 'Italian')
And you can get information for all known languages.
@@ -47,7 +47,7 @@ Other iterations
You can iterate over all the known language codes.
- >>> mgr.add_language('pl', 'iso-8859-2', 'Polish')
+ >>> mgr.add('pl', 'iso-8859-2', 'Polish')
>>> sorted(mgr.codes)
['en', 'it', 'pl']
diff --git a/src/mailman/docs/requests.txt b/src/mailman/docs/requests.txt
index 87b835fb8..a620338db 100644
--- a/src/mailman/docs/requests.txt
+++ b/src/mailman/docs/requests.txt
@@ -39,7 +39,7 @@ mailing list you need to get its requests object.
>>> from zope.interface.verify import verifyObject
>>> verifyObject(IRequests, config.db.requests)
True
- >>> mlist = config.db.list_manager.create(u'test@example.com')
+ >>> mlist = create_list(u'test@example.com')
>>> requests = config.db.requests.get_list_requests(mlist)
>>> verifyObject(IListRequests, requests)
True
@@ -215,7 +215,7 @@ Holding messages
For this section, we need a mailing list and at least one message.
- >>> mlist = config.db.list_manager.create(u'alist@example.com')
+ >>> mlist = create_list(u'alist@example.com')
>>> mlist.preferred_language = u'en'
>>> mlist.real_name = u'A Test List'
>>> msg = message_from_string("""\
@@ -678,7 +678,7 @@ Frank Person is now a member of the mailing list.
<Member: Frank Person <fperson@example.org>
on alist@example.com as MemberRole.member>
>>> member.preferred_language
- u'en'
+ <Language [en] English (USA)>
>>> print member.delivery_mode
DeliveryMode.regular
>>> user = config.db.user_manager.get_user(member.address.address)
diff --git a/src/mailman/docs/users.txt b/src/mailman/docs/users.txt
index ff7b9ca84..b557a280d 100644
--- a/src/mailman/docs/users.txt
+++ b/src/mailman/docs/users.txt
@@ -132,6 +132,8 @@ Users have preferences, but these preferences have no default settings.
Some of these preferences are booleans and they can be set to True or False.
+ >>> config.languages.add(u'it', u'iso-8859-1', u'Italian')
+
>>> from mailman.constants import DeliveryMode
>>> prefs = user_1.preferences
>>> prefs.acknowledge_posts = True
@@ -141,7 +143,7 @@ Some of these preferences are booleans and they can be set to True or False.
>>> prefs.delivery_mode = DeliveryMode.regular
>>> show_prefs(user_1.preferences)
acknowledge_posts : True
- preferred_language : it
+ preferred_language : <Language [it] Italian>
receive_list_copy : False
receive_own_postings : False
delivery_mode : DeliveryMode.regular
diff --git a/src/mailman/email/message.py b/src/mailman/email/message.py
index 2b552cd8c..984c58c76 100644
--- a/src/mailman/email/message.py
+++ b/src/mailman/email/message.py
@@ -42,7 +42,6 @@ from email.charset import Charset
from email.header import Header
from lazr.config import as_boolean
-from mailman.Utils import GetCharSet
from mailman.config import config
@@ -167,13 +166,10 @@ class UserNotification(Message):
def __init__(self, recip, sender, subject=None, text=None, lang=None):
Message.__init__(self)
- charset = 'us-ascii'
- if lang is not None:
- charset = GetCharSet(lang)
+ charset = (lang.charset if lang is not None else 'us-ascii')
+ subject = ('(no subject)' if subject is None else subject)
if text is not None:
self.set_payload(text.encode(charset), charset)
- if subject is None:
- subject = '(no subject)'
self['Subject'] = Header(subject.encode(charset), charset,
header_name='Subject', errors='replace')
self['From'] = sender
@@ -233,8 +229,8 @@ class OwnerNotification(UserNotification):
roster = mlist.owners
recips = [address.address for address in roster.addresses]
sender = config.mailman.site_owner
- lang = mlist.preferred_language
- UserNotification.__init__(self, recips, sender, subject, text, lang)
+ UserNotification.__init__(self, recips, sender, subject,
+ text, mlist.preferred_language)
# Hack the To header to look like it's going to the -owner address
del self['to']
self['To'] = mlist.owner_address
diff --git a/src/mailman/i18n.py b/src/mailman/i18n.py
index 12a06dc02..d06db4cb8 100644
--- a/src/mailman/i18n.py
+++ b/src/mailman/i18n.py
@@ -61,12 +61,12 @@ class attrdict(dict):
-def set_language(language=None):
+def set_language(language_code=None):
global _translation
- if language is not None:
- language = [language]
+ # gettext.translation() API requires None or a sequence.
+ codes = (None if language_code is None else [language_code])
try:
- _translation = gettext.translation('mailman', MESSAGES_DIR, language)
+ _translation = gettext.translation('mailman', MESSAGES_DIR, codes)
except IOError:
# The selected language was not installed in messages, so fall back to
# untranslated English.
@@ -82,15 +82,15 @@ def set_translation(translation):
_translation = translation
-class using_language(object):
- """Context manager for Python 2.5's `with` statement."""
- def __init__(self, language):
- self._language = language
+class using_language:
+ """Context manager for Python's `with` statement."""
+ def __init__(self, language_code):
+ self._language_code = language_code
self._old_translation = None
def __enter__(self):
self._old_translation = _translation
- set_language(self._language)
+ set_language(self._language_code)
def __exit__(self, *exc_info):
global _translation
diff --git a/src/mailman/interfaces/languages.py b/src/mailman/interfaces/languages.py
index a41a6e80e..7be5fca7b 100644
--- a/src/mailman/interfaces/languages.py
+++ b/src/mailman/interfaces/languages.py
@@ -47,7 +47,7 @@ class ILanguageManager(Interface):
Current, disabling languages is not supported.
"""
- def add_language(code, charset, description):
+ def add(code, charset, description):
"""Teach the language manager about a language.
:param code: The short two-character language code for the
diff --git a/src/mailman/languages/language.py b/src/mailman/languages/language.py
new file mode 100644
index 000000000..f5e83c255
--- /dev/null
+++ b/src/mailman/languages/language.py
@@ -0,0 +1,47 @@
+# Copyright (C) 2009 by the Free Software Foundation, Inc.
+#
+# This file is part of GNU Mailman.
+#
+# GNU Mailman is free software: you can redistribute it and/or modify it under
+# the terms of the GNU General Public License as published by the Free
+# Software Foundation, either version 3 of the License, or (at your option)
+# any later version.
+#
+# GNU Mailman is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+# more details.
+#
+# You should have received a copy of the GNU General Public License along with
+# GNU Mailman. If not, see <http://www.gnu.org/licenses/>.
+
+"""The representation of a language."""
+
+
+from __future__ import absolute_import, unicode_literals
+
+__metaclass__ = type
+__all__ = [
+ 'Language',
+ ]
+
+
+from zope.interface import implements
+from mailman.interfaces.languages import ILanguage
+
+
+
+class Language:
+ """The representation of a language."""
+
+ implements(ILanguage)
+
+ def __init__(self, code, charset, description):
+ self.code = code
+ self.charset = charset
+ self.description = description
+
+ def __str__(self):
+ return '<Language [{0.code}] {0.description}>'.format(self)
+
+ __repr__ = __str__
diff --git a/src/mailman/languages/manager.py b/src/mailman/languages/manager.py
index a5a3d02f2..96c00d09f 100644
--- a/src/mailman/languages/manager.py
+++ b/src/mailman/languages/manager.py
@@ -40,7 +40,7 @@ class LanguageManager:
# Mapping from 2-letter code to Language instance.
self._languages = {}
- def add_language(self, code, charset, description):
+ def add(self, code, charset, description):
"""See `ILanguageManager`."""
if code in self._languages:
raise ValueError('Language code already registered: ' + code)
diff --git a/src/mailman/mta/smtp_direct.py b/src/mailman/mta/smtp_direct.py
index 64694cfc5..d45bf15d6 100644
--- a/src/mailman/mta/smtp_direct.py
+++ b/src/mailman/mta/smtp_direct.py
@@ -45,7 +45,7 @@ from email.Header import Header
from email.Utils import formataddr
from zope.interface import implements
-from mailman import Utils
+from mailman.Utils import ParseEmail
from mailman.config import config
from mailman.core import errors
from mailman.i18n import _
@@ -304,8 +304,8 @@ def verpdeliver(mlist, msg, msgdata, envsender, failures, conn):
handler.process(mlist, msgcopy, msgdata)
# Calculate the envelope sender, which we may be VERPing
if msgdata.get('verp'):
- bmailbox, bdomain = Utils.ParseEmail(envsender)
- rmailbox, rdomain = Utils.ParseEmail(recip)
+ bmailbox, bdomain = ParseEmail(envsender)
+ rmailbox, rdomain = ParseEmail(recip)
if rdomain is None:
# The recipient address is not fully-qualified. We can't
# deliver it to this person, nor can we craft a valid verp
@@ -330,7 +330,7 @@ def verpdeliver(mlist, msg, msgdata, envsender, failures, conn):
# characters for which we can do nothing about. Once we have
# the name as Unicode, we can create a Header instance for it
# so that it's properly encoded for email transport.
- charset = Utils.GetCharSet(mlist.getMemberLanguage(recip))
+ charset = mlist.getMemberLanguage(recip).charset
if charset == 'us-ascii':
# Since Header already tries both us-ascii and utf-8,
# let's add something a bit more useful.
diff --git a/src/mailman/pipeline/acknowledge.py b/src/mailman/pipeline/acknowledge.py
index 2ee27a5ae..5daf30003 100644
--- a/src/mailman/pipeline/acknowledge.py
+++ b/src/mailman/pipeline/acknowledge.py
@@ -31,6 +31,7 @@ __all__ = [
from zope.interface import implements
from mailman import Utils
+from mailman.config import config
from mailman.email.message import Message, UserNotification
from mailman.i18n import _
from mailman.interfaces.handler import IHandler
@@ -60,21 +61,23 @@ class Acknowledge:
original_subject = msgdata.get(
'origsubj', msg.get('subject', _('(no subject)')))
# Get the user's preferred language.
- lang = msgdata.get('lang', member.preferred_language)
+ language = (config.languages[msgdata['lang']]
+ if 'lang' in msgdata
+ else member.preferred_language)
+ charset = config.languages[language.code].charset
# Now get the acknowledgement template.
realname = mlist.real_name
text = Utils.maketext(
'postack.txt',
- {'subject' : Utils.oneline(original_subject,
- Utils.GetCharSet(lang)),
+ {'subject' : Utils.oneline(original_subject, charset),
'listname' : realname,
'listinfo_url': mlist.script_url('listinfo'),
'optionsurl' : member.options_url,
- }, lang=lang, mlist=mlist, raw=True)
+ }, lang=language.code, mlist=mlist, raw=True)
# Craft the outgoing message, with all headers and attributes
# necessary for general delivery. Then enqueue it to the outgoing
# queue.
subject = _('$realname post acknowledgment')
usermsg = UserNotification(sender, mlist.bounces_address,
- subject, text, lang)
+ subject, text, language)
usermsg.send(mlist)
diff --git a/src/mailman/pipeline/cook_headers.py b/src/mailman/pipeline/cook_headers.py
index 7da413cd2..4d3e12eb1 100644
--- a/src/mailman/pipeline/cook_headers.py
+++ b/src/mailman/pipeline/cook_headers.py
@@ -32,7 +32,6 @@ from email.header import Header, decode_header, make_header
from email.utils import parseaddr, formataddr, getaddresses
from zope.interface import implements
-from mailman import Utils
from mailman.config import config
from mailman.i18n import _
from mailman.interfaces.handler import IHandler
@@ -53,7 +52,7 @@ def uheader(mlist, s, header_name=None, continuation_ws='\t', maxlinelen=None):
# non-ascii character is in the string. If there is and the charset is
# us-ascii then we use iso-8859-1 instead. If the string is ascii only
# we use 'us-ascii' if another charset is specified.
- charset = Utils.GetCharSet(mlist.preferred_language)
+ charset = mlist.preferred_language.charset
if nonascii.search(s):
# use list charset but ...
if charset == 'us-ascii':
@@ -181,7 +180,7 @@ def process(mlist, msg, msgdata):
return
# This will act like an email address for purposes of formataddr()
listid = '{0}.{1}'.format(mlist.list_name, mlist.host_name)
- cset = Utils.GetCharSet(mlist.preferred_language)
+ cset = mlist.preferred_language.charset
if mlist.description:
# Don't wrap the header since here we just want to get it properly RFC
# 2047 encoded.
@@ -288,7 +287,7 @@ def prefix_subject(mlist, msg, msgdata):
# subject: [subject prefix]
if subject.strip() == '':
subject = _('(no subject)')
- cset = Utils.GetCharSet(mlist.preferred_language)
+ cset = mlist.preferred_language.charset
# and substitute %d in prefix with post_id
try:
prefix = prefix % mlist.post_id
@@ -312,9 +311,8 @@ def prefix_subject(mlist, msg, msgdata):
def ch_oneline(headerstr):
- # Decode header string in one line and convert into single charset
- # copied and modified from ToDigest.py and Utils.py
- # return (string, cset) tuple as check for failure
+ # Decode header string in one line and convert into single charset.
+ # Return (string, cset) tuple as check for failure.
try:
d = decode_header(headerstr)
# At this point, we should rstrip() every string because some
diff --git a/src/mailman/pipeline/decorate.py b/src/mailman/pipeline/decorate.py
index 87313446d..3941c6509 100644
--- a/src/mailman/pipeline/decorate.py
+++ b/src/mailman/pipeline/decorate.py
@@ -31,7 +31,6 @@ import logging
from email.MIMEText import MIMEText
from zope.interface import implements
-from mailman import Utils
from mailman.config import config
from mailman.email.message import Message
from mailman.i18n import _
@@ -91,7 +90,7 @@ def process(mlist, msg, msgdata):
# TK: Message with 'charset=' cause trouble. So, instead of
# mgs.get_content_charset('us-ascii') ...
mcset = msg.get_content_charset() or 'us-ascii'
- lcset = Utils.GetCharSet(mlist.preferred_language)
+ lcset = mlist.preferred_language.charset
msgtype = msg.get_content_type()
# BAW: If the charsets don't match, should we add the header and footer by
# MIME multipart chroming the message?
diff --git a/src/mailman/pipeline/docs/replybot.txt b/src/mailman/pipeline/docs/replybot.txt
index f3c3281b3..3de6679dd 100644
--- a/src/mailman/pipeline/docs/replybot.txt
+++ b/src/mailman/pipeline/docs/replybot.txt
@@ -6,8 +6,7 @@ it receives on its posting address, or special robot addresses. Automatic
responses are subject to various conditions, such as headers in the original
message or the amount of time since the last auto-response.
- >>> from mailman.pipeline.replybot import process
- >>> mlist = config.db.list_manager.create(u'_xtest@example.com')
+ >>> mlist = create_list(u'_xtest@example.com')
>>> mlist.real_name = u'XTest'
>>> # Ensure that the virgin queue is empty, since we'll be checking this
@@ -36,6 +35,8 @@ will be sent, with 0 meaning "there is no grace period".
...
... help
... """)
+
+ >>> from mailman.pipeline.replybot import process
>>> process(mlist, msg, dict(toowner=True))
>>> len(virginq.files)
1
diff --git a/src/mailman/pipeline/moderate.py b/src/mailman/pipeline/moderate.py
index 8d6fc7d65..3714f3bfc 100644
--- a/src/mailman/pipeline/moderate.py
+++ b/src/mailman/pipeline/moderate.py
@@ -30,10 +30,10 @@ import re
from email.MIMEMessage import MIMEMessage
from email.MIMEText import MIMEText
-from mailman import Utils
+from mailman.Utils import wrap
from mailman.config import config
from mailman.core import errors
-from mailman.email.message import Message
+from mailman.email.message import UserNotification
from mailman.i18n import _
@@ -156,17 +156,16 @@ error, contact the mailing list owner at %(listowner)s."""))
def do_discard(mlist, msg):
# Do we forward auto-discards to the list owners?
if mlist.forward_auto_discards:
- lang = mlist.preferred_language
varhelp = '%s/?VARHELP=privacy/sender/discard_these_nonmembers' % \
mlist.GetScriptURL('admin', absolute=1)
- nmsg = Message.UserNotification(mlist.GetOwnerEmail(),
- mlist.GetBouncesEmail(),
- _('Auto-discard notification'),
- lang=lang)
+ nmsg = UserNotification(mlist.GetOwnerEmail(),
+ mlist.GetBouncesEmail(),
+ _('Auto-discard notification'),
+ lang=mlist.preferred_language)
nmsg.set_type('multipart/mixed')
text = MIMEText(Utils.wrap(_(
'The attached message has been automatically discarded.')),
- _charset=Utils.GetCharSet(lang))
+ _charset=mlist.preferred_language.charset)
nmsg.attach(text)
nmsg.attach(MIMEMessage(msg))
nmsg.send(mlist)
diff --git a/src/mailman/pipeline/scrubber.py b/src/mailman/pipeline/scrubber.py
index 3ee68612f..1148c6518 100644
--- a/src/mailman/pipeline/scrubber.py
+++ b/src/mailman/pipeline/scrubber.py
@@ -42,7 +42,7 @@ from mimetypes import guess_all_extensions
from string import Template
from zope.interface import implements
-from mailman import Utils
+from mailman.Utils import oneline, websafe
from mailman.config import config
from mailman.core.errors import DiscardMessage
from mailman.core.plugins import get_plugin
@@ -175,7 +175,7 @@ def process(mlist, msg, msgdata=None):
return
dir = calculate_attachments_dir(mlist, msg, msgdata)
charset = format = delsp = None
- lcset = Utils.GetCharSet(mlist.preferred_language)
+ lcset = mlist.preferred_language.charset
lcset_out = Charset(lcset).output_charset or lcset
# Now walk over all subparts of this message and scrub out various types
for part in msg.walk():
@@ -206,7 +206,7 @@ def process(mlist, msg, msgdata=None):
not part.get_content_charset():
url = save_attachment(mlist, part, dir)
filename = part.get_filename(_('not available'))
- filename = Utils.oneline(filename, lcset)
+ filename = oneline(filename, lcset)
replace_payload_by_text(part, _("""\
An embedded and charset-unspecified text was scrubbed...
Name: $filename
@@ -236,7 +236,7 @@ URL: $url
else:
# HTML-escape it and store it as an attachment, but make it
# look a /little/ bit prettier. :(
- payload = Utils.websafe(part.get_payload(decode=True))
+ payload = websafe(part.get_payload(decode=True))
# For whitespace in the margin, change spaces into
# non-breaking spaces, and tabs into 8 of those. Then use a
# mono-space font. Still looks hideous to me, but then I'd
@@ -287,9 +287,9 @@ URL: $url
size = len(payload)
url = save_attachment(mlist, part, dir)
desc = part.get('content-description', _('not available'))
- desc = Utils.oneline(desc, lcset)
+ desc = oneline(desc, lcset)
filename = part.get_filename(_('not available'))
- filename = Utils.oneline(filename, lcset)
+ filename = oneline(filename, lcset)
replace_payload_by_text(part, _("""\
A non-text attachment was scrubbed...
Name: $filename
@@ -390,8 +390,8 @@ def save_attachment(mlist, msg, dir, filter_html=True):
# things as application/octet-streams since that seems the safest.
ctype = msg.get_content_type()
# i18n file name is encoded
- lcset = Utils.GetCharSet(mlist.preferred_language)
- filename = Utils.oneline(msg.get_filename(''), lcset)
+ lcset = mlist.preferred_language.charset
+ filename = oneline(msg.get_filename(''), lcset)
filename, fnext = os.path.splitext(filename)
# For safety, we should confirm this is valid ext for content-type
# but we can use fnext if we introduce fnext filtering
@@ -481,7 +481,7 @@ def save_attachment(mlist, msg, dir, filter_html=True):
elif ctype == 'message/rfc822':
submsg = msg.get_payload()
# BAW: I'm sure we can eventually do better than this. :(
- decodedpayload = Utils.websafe(str(submsg))
+ decodedpayload = websafe(str(submsg))
fp = open(path, 'w')
fp.write(decodedpayload)
fp.close()
diff --git a/src/mailman/queue/__init__.py b/src/mailman/queue/__init__.py
index 1f284ba4d..b7c6eb1a5 100644
--- a/src/mailman/queue/__init__.py
+++ b/src/mailman/queue/__init__.py
@@ -434,8 +434,8 @@ class Runner:
else mlist.preferred_language)
else:
language = mlist.preferred_language
- with i18n.using_language(language):
- msgdata['lang'] = language
+ with i18n.using_language(language.code):
+ msgdata['lang'] = language.code
keepqueued = self._dispose(mlist, msg, msgdata)
if keepqueued:
self.switchboard.enqueue(msg, msgdata)
diff --git a/src/mailman/queue/command.py b/src/mailman/queue/command.py
index 8a7793e9e..d32361cf9 100644
--- a/src/mailman/queue/command.py
+++ b/src/mailman/queue/command.py
@@ -195,9 +195,10 @@ class CommandRunner(Runner):
# Send a reply, but do not attach the original message. This is a
# compromise because the original message is often helpful in tracking
# down problems, but it's also a vector for backscatter spam.
+ language = config.languages[msgdata['lang']]
reply = UserNotification(msg.sender, mlist.bounces_address,
_('The results of your email commands'),
- lang=msgdata['lang'])
+ lang=language)
# Find a charset for the response body. Try ascii first, then
# latin-1 and finally falling back to utf-8.
reply_body = unicode(results)
diff --git a/src/mailman/queue/digest.py b/src/mailman/queue/digest.py
index e066be993..a590a9997 100644
--- a/src/mailman/queue/digest.py
+++ b/src/mailman/queue/digest.py
@@ -39,7 +39,7 @@ from email.mime.text import MIMEText
from email.utils import formatdate, getaddresses, make_msgid
from mailman import i18n
-from mailman.Utils import GetCharSet, maketext, oneline, wrap
+from mailman.Utils import maketext, oneline, wrap
from mailman.config import config
from mailman.core.errors import DiscardMessage
from mailman.i18n import _
@@ -55,7 +55,7 @@ class Digester:
def __init__(self, mlist, volume, digest_number):
self._mlist = mlist
- self._charset = GetCharSet(mlist.preferred_language)
+ self._charset = mlist.preferred_language.charset
# This will be used in the Subject, so use $-strings.
realname = mlist.real_name
issue = digest_number
@@ -298,8 +298,8 @@ class DigestRunner(Runner):
volume = msgdata['volume']
digest_number = msgdata['digest_number']
with nested(Mailbox(msgdata['digest_path']),
- i18n.using_language(mlist.preferred_language)) as (
- mailbox, language):
+ i18n.using_language(mlist.preferred_language.code)) as (
+ mailbox, language_code):
# Create the digesters.
mime_digest = MIMEDigester(mlist, volume, digest_number)
rfc1153_digest = RFC1153Digester(mlist, volume, digest_number)
diff --git a/src/mailman/styles/default.py b/src/mailman/styles/default.py
index 0f7869a75..ea4e1a342 100644
--- a/src/mailman/styles/default.py
+++ b/src/mailman/styles/default.py
@@ -30,7 +30,7 @@ import datetime
from zope.interface import implements
-from mailman import Utils
+from mailman.config import config
from mailman.i18n import _
from mailman.interfaces import Action, NewsModeration
from mailman.interfaces.mailinglist import (
@@ -157,8 +157,8 @@ $fqdn_listname
${listinfo_page}
"""
# Set this to Never if the list's preferred language uses us-ascii,
- # otherwise set it to As Needed
- if Utils.GetCharSet(mlist.preferred_language) == 'us-ascii':
+ # otherwise set it to As Needed.
+ if mlist.preferred_language.charset == 'us-ascii':
mlist.encode_ascii_prefixes = 0
else:
mlist.encode_ascii_prefixes = 2