Index: /pykota/trunk/pykota/dumper.py
===================================================================
--- /pykota/trunk/pykota/dumper.py (revision 3291)
+++ /pykota/trunk/pykota/dumper.py (revision 3295)
@@ -39,6 +39,8 @@
     hasJAXML = True
 
+from pykota.utils import *
+
 from pykota import version
-from pykota.tool import PyKotaTool, N_
+from pykota.tool import PyKotaTool
 from pykota.errors import PyKotaToolError, PyKotaCommandLineError
 
Index: /pykota/trunk/pykota/utils.py
===================================================================
--- /pykota/trunk/pykota/utils.py (revision 3294)
+++ /pykota/trunk/pykota/utils.py (revision 3295)
@@ -23,4 +23,5 @@
 
 import sys
+import os
 import locale
 import gettext
@@ -63,4 +64,24 @@
     except :
         gettext.NullTranslations().install(unicode=True)
+        
+def getpreferredlanguage() :
+    """Returns the preferred language."""
+    languages = os.environ.get("HTTP_ACCEPT_LANGUAGE", "")
+    langs = [l.strip().split(';')[0] for l in languages.split(",")]
+    return langs[0].replace("-", "_")
+    
+def getpreferredcharset() :
+    """Returns the preferred charset."""
+    charsets = os.environ.get("HTTP_ACCEPT_CHARSET", "UTF-8")
+    charsets = [l.strip().split(';')[0] for l in charsets.split(",")]
+    return charsets[0]
+
+def reinitcgilocale() :        
+    """Reinitializes the locale and gettext translations for CGI scripts, according to browser's preferences."""
+    initgettext(*initlocale(getpreferredlanguage(), getpreferredcharset()))
+    
+def N_(message) :
+    """Fake translation marker for translatable strings extraction."""
+    return message
 
 def databaseToUnicode(text) :
@@ -80,4 +101,16 @@
 def logerr(text) :
     """Logs an unicode text to stderr."""
-    sys.stderr.write(text.encode(sys.stdout.encoding, "replace"))
+    sys.stderr.write(text.encode(sys.stdout.encoding or locale.getlocale()[1], \
+                                 "replace"))
+    sys.stderr.flush()
             
+def crashed(message="Bug in PyKota") :    
+    """Minimal crash method."""
+    import traceback
+    from pykota.version import __version__
+    lines = []
+    for line in traceback.format_exception(*sys.exc_info()) :
+        lines.extend([l for l in line.split("\n") if l])
+    msg = "ERROR: ".join(["%s\n" % l for l in (["ERROR: PyKota v%s" % __version__, message] + lines)])
+    logerr(msg)
+    return msg
Index: /pykota/trunk/pykota/tool.py
===================================================================
--- /pykota/trunk/pykota/tool.py (revision 3294)
+++ /pykota/trunk/pykota/tool.py (revision 3295)
@@ -38,22 +38,8 @@
 from mx import DateTime
 
+from pykota import utils
 from pykota.errors import PyKotaCommandLineError
 from pykota import config, storage, logger
 from pykota.version import __version__, __author__, __years__, __gplblurb__
-
-def N_(message) :
-    """Fake translation marker for translatable strings extraction."""
-    return message
-
-def crashed(message="Bug in PyKota") :    
-    """Minimal crash method."""
-    import traceback
-    lines = []
-    for line in traceback.format_exception(*sys.exc_info()) :
-        lines.extend([l for l in line.split("\n") if l])
-    msg = "ERROR: ".join(["%s\n" % l for l in (["ERROR: PyKota v%s" % __version__, message] + lines)])
-    sys.stderr.write(msg)
-    sys.stderr.flush()
-    return msg
 
 class Percent :
@@ -103,5 +89,5 @@
 class Tool :
     """Base class for tools with no database access."""
-    def __init__(self, lang="", charset=None, doc="PyKota v%(__version__)s (c) %(__years__)s %(__author__)s") :
+    def __init__(self, doc="PyKota v%(__version__)s (c) %(__years__)s %(__author__)s") :
         """Initializes the command line tool."""
         self.debug = True # in case of early failure
@@ -110,4 +96,6 @@
         # Saves a copy of the locale settings
         (self.language, self.charset) = locale.getlocale()
+        if not self.charset :
+            self.charset = "UTF-8"
         
         # pykota specific stuff
@@ -247,5 +235,5 @@
     def crashed(self, message="Bug in PyKota") :    
         """Outputs a crash message, and optionally sends it to software author."""
-        msg = crashed(message)
+        msg = utils.crashed(message)
         fullmessage = "========== Traceback :\n\n%s\n\n========== sys.argv :\n\n%s\n\n========== Environment :\n\n%s\n" % \
                         (msg, \
@@ -347,8 +335,4 @@
 class PyKotaTool(Tool) :    
     """Base class for all PyKota command line tools."""
-    def __init__(self, lang="", charset=None, doc="PyKota v%(__version__)s (c) %(__years__)s %(__author__)s") :
-        """Initializes the command line tool and opens the database."""
-        Tool.__init__(self, lang, charset, doc)
-        
     def deferredInit(self) :    
         """Deferred initialization."""
Index: /kota/trunk/pykota/cgifuncs.py
===================================================================
--- /pykota/trunk/pykota/cgifuncs.py (revision 3275)
+++  (revision )
@@ -1,40 +1,0 @@
-# -*- coding: UTF-8 -*-
-#
-# PyKota : Print Quotas for CUPS
-#
-# (c) 2003, 2004, 2005, 2006, 2007, 2008 Jerome Alet <alet@librelogiciel.com>
-# This program 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.
-# 
-# This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.
-#
-# $Id$
-#
-#
-
-"""This module defines some helper functions to use in CGI scripts."""
-
-import sys
-import os
-
-def getLanguagePreference() :
-    """Returns the preferred language."""
-    languages = os.environ.get("HTTP_ACCEPT_LANGUAGE", "")
-    langs = [l.strip().split(';')[0] for l in languages.split(",")]
-    #sys.stderr.write("Languages preferences : %s\n" % langs)
-    return langs[0].replace("-", "_")
-    
-def getCharsetPreference() :
-    """Returns the preferred charset."""
-    charsets = os.environ.get("HTTP_ACCEPT_CHARSET", "UTF-8")
-    charsets = [l.strip().split(';')[0] for l in charsets.split(",")]
-    #sys.stderr.write("Charsets preferences : %s\n" % charsets)
-    return charsets[0]
Index: /pykota/trunk/cgi-bin/printquota.cgi
===================================================================
--- /pykota/trunk/cgi-bin/printquota.cgi (revision 3275)
+++ /pykota/trunk/cgi-bin/printquota.cgi (revision 3295)
@@ -31,8 +31,10 @@
 from mx import DateTime
 
-from pykota import version
-from pykota.tool import PyKotaTool, PyKotaToolError
-from pykota.reporter import PyKotaReporterError, openReporter
-from pykota.cgifuncs import getLanguagePreference, getCharsetPreference
+import pykota.appinit
+
+from pykota import version, utils
+from pykota.tool import PyKotaTool
+from pykota.errors import PyKotaToolError, PyKotaReporterError
+from pykota.reporter import openReporter
 
 header = """Content-type: text/html;charset=%s
@@ -44,5 +46,4 @@
   </head>
   <body>
-    <!-- %s %s -->
     <p>
       <form action="printquota.cgi" method="POST">
@@ -96,13 +97,15 @@
         """Displays the administrative interface."""
         global header, footer
-        print header % (self.charset, _("PyKota Reports"), \
-                        self.language, self.charset, \
-                        self.config.getLogoLink(), \
-                        self.config.getLogoURL(), version.__version__, \
-                        self.config.getLogoLink(), \
-                        version.__version__, _("PyKota Reports"), \
-                        _("Report"))
-        print self.body
-        print footer % (_("Report"), version.__doc__, version.__years__, version.__author__, version.__gplblurb__)
+        content = [ header % (self.charset, _("PyKota Reports"), \
+                              self.config.getLogoLink(), \
+                              self.config.getLogoURL(), version.__version__, \
+                              self.config.getLogoLink(), \
+                              version.__version__, _("PyKota Reports"), \
+                              _("Report")) ]
+        content.append(self.body)                      
+        content.append(footer % (_("Report"), version.__doc__, version.__years__, version.__author__, version.__gplblurb__))
+        for c in content :
+            sys.stdout.write(c.encode(self.charset, "replace"))
+        sys.stdout.flush()
         
     def error(self, message) :
@@ -287,5 +290,6 @@
             
 if __name__ == "__main__" :
-    admin = PyKotaReportGUI(lang=getLanguagePreference(), charset=getCharsetPreference())
+    utils.reinitcgilocale()
+    admin = PyKotaReportGUI()
     admin.deferredInit()
     admin.form = cgi.FieldStorage()
Index: /pykota/trunk/cgi-bin/pykotme.cgi
===================================================================
--- /pykota/trunk/cgi-bin/pykotme.cgi (revision 3275)
+++ /pykota/trunk/cgi-bin/pykotme.cgi (revision 3295)
@@ -30,7 +30,10 @@
 import cStringIO
 
-from pykota import version
-from pykota.tool import PyKotaTool, PyKotaToolError
-from pykota.cgifuncs import getLanguagePreference, getCharsetPreference
+import pykota.appinit
+
+from pykota import version, utils
+from pykota.tool import PyKotaTool
+from pykota.errors import PyKotaToolError
+
 from pkpgpdls import analyzer, pdlparser
     
@@ -44,5 +47,4 @@
   </head>
   <body>
-    <!-- %s %s -->
     <p>
       <form action="pykotme.cgi" method="POST" enctype="multipart/form-data">
@@ -96,13 +98,15 @@
         """Displays the administrative interface."""
         global header, footer
-        print header % (self.charset, _("PyKota Quotes"), \
-                        self.language, self.charset, \
+        content = [ header % (self.charset, _("PyKota Quotes"), \
                         self.config.getLogoLink(), \
                         self.config.getLogoURL(), version.__version__, \
                         self.config.getLogoLink(), \
                         version.__version__, _("PyKota Quotes"), \
-                        _("Quote"))
-        print self.body
-        print footer % (_("Quote"), version.__doc__, version.__years__, version.__author__, version.__gplblurb__)
+                        _("Quote")) ]
+        content.append(self.body)
+        content.append(footer % (_("Quote"), version.__doc__, version.__years__, version.__author__, version.__gplblurb__))
+        for c in content :
+            sys.stdout.write(c.encode(self.charset, "replace"))
+        sys.stdout.flush()
         
     def error(self, message) :
@@ -187,5 +191,6 @@
             
 if __name__ == "__main__" :
-    admin = PyKotMeGUI(lang=getLanguagePreference(), charset=getCharsetPreference())
+    utils.reinitcgilocale()
+    admin = PyKotMeGUI()
     admin.deferredInit()
     admin.form = cgi.FieldStorage()
Index: /pykota/trunk/cgi-bin/dumpykota.cgi
===================================================================
--- /pykota/trunk/cgi-bin/dumpykota.cgi (revision 3275)
+++ /pykota/trunk/cgi-bin/dumpykota.cgi (revision 3295)
@@ -29,8 +29,7 @@
 import urllib
 
-from pykota import version
-from pykota.tool import PyKotaToolError
+import pykota.appinit
+from pykota import version, utils
 from pykota.dumper import DumPyKota
-from pykota.cgifuncs import getLanguagePreference, getCharsetPreference
 
 header = """Content-type: text/html;charset=%s
@@ -68,5 +67,4 @@
   </head>
   <body>
-    <!-- %s %s -->
     <p>
       <form action="dumpykota.cgi" method="GET" name="mainform" onsubmit="return checkvalues()">
@@ -123,21 +121,23 @@
         """Displays the dumper interface."""
         global header, footer
-        print header % (self.charset, _("PyKota Data Dumper"), \
-                        self.language, self.charset, \
+        content = [ header % (self.charset, _("PyKota Data Dumper"), \
                         self.config.getLogoLink(), \
                         self.config.getLogoURL(), version.__version__, \
                         self.config.getLogoLink(), \
                         version.__version__, _("PyKota Data Dumper"), \
-                        _("Dump"), _("Please click on the above button"))
-        print self.htmlListDataTypes(self.options.get("data", "")) 
-        print "<br />"
-        print self.htmlListFormats(self.options.get("format", ""))
-        print "<br />"
-        print self.htmlFilterInput(" ".join(self.arguments))
-        print "<br />"
-        print self.htmlOrderbyInput(self.options.get("orderby", ""))
-        print "<br />"
-        print self.htmlSumCheckbox(self.options.get("sum", ""))
-        print footer % (_("Dump"), version.__doc__, version.__years__, version.__author__, version.__gplblurb__)
+                        _("Dump"), _("Please click on the above button")) ]
+        content.append(self.htmlListDataTypes(self.options.get("data", "")))
+        content.append(u"<br />")
+        content.append(self.htmlListFormats(self.options.get("format", "")))
+        content.append(u"<br />")
+        content.append(self.htmlFilterInput(" ".join(self.arguments)))
+        content.append(u"<br />")
+        content.append(self.htmlOrderbyInput(self.options.get("orderby", "")))
+        content.append(u"<br />")
+        content.append(self.htmlSumCheckbox(self.options.get("sum", "")))
+        content.append(footer % (_("Dump"), version.__doc__, version.__years__, version.__author__, version.__gplblurb__))
+        for c in content :
+            sys.stdout.write(c.encode(self.charset, "replace"))
+        sys.stdout.flush()
         
     def htmlListDataTypes(self, selected="") :    
@@ -236,5 +236,6 @@
             
 if __name__ == "__main__" :
-    admin = PyKotaDumperGUI(lang=getLanguagePreference(), charset=getCharsetPreference())
+    utils.reinitcgilocale()
+    admin = PyKotaDumperGUI()
     admin.deferredInit()
     admin.form = cgi.FieldStorage()
Index: /pykota/trunk/bin/edpykota
===================================================================
--- /pykota/trunk/bin/edpykota (revision 3294)
+++ /pykota/trunk/bin/edpykota (revision 3295)
@@ -28,5 +28,5 @@
 
 from pykota.errors import PyKotaCommandLineError
-from pykota.tool import Percent, PyKotaTool, crashed, N_
+from pykota.tool import Percent, PyKotaTool
 from pykota.storage import StorageUserPQuota, StorageGroupPQuota
 
Index: /pykota/trunk/bin/pkinvoice
===================================================================
--- /pykota/trunk/bin/pkinvoice (revision 3294)
+++ /pykota/trunk/bin/pkinvoice (revision 3295)
@@ -48,5 +48,5 @@
 
 from pykota.errors import PyKotaToolError, PyKotaCommandLineError
-from pykota.tool import Percent, PyKotaTool, crashed, N_
+from pykota.tool import Percent, PyKotaTool
 
 __doc__ = N_("""pkinvoice v%(__version__)s (c) %(__years__)s %(__author__)s
Index: /pykota/trunk/bin/pykotme
===================================================================
--- /pykota/trunk/bin/pykotme (revision 3294)
+++ /pykota/trunk/bin/pykotme (revision 3295)
@@ -30,5 +30,5 @@
 
 from pykota.errors import PyKotaCommandLineError
-from pykota.tool import PyKotaTool, crashed, N_
+from pykota.tool import PyKotaTool
 from pykota.accounter import openAccounter
     
Index: /pykota/trunk/bin/pkbcodes
===================================================================
--- /pykota/trunk/bin/pkbcodes (revision 3294)
+++ /pykota/trunk/bin/pkbcodes (revision 3295)
@@ -30,5 +30,5 @@
 
 from pykota.errors import PyKotaCommandLineError
-from pykota.tool import Percent, PyKotaTool, crashed, N_
+from pykota.tool import Percent, PyKotaTool
 from pykota.storage import StorageBillingCode
 
Index: /pykota/trunk/bin/pkturnkey
===================================================================
--- /pykota/trunk/bin/pkturnkey (revision 3294)
+++ /pykota/trunk/bin/pkturnkey (revision 3295)
@@ -33,5 +33,5 @@
 
 from pykota.errors import PyKotaToolError, PyKotaCommandLineError
-from pykota.tool import Tool, crashed, N_
+from pykota.tool import Tool
 
 __doc__ = N_("""pkturnkey v%(__version__)s (c) %(__years__)s %(__author__)s
Index: /pykota/trunk/bin/pkusers
===================================================================
--- /pykota/trunk/bin/pkusers (revision 3294)
+++ /pykota/trunk/bin/pkusers (revision 3295)
@@ -30,5 +30,5 @@
 
 from pykota.errors import PyKotaCommandLineError
-from pykota.tool import Percent, PyKotaTool, crashed, N_
+from pykota.tool import Percent, PyKotaTool
 from pykota.storage import StorageUser, StorageGroup
 
Index: /pykota/trunk/bin/repykota
===================================================================
--- /pykota/trunk/bin/repykota (revision 3294)
+++ /pykota/trunk/bin/repykota (revision 3295)
@@ -32,5 +32,5 @@
 
 from pykota.errors import PyKotaToolError, PyKotaCommandLineError
-from pykota.tool import PyKotaTool, crashed, N_
+from pykota.tool import PyKotaTool
 from pykota import reporter
 
Index: /pykota/trunk/bin/warnpykota
===================================================================
--- /pykota/trunk/bin/warnpykota (revision 3294)
+++ /pykota/trunk/bin/warnpykota (revision 3295)
@@ -30,5 +30,5 @@
 
 from pykota.errors import PyKotaCommandLineError
-from pykota.tool import PyKotaTool, crashed, N_
+from pykota.tool import PyKotaTool
 
 __doc__ = N_("""warnpykota v%(__version__)s (c) %(__years__)s %(__author__)s
Index: /pykota/trunk/bin/pkbanner
===================================================================
--- /pykota/trunk/bin/pkbanner (revision 3294)
+++ /pykota/trunk/bin/pkbanner (revision 3295)
@@ -48,5 +48,5 @@
 
 from pykota.errors import PyKotaToolError, PyKotaCommandLineError
-from pykota.tool import Tool, crashed, N_
+from pykota.tool import Tool
 
 __doc__ = N_("""pkbanner v%(__version__)s (c) %(__years__)s %(__author__)s
Index: /pykota/trunk/bin/autopykota
===================================================================
--- /pykota/trunk/bin/autopykota (revision 3294)
+++ /pykota/trunk/bin/autopykota (revision 3295)
@@ -30,5 +30,5 @@
 
 from pykota.errors import PyKotaToolError, PyKotaCommandLineError
-from pykota.tool import PyKotaTool, crashed, N_
+from pykota.tool import PyKotaTool
 
 __doc__ = N_("""autopykota v%(__version__)s (c) %(__years__)s %(__author__)s
Index: /pykota/trunk/bin/pkprinters
===================================================================
--- /pykota/trunk/bin/pkprinters (revision 3294)
+++ /pykota/trunk/bin/pkprinters (revision 3295)
@@ -30,5 +30,5 @@
 
 from pykota.errors import PyKotaCommandLineError
-from pykota.tool import Percent, PyKotaTool, crashed, N_
+from pykota.tool import Percent, PyKotaTool
 from pykota.storage import StoragePrinter
 
Index: /pykota/trunk/bin/cupspykota
===================================================================
--- /pykota/trunk/bin/cupspykota (revision 3294)
+++ /pykota/trunk/bin/cupspykota (revision 3295)
@@ -48,5 +48,5 @@
 
 from pykota.errors import PyKotaToolError
-from pykota.tool import PyKotaTool, crashed
+from pykota.tool import PyKotaTool
 from pykota.accounter import openAccounter
 from pykota import cups
Index: /pykota/trunk/bin/pknotify
===================================================================
--- /pykota/trunk/bin/pknotify (revision 3294)
+++ /pykota/trunk/bin/pknotify (revision 3295)
@@ -39,5 +39,5 @@
 
 from pykota.errors import PyKotaToolError, PyKotaCommandLineError
-from pykota.tool import Tool, crashed, N_
+from pykota.tool import Tool
 
 __doc__ = N_("""pknotify v%(__version__)s (c) %(__years__)s %(__author__)s
Index: /pykota/trunk/bin/pykosd
===================================================================
--- /pykota/trunk/bin/pykosd (revision 3294)
+++ /pykota/trunk/bin/pykosd (revision 3295)
@@ -37,5 +37,5 @@
 
 from pykota.errors import PyKotaToolError, PyKotaCommandLineError
-from pykota.tool import PyKotaTool, crashed, N_
+from pykota.tool import PyKotaTool
 
 __doc__ = N_("""pykosd v%(__version__)s (c) %(__years__)s %(__author__)s
Index: /pykota/trunk/bin/pkmail
===================================================================
--- /pykota/trunk/bin/pkmail (revision 3294)
+++ /pykota/trunk/bin/pkmail (revision 3295)
@@ -35,5 +35,5 @@
 
 from pykota.errors import PyKotaCommandLineError
-from pykota.tool import PyKotaTool, crashed, N_
+from pykota.tool import PyKotaTool
     
 __doc__ = N_("""pkmail v%(__version__)s (c) %(__years__)s %(__author__)s
Index: /pykota/trunk/bin/dumpykota
===================================================================
--- /pykota/trunk/bin/dumpykota (revision 3294)
+++ /pykota/trunk/bin/dumpykota (revision 3295)
@@ -28,5 +28,4 @@
 
 from pykota.errors import PyKotaCommandLineError
-from pykota.tool import crashed, N_
 from pykota.dumper import DumPyKota
 
Index: /pykota/trunk/bin/pkrefund
===================================================================
--- /pykota/trunk/bin/pkrefund (revision 3294)
+++ /pykota/trunk/bin/pkrefund (revision 3295)
@@ -48,5 +48,5 @@
 
 from pykota.errors import PyKotaToolError, PyKotaCommandLineError
-from pykota.tool import Percent, PyKotaTool, crashed, N_
+from pykota.tool import Percent, PyKotaTool
 
 __doc__ = N_("""pkrefund v%(__version__)s (c) %(__years__)s %(__author__)s
