[Tkinter-discuss] Tips for using Tkinter in non-US locales and/or locale module integration with Tkinter Entry widgets

Michael Lange klappnase at web.de
Fri Dec 10 19:35:17 CET 2010


Thus spoketh python at bdurham.com 
unto us on Fri, 10 Dec 2010 10:23:37 -0500:

> I noticed there are a lot of non-US developers on this list. I'm
> looking for tips on using Tkinter in non-US locales.
> 
> In particular:
> 
> 1. Are there any Unicode or font specific issues to be concerned
> about?
> 
> 2. Are you using the locale module to control how you display or
> parse data moving into and out of Entry widgets? (has anyone
> wrapped the Entry widget with locale aware code?)
> 
> 3. Are you using gettext with Tkinter and if so, are there any
> tips or traps to watch for? (I think gettext integration should
> be seamless, but didn't think it would hurt to confirm this)

I haven't used python3 yet, I think there aren't separate unicode and byte
string types anymore (can someone confirm this?) which will make things
probably straightforward.
In python-2.x using gettext can be quite a pain in the neck. To be on the
safe side, I always use gettext with unicode=True and take care that any
string that is passed to tk is converted into unicode first and any
string that python receives from Tk is converted into a byte string
before processing it (the odd thing is that sometimes you don't know in
advance if you get a byte string or unicode). When dealing with gettext
I always use a module with some convenience methods to make this easier:

##################################################

sysencoding = _sysencoding().lower()

def fsdecode(input, errors='strict'):
    '''Fail-safe decodes a string into unicode.'''
    if not isinstance(input, unicode):
        try:
            return unicode(input, sysencoding, errors)
        except UnicodeError:
            print 'Unicode Error while decoding string:', input
            return unicode(input, sysencoding, 'replace')
    return input

def fsencode(input, errors='strict'):
    '''Fail-safe encodes a unicode string into system default encoding.'''
    if isinstance(input, unicode):
        try:
            return input.encode(sysencoding, errors)
        except UnicodeError:
            print 'Unicode Error while encoding string:', input
            return input.encode(sysencoding, 'replace')
    return input

class UnicodeVar(Tkinter.StringVar):
    def __init__(self, master=None, errors='strict'):
        self.errors = errors
        Tkinter.StringVar.__init__(self, master)

    def get(self):
        """Return value of variable as unicode string."""
        value = self._tk.globalgetvar(self._name)
        if isinstance(value, basestring):
            return fsdecode(value, self.errors)
        return fsdecode(value, self.errors)

    def set(self, value):
        """Set the variable to VALUE."""
        return self._tk.globalsetvar(self._name, fsencode(value, self.errors))

##################################################

The tricky thing here is of course the _sysencoding() function that
should detect the system default encoding. My function does basically
the same as the idlelib.IOBinding module, so you could replace it with 

def _sysencoding():
    import idlelib
    return idlelib.IOBinding.encoding

The fsdecode and fsencode functions proved to be quite handy, in situations
where you don't know if you have a byte string or unicode I can simply do for
example:

message = _('Unsupported file type') + u':\n"%s"' % fsdecode(fname)

(if fname is e.g. returned from a tkFileDialog it is unicode in case it
contains non-ascii characters, otherwise a byte string; otoh, the same filename
returned by os.listdir() is always a byte string!)

Regards

Michael



.-.. .. ...- .   .-.. --- -. --.   .- -. -..   .--. .-. --- ... .--. . .-.

	"... freedom ... is a worship word..."
	"It is our worship word too."
		-- Cloud William and Kirk, "The Omega Glory", stardate unknown


More information about the Tkinter-discuss mailing list