1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172
|
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""extends the standard Python gettext classes
allows multiple simultaneous domains... (makes multiple sessions with different languages easier too)"""
# Copyright 2002, 2003 St James Software
#
# This file is part of jToolkit.
#
# jToolkit 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 2 of the License, or
# (at your option) any later version.
#
# jToolkit 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 jToolkit; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
import gettext
import locale
import os.path
from errno import ENOENT
from jToolkit import languagenames
class ManyTranslations(gettext.NullTranslations):
"""this proxies to many translations"""
def __init__(self, translations=None):
"""Takes an optional sequence of translations."""
gettext.NullTranslations.__init__(self)
if translations is None:
self.translations = []
else:
self.translations = translations
def gettext(self, message):
"""gets the translation of the message by searching through all the domains"""
for translation in self.translations:
tmsg = translation._catalog.get(message, None)
if tmsg is not None:
return tmsg
return message
def ngettext(self, singular, plural, n):
"""gets the plural translation of the message by searching through all the domains"""
for translation in self.translations:
if not hasattr(translation, "plural"):
continue
plural = translation.plural
tmsg = translation._catalog[(singular, plural(n))]
if tmsg is not None:
return tmsg
if n == 1:
return singular
else:
return plural
def ugettext(self, message):
"""gets the translation of the message by searching through all the domains (unicode version)"""
for translation in self.translations:
tmsg = translation._catalog.get(message, None)
# TODO: we shouldn't set _charset like this. make sure it is set properly
if translation._charset is None: translation._charset = 'UTF-8'
if tmsg is not None:
if isinstance(tmsg, unicode):
return tmsg
else:
return unicode(tmsg, translation._charset)
return unicode(message)
def ungettext(self, singular, plural, n):
"""gets the plural translation of the message by searching through all the domains (unicode version)"""
for translation in self.translations:
if not hasattr(translation, "plural"):
continue
plural = translation.plural
tmsg = translation._catalog.get((singular, plural(n)), None)
# TODO: we shouldn't set _charset like this. make sure it is set properly
if translation._charset is None: translation._charset = 'UTF-8'
if tmsg is not None:
if isinstance(tmsg, unicode):
return tmsg
else:
return unicode(tmsg, translation._charset)
if n == 1:
return unicode(singular)
else:
return unicode(plural)
def getinstalledlanguages(localedir):
"""looks in localedir and returns a list of languages installed there"""
languages = []
def visit(arg, dirname, names):
if 'LC_MESSAGES' in names:
languages.append(os.path.basename(dirname))
os.path.walk(localedir, visit, None)
return languages
def getlanguagenames(languagecodes):
"""return a dictionary mapping the language code to the language name..."""
return dict([(code, languagenames.languagenames.get(code, code)) for code in languagecodes])
def findmany(domains, localedir=None, languages=None):
"""same as gettext.find, but handles many domains, returns many mofiles (not just one)"""
mofiles = []
if languages is None:
languages = getinstalledlanguages(localedir)
for domain in domains:
mofile = gettext.find(domain, localedir, languages)
mofiles.append(mofile)
return mofiles
def translation(domains, localedir=None, languages=None, class_=None):
"""same as gettext.translation, but handles many domains, returns a ManyTranslations object"""
if class_ is None:
class_ = gettext.GNUTranslations
mofiles = findmany(domains, localedir, languages)
# we'll just use null translations where domains are missing ; this code will refuse to
# if None in mofiles:
# missingindex = mofiles.index(None)
# raise IOError(ENOENT, 'No translation file found for domain', domains[missingindex])
translations = []
for mofile in mofiles:
if mofile is None:
t = gettext.NullTranslations()
t._catalog = {}
else:
key = os.path.abspath(mofile)
t = gettext._translations.get(key)
if t is None:
t = gettext._translations.setdefault(key, class_(open(mofile, 'rb')))
translations.append(t)
return ManyTranslations(translations)
def getdefaultlanguage(languagelist):
"""tries to work out the default language from a list"""
def reducelocale(locale):
pos = locale.find('_')
if pos == -1:
return locale
else:
return locale[:pos]
currentlocale, currentencoding = locale.getlocale()
try:
defaultlocale, defaultencoding = locale.getdefaultlocale()
except ValueError:
defaultlocale, defaultencoding = None, None
if len(languagelist) > 0:
if currentlocale is not None:
if currentlocale in languagelist:
return currentlocale
elif reducelocale(currentlocale) in languagelist:
return reducelocale(currentlocale)
if defaultlocale is not None:
if defaultlocale in languagelist:
return defaultlocale
elif reducelocale(defaultlocale) in languagelist:
return reducelocale(defaultlocale)
return languagelist[0]
else:
# if our language list is empty, we'll just ignore it
if currentlocale is not None:
return currentlocale
elif defaultlocale is not None:
return defaultlocale
return None
|