diff --git a/Mailman/MTA/Postfix.py b/Mailman/MTA/Postfix.py
index 376f8b6..0a8395b 100644
--- a/Mailman/MTA/Postfix.py
+++ b/Mailman/MTA/Postfix.py
@@ -27,7 +27,7 @@ from stat import *
from Mailman import mm_cfg
from Mailman import Utils
from Mailman import LockFile
-from Mailman.i18n import _
+from Mailman.i18n import C_
from Mailman.MTA.Utils import makealiases
from Mailman.Logging.Syslog import syslog
@@ -314,7 +314,7 @@ def checkperms(state):
targetmode = S_IFREG | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP
for file in ALIASFILE, VIRTFILE:
if state.VERBOSE:
- print _('checking permissions on %(file)s')
+ print C_('checking permissions on %(file)s')
stat = None
try:
stat = os.stat(file)
@@ -324,9 +324,9 @@ def checkperms(state):
if stat and (stat[ST_MODE] & targetmode) <> targetmode:
state.ERRORS += 1
octmode = oct(stat[ST_MODE])
- print _('%(file)s permissions must be 066x (got %(octmode)s)'),
+ print C_('%(file)s permissions must be 066x (got %(octmode)s)'),
if state.FIX:
- print _('(fixing)')
+ print C_('(fixing)')
os.chmod(file, stat[ST_MODE] | targetmode)
else:
print
@@ -342,7 +342,7 @@ def checkperms(state):
raise
continue
if state.VERBOSE:
- print _('checking ownership of %(dbfile)s')
+ print C_('checking ownership of %(dbfile)s')
user = mm_cfg.MAILMAN_USER
ownerok = stat[ST_UID] == pwd.getpwnam(user)[2]
if not ownerok:
@@ -350,10 +350,10 @@ def checkperms(state):
owner = pwd.getpwuid(stat[ST_UID])[0]
except KeyError:
owner = 'uid %d' % stat[ST_UID]
- print _('%(dbfile)s owned by %(owner)s (must be owned by %(user)s'),
+ print C_('%(dbfile)s owned by %(owner)s (must be owned by %(user)s'),
state.ERRORS += 1
if state.FIX:
- print _('(fixing)')
+ print C_('(fixing)')
uid = pwd.getpwnam(user)[2]
gid = grp.getgrnam(mm_cfg.MAILMAN_GROUP)[2]
os.chown(dbfile, uid, gid)
diff --git a/Mailman/i18n.py b/Mailman/i18n.py
index 5f926b7..be85e3b 100644
--- a/Mailman/i18n.py
+++ b/Mailman/i18n.py
@@ -15,6 +15,7 @@
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
# USA.
+import locale
import sys
import time
import gettext
@@ -26,6 +27,16 @@ from Mailman.SafeDict import SafeDict
_translation = None
+def _get_ctype_charset():
+ old = locale.setlocale(locale.LC_CTYPE, '')
+ charset = locale.nl_langinfo(locale.CODESET)
+ locale.setlocale(locale.LC_CTYPE, old)
+ return charset
+
+_ctype_charset = _get_ctype_charset()
+
+
+
def set_language(language=None):
global _translation
@@ -54,7 +65,7 @@ if _translation is None:
-def _(s):
+def _(s, frame = 1):
if s == '':
return s
assert s
@@ -70,7 +81,7 @@ def _(s):
# original string is 1) locals dictionary, 2) globals dictionary.
#
# First, get the frame of the caller
- frame = sys._getframe(1)
+ frame = sys._getframe(frame)
# A `safe' dictionary is used so we won't get an exception if there's a
# missing key in the dictionary.
dict = SafeDict(frame.f_globals.copy())
@@ -93,6 +104,17 @@ def _(s):
# Bad interpolation format. Punt.
return tns
+def tolocale(s):
+ global _ctype_charset
+ if isinstance(s, UnicodeType):
+ return s
+ source = _translation.charset ()
+ if not source:
+ return s
+ return unicode(s, source, 'replace').encode(_ctype_charset, 'replace')
+
+def C_(s):
+ return tolocale(_(s, 2))
def ctime(date):
diff --git a/bin/add_members b/bin/add_members
index 03f0af3..056e320 100755
--- a/bin/add_members
+++ b/bin/add_members
@@ -80,7 +80,7 @@ from Mailman import Errors
from Mailman import mm_cfg
from Mailman import i18n
-_ = i18n._
+C_ = i18n.C_
@@ -89,7 +89,7 @@ def usage(status, msg=''):
fd = sys.stderr
else:
fd = sys.stdout
- print >> fd, _(__doc__)
+ print >> fd, C_(__doc__)
if msg:
print >> fd, msg
sys.exit(status)
@@ -134,19 +134,19 @@ def addall(mlist, members, digest, ack, outfp):
try:
mlist.ApprovedAddMember(userdesc, ack, 0)
except Errors.MMAlreadyAMember:
- print >> tee, _('Already a member: %(member)s')
+ print >> tee, C_('Already a member: %(member)s')
except Errors.MembershipIsBanned, pattern:
print >> tee, ('%s:' %
- member), _('Banned address (matched %(pattern)s)')
+ member), C_('Banned address (matched %(pattern)s)')
except Errors.MMBadEmailError:
if userdesc.address == '':
- print >> tee, _('Bad/Invalid email address: blank line')
+ print >> tee, C_('Bad/Invalid email address: blank line')
else:
- print >> tee, _('Bad/Invalid email address: %(member)s')
+ print >> tee, C_('Bad/Invalid email address: %(member)s')
except Errors.MMHostileAddress:
- print >> tee, _('Hostile address (illegal characters): %(member)s')
+ print >> tee, C_('Hostile address (illegal characters): %(member)s')
else:
- print >> tee, _('Subscribed: %(member)s')
+ print >> tee, C_('Subscribed: %(member)s')
@@ -191,26 +191,26 @@ def main():
elif arg.lower()[0] == 'n':
send_welcome_msg = 0
else:
- usage(1, _('Bad argument to -w/--welcome-msg: %(arg)s'))
+ usage(1, C_('Bad argument to -w/--welcome-msg: %(arg)s'))
elif opt in ('-a', '--admin-notify'):
if arg.lower()[0] == 'y':
admin_notif = 1
elif arg.lower()[0] == 'n':
admin_notif = 0
else:
- usage(1, _('Bad argument to -a/--admin-notify: %(arg)s'))
+ usage(1, C_('Bad argument to -a/--admin-notify: %(arg)s'))
if dfile is None and nfile is None:
usage(1)
if dfile == "-" and nfile == "-":
- usage(1, _('Cannot read both digest and normal members '
+ usage(1, C_('Cannot read both digest and normal members '
'from standard input.'))
try:
mlist = MailList.MailList(listname)
except Errors.MMUnknownListError:
- usage(1, _('No such list: %(listname)s'))
+ usage(1, C_('No such list: %(listname)s'))
# Set up defaults
if send_welcome_msg is None:
@@ -230,7 +230,7 @@ def main():
nmembers = readfile(nfile)
if not dmembers and not nmembers:
- usage(0, _('Nothing to do.'))
+ usage(0, C_('Nothing to do.'))
s = StringIO()
i18n.set_language(mlist.preferred_language)
@@ -242,7 +242,7 @@ def main():
if admin_notif:
realname = mlist.real_name
- subject = _('%(realname)s subscription notification')
+ subject = C_('%(realname)s subscription notification')
msg = Message.UserNotification(
mlist.owner, Utils.get_site_email(), subject, s.getvalue(),
mlist.preferred_language)
diff --git a/bin/arch b/bin/arch
index a98ae2a..8fdca6a 100644
--- a/bin/arch
+++ b/bin/arch
@@ -70,7 +70,7 @@ from Mailman.Archiver.HyperArch import HyperArchive
from Mailman.LockFile import LockFile
from Mailman import i18n
-_ = i18n._
+C_ = i18n.C_
PROGRAM = sys.argv[0]
i18n.set_language(mm_cfg.DEFAULT_SERVER_LANGUAGE)
@@ -82,7 +82,7 @@ def usage(code, msg=''):
fd = sys.stderr
else:
fd = sys.stdout
- print >> fd, _(__doc__)
+ print >> fd, C_(__doc__)
if msg:
print >> fd, msg
sys.exit(code)
@@ -122,7 +122,7 @@ def main():
# grok arguments
if len(args) < 1:
- usage(1, _('listname is required'))
+ usage(1, C_('listname is required'))
listname = args[0].lower().strip()
if len(args) < 2:
@@ -140,7 +140,7 @@ def main():
try:
mlist = MailList(listname)
except Errors.MMListError, e:
- usage(2, _('No such list "%(listname)s"\n%(e)s'))
+ usage(2, C_('No such list "%(listname)s"\n%(e)s'))
if mbox is None:
mbox = mlist.ArchiveFileName()
@@ -165,7 +165,7 @@ def main():
try:
fp = open(mbox)
except IOError, msg:
- usage(3, _('Cannot open mbox file %(mbox)s: %(msg)s'))
+ usage(3, C_('Cannot open mbox file %(mbox)s: %(msg)s'))
# Maybe wipe the old archives
if wipe:
if mlist.scrub_nondigest:
diff --git a/bin/b4b5-archfix b/bin/b4b5-archfix
index 1bdaeda..22d8839 100644
--- a/bin/b4b5-archfix
+++ b/bin/b4b5-archfix
@@ -44,7 +44,7 @@ import cPickle as pickle
# Required to get the right classes for unpickling
import paths
-from Mailman.i18n import _
+from Mailman.i18n import C_
PROGRAM = sys.argv[0]
@@ -55,7 +55,7 @@ def usage(code, msg=''):
fd = sys.stderr
else:
fd = sys.stdout
- print >> fd, _(__doc__)
+ print >> fd, C_(__doc__)
if msg:
print >> fd, msg
sys.exit(code)
diff --git a/bin/change_pw b/bin/change_pw
index 6adabcd..c008a6d 100644
--- a/bin/change_pw
+++ b/bin/change_pw
@@ -76,7 +76,7 @@ from Mailman import Errors
from Mailman import Message
from Mailman import i18n
-_ = i18n._
+C_ = i18n.C_
SPACE = ' '
@@ -87,7 +87,7 @@ def usage(code, msg=''):
fd = sys.stderr
else:
fd = sys.stdout
- print >> fd, _(__doc__)
+ print >> fd, C_(__doc__)
if msg:
print >> fd, msg
sys.exit(code)
@@ -103,7 +103,7 @@ def openlist(listname):
try:
mlist = MailList.MailList(listname, lock=0)
except Errors.MMListError, e:
- usage(1, _('No such list "%(listname)s"\n%(e)s'))
+ usage(1, C_('No such list "%(listname)s"\n%(e)s'))
_listcache[listname] = mlist
return mlist
@@ -141,11 +141,11 @@ def main():
if args:
strargs = SPACE.join(args)
- usage(1, _('Bad arguments: %(strargs)s'))
+ usage(1, C_('Bad arguments: %(strargs)s'))
if password is not None:
if not password:
- usage(1, _('Empty list passwords are not allowed'))
+ usage(1, C_('Empty list passwords are not allowed'))
shapassword = Utils.sha_new(password).hexdigest()
if domains:
@@ -155,7 +155,7 @@ def main():
listnames[name] = 1
if not listnames:
- print >> sys.stderr, _('Nothing to do.')
+ print >> sys.stderr, C_('Nothing to do.')
sys.exit(0)
# Set the password on the lists
@@ -177,7 +177,7 @@ def main():
mlist.Unlock()
# Notification
- print _('New %(listname)s password: %(notifypassword)s')
+ print C_('New %(listname)s password: %(notifypassword)s')
if not quiet:
otrans = i18n.get_translation()
i18n.set_language(mlist.preferred_language)
diff --git a/bin/check_db b/bin/check_db
index b1157bc..40fa0a2 100755
--- a/bin/check_db
+++ b/bin/check_db
@@ -59,7 +59,7 @@ import paths
from Mailman import mm_cfg
from Mailman import Utils
from Mailman.MailList import MailList
-from Mailman.i18n import _
+from Mailman.i18n import C_
PROGRAM = sys.argv[0]
@@ -70,7 +70,7 @@ def usage(code, msg=''):
fd = sys.stderr
else:
fd = sys.stdout
- print >> fd, _(__doc__)
+ print >> fd, C_(__doc__)
if msg:
print >> fd, msg
sys.exit(code)
@@ -111,12 +111,12 @@ def main():
listnames = [n.lower().strip() for n in listnames]
if not listnames:
- print _('Nothing to do.')
+ print C_('Nothing to do.')
sys.exit(0)
for listname in listnames:
if not Utils.list_exists(listname):
- print _('No list named:'), listname
+ print C_('No list named:'), listname
continue
mlist = MailList(listname, lock=0)
pfile = os.path.join(mlist.fullpath(), 'config.pck')
@@ -125,7 +125,7 @@ def main():
dlast = dfile + '.last'
if verbose:
- print _('List:'), listname
+ print C_('List:'), listname
for file in (pfile, plast, dfile, dlast):
status = 0
@@ -145,7 +145,7 @@ def main():
else:
print ' %s: %s' % (file, status)
elif verbose:
- print _(' %(file)s: okay')
+ print C_(' %(file)s: okay')
diff --git a/bin/check_perms b/bin/check_perms
index eb80b2d..0d77672 100755
--- a/bin/check_perms
+++ b/bin/check_perms
@@ -45,7 +45,7 @@ directory. You must run this from the installation directory instead.
raise
from Mailman import mm_cfg
from Mailman.mm_cfg import MAILMAN_USER, MAILMAN_GROUP
-from Mailman.i18n import _
+from Mailman.i18n import C_
# Let KeyErrors percolate
MAILMAN_GID = grp.getgrnam(MAILMAN_GROUP)[2]
@@ -107,7 +107,7 @@ def checkwalk(arg, dirname, names):
for name in names:
path = os.path.join(dirname, name)
if arg.VERBOSE:
- print _(' checking gid and mode for %(path)s')
+ print C_(' checking gid and mode for %(path)s')
try:
mode, gid = statgidmode(path)
except OSError, e:
@@ -119,10 +119,10 @@ def checkwalk(arg, dirname, names):
except KeyError:
groupname = '<anon gid %d>' % gid
arg.ERRORS += 1
- print _('%(path)s bad group (has: %(groupname)s, '
+ print C_('%(path)s bad group (has: %(groupname)s, '
'expected %(MAILMAN_GROUP)s)'),
if STATE.FIX:
- print _('(fixing)')
+ print C_('(fixing)')
os.chown(path, -1, MAILMAN_GID)
else:
print
@@ -148,19 +148,19 @@ def checkwalk(arg, dirname, names):
octperms = oct(targetperms)
if S_ISDIR(mode) and (mode & targetperms) <> targetperms:
arg.ERRORS += 1
- print _('directory permissions must be %(octperms)s: %(path)s'),
+ print C_('directory permissions must be %(octperms)s: %(path)s'),
if STATE.FIX:
- print _('(fixing)')
+ print C_('(fixing)')
os.chmod(path, mode | targetperms)
else:
print
elif os.path.splitext(path)[1] in ('.py', '.pyc', '.pyo'):
octperms = oct(PYFILEPERMS)
if mode & PYFILEPERMS <> PYFILEPERMS:
- print _('source perms must be %(octperms)s: %(path)s'),
+ print C_('source perms must be %(octperms)s: %(path)s'),
arg.ERRORS += 1
if STATE.FIX:
- print _('(fixing)')
+ print C_('(fixing)')
os.chmod(path, mode | PYFILEPERMS)
else:
print
@@ -168,10 +168,10 @@ def checkwalk(arg, dirname, names):
# Article files must be group writeable
octperms = oct(ARTICLEFILEPERMS)
if mode & ARTICLEFILEPERMS <> ARTICLEFILEPERMS:
- print _('article db files must be %(octperms)s: %(path)s'),
+ print C_('article db files must be %(octperms)s: %(path)s'),
arg.ERRORS += 1
if STATE.FIX:
- print _('(fixing)')
+ print C_('(fixing)')
os.chmod(path, mode | ARTICLEFILEPERMS)
else:
print
@@ -180,7 +180,7 @@ def checkall():
# first check PREFIX
if STATE.VERBOSE:
prefix = mm_cfg.PREFIX
- print _('checking mode for %(prefix)s')
+ print C_('checking mode for %(prefix)s')
dirs = {}
for d in (mm_cfg.PREFIX, mm_cfg.EXEC_PREFIX, mm_cfg.VAR_PREFIX,
mm_cfg.CONFIG_DIR, mm_cfg.DATA_DIR, mm_cfg.LOCK_DIR,
@@ -191,13 +191,13 @@ def checkall():
mode = statmode(d)
except OSError, e:
if e.errno <> errno.ENOENT: raise
- print _('WARNING: directory does not exist: %(d)s')
+ print C_('WARNING: directory does not exist: %(d)s')
continue
if (mode & DIRPERMS) <> DIRPERMS:
STATE.ERRORS += 1
- print _('directory must be at least 02775: %(d)s'),
+ print C_('directory must be at least 02775: %(d)s'),
if STATE.FIX:
- print _('(fixing)')
+ print C_('(fixing)')
os.chmod(d, mode | DIRPERMS)
else:
print
@@ -207,14 +207,14 @@ def checkall():
def checkarchives():
private = mm_cfg.PRIVATE_ARCHIVE_FILE_DIR
if STATE.VERBOSE:
- print _('checking perms on %(private)s')
+ print C_('checking perms on %(private)s')
# private archives must not be other readable
mode = statmode(private)
if mode & S_IROTH:
STATE.ERRORS += 1
- print _('%(private)s must not be other-readable'),
+ print C_('%(private)s must not be other-readable'),
if STATE.FIX:
- print _('(fixing)')
+ print C_('(fixing)')
os.chmod(private, mode & ~S_IROTH)
else:
print
@@ -238,9 +238,9 @@ def checkmboxfile(mboxdir):
mode = statmode(mboxfile)
if (mode & MBOXPERMS) <> MBOXPERMS:
STATE.ERRORS = STATE.ERRORS + 1
- print _('mbox file must be at least 0660:'), mboxfile
+ print C_('mbox file must be at least 0660:'), mboxfile
if STATE.FIX:
- print _('(fixing)')
+ print C_('(fixing)')
os.chmod(mboxfile, mode | MBOXPERMS)
else:
print
@@ -261,9 +261,9 @@ def checkarchivedbs():
continue
if mode & S_IRWXO:
STATE.ERRORS += 1
- print _('%(dbdir)s "other" perms must be 000'),
+ print C_('%(dbdir)s "other" perms must be 000'),
if STATE.FIX:
- print _('(fixing)')
+ print C_('(fixing)')
os.chmod(dbdir, mode & ~S_IRWXO)
else:
print
@@ -271,18 +271,18 @@ def checkarchivedbs():
def checkcgi():
cgidir = os.path.join(mm_cfg.EXEC_PREFIX, 'cgi-bin')
if STATE.VERBOSE:
- print _('checking cgi-bin permissions')
+ print C_('checking cgi-bin permissions')
exes = os.listdir(cgidir)
for f in exes:
path = os.path.join(cgidir, f)
if STATE.VERBOSE:
- print _(' checking set-gid for %(path)s')
+ print C_(' checking set-gid for %(path)s')
mode = statmode(path)
if mode & S_IXGRP and not mode & S_ISGID:
STATE.ERRORS += 1
- print _('%(path)s must be set-gid'),
+ print C_('%(path)s must be set-gid'),
if STATE.FIX:
- print _('(fixing)')
+ print C_('(fixing)')
os.chmod(path, mode | S_ISGID)
else:
print
@@ -290,13 +290,13 @@ def checkcgi():
def checkmail():
wrapper = os.path.join(mm_cfg.WRAPPER_DIR, 'mailman')
if STATE.VERBOSE:
- print _('checking set-gid for %(wrapper)s')
+ print C_('checking set-gid for %(wrapper)s')
mode = statmode(wrapper)
if not mode & S_ISGID:
STATE.ERRORS += 1
- print _('%(wrapper)s must be set-gid'),
+ print C_('%(wrapper)s must be set-gid'),
if STATE.FIX:
- print _('(fixing)')
+ print C_('(fixing)')
os.chmod(wrapper, mode | S_ISGID)
def checkadminpw():
@@ -304,7 +304,7 @@ def checkadminpw():
os.path.join(mm_cfg.DATA_DIR, 'creator.pw')):
targetmode = S_IFREG | S_IRUSR | S_IWUSR | S_IRGRP
if STATE.VERBOSE:
- print _('checking permissions on %(pwfile)s')
+ print C_('checking permissions on %(pwfile)s')
try:
mode = statmode(pwfile)
except OSError, e:
@@ -313,10 +313,10 @@ def checkadminpw():
if mode <> targetmode:
STATE.ERRORS += 1
octmode = oct(mode)
- print _('%(pwfile)s permissions must be exactly 0640 '
+ print C_('%(pwfile)s permissions must be exactly 0640 '
'(got %(octmode)s)'),
if STATE.FIX:
- print _('(fixing)')
+ print C_('(fixing)')
os.chmod(pwfile, targetmode)
else:
print
@@ -338,7 +338,7 @@ def checkdata():
'digest.mbox', 'pending.pck',
'request.db', 'request.db.tmp')
if STATE.VERBOSE:
- print _('checking permissions on list data')
+ print C_('checking permissions on list data')
# BAW: This needs to be converted to the Site module abstraction
for dir in os.listdir(mm_cfg.LIST_DATA_DIR):
if not os.path.isdir(os.path.join(mm_cfg.LIST_DATA_DIR, dir)):
@@ -346,7 +346,7 @@ def checkdata():
for file in checkfiles:
path = os.path.join(mm_cfg.LIST_DATA_DIR, dir, file)
if STATE.VERBOSE:
- print _(' checking permissions on: %(path)s')
+ print C_(' checking permissions on: %(path)s')
try:
mode = statmode(path)
except OSError, e:
@@ -354,9 +354,9 @@ def checkdata():
continue
if (mode & targetmode) <> targetmode:
STATE.ERRORS += 1
- print _('file permissions must be at least 660: %(path)s'),
+ print C_('file permissions must be at least 660: %(path)s'),
if STATE.FIX:
- print _('(fixing)')
+ print C_('(fixing)')
os.chmod(path, mode | targetmode)
else:
print
@@ -368,7 +368,7 @@ def usage(code, msg=''):
fd = sys.stderr
else:
fd = sys.stdout
- print >> fd, _(__doc__)
+ print >> fd, C_(__doc__)
if msg:
print >> fd, msg
sys.exit(code)
@@ -399,7 +399,7 @@ if __name__ == '__main__':
checkmta()
if not STATE.ERRORS:
- print _('No problems found')
+ print C_('No problems found')
else:
- print _('Problems found:'), STATE.ERRORS
- print _('Re-run as %(MAILMAN_USER)s (or root) with -f flag to fix')
+ print C_('Problems found:'), STATE.ERRORS
+ print C_('Re-run as %(MAILMAN_USER)s (or root) with -f flag to fix')