Blob Blame History Raw
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')