[r21830]GrampsLocale: Better initialization from environment

Splits out Win32 and Posix initializations to take account of the
fact that on Win32 setlocale() ignores environment variables and on
Posix it's not necessary to check them because setlocale() does the
right thing.

svn: r21833
This commit is contained in:
John Ralls 2013-03-31 22:51:32 +00:00
parent d3d80b443e
commit 444a3f4c12

View File

@ -46,12 +46,72 @@ except ImportError:
except ImportError as err:
LOG.warning("ICU not loaded because %s. Localization will be impaired. "
"Use your package manager to install PyICU", str(err))
#-------------------------------------------------------------------------
#
# gramps modules
#
#-------------------------------------------------------------------------
from ..constfunc import mac, win, UNITYPE
ICU_LOCALES = None
if HAVE_ICU:
ICU_LOCALES = Locale.getAvailableLocales()
#Map our translated language codes to Microsoft Locale Names
#Important: Maintain this list with new translations or they
#won't work under MS Windows!
mslocales = {
'ar': ('Arabic_Saudi Arabia', '1256'),
'bg': ('Bulgrian_Bulgaria', '1251'),
'br': None, #Windows has no translation for Breton
'ca': ('Catalang_Spain', '1252'),
'cs': ('Czech_Czech Republic', '1250'),
'da': ('Danish_Denmark', '1252'),
'de': ('German_Germany', '1252'),
'en_GB': ('English_United Kingdom', '1252'),
'eo': None, #Windows has no translation for Esperanto
'es': ('Spanish_Spain', '1252'),
'fi': ('Finnish_Finland', '1252'),
'fr': ('French_France', '1252'),
'ga': None, #Windows has no translation for Gaelic
'he': ('Hebrew_Israel', '1255'),
'hr': ('Croatian_Croatia', '1250'),
'hu': ('Hungarian_Hungary', '1250'),
'it': ('Italian_Italy', '1252'),
'ja': ('Japanese_Japan', '932'),
'lt': ('Lithuanian_Lithuania', '1252'),
'mk': None, #Windows has no translation for Macedonian
'nb': ('Norwegian_Norway', '1252'),
'nl': ('Dutch_Netherlands', '1252'),
'nn': ('Norwegian-Nynorsk_Norway', '1252'),
'pl': ('Polish_Poland', '1250'),
'pt_BR': ('Portuguese_Brazil', '1252'),
'pt_PT': ('Portuguese_Portugal', '1252'),
'ro': ('Romanian_Romania', '1250'),
'ru': ('Russian_Russia', '1251'),
'sk': ('Slovak_Slovakia', '1250'),
'sl': ('Slovenian_Slovenia', '1250'),
'sq': ('Albanian_Albania', '1250'),
'sr': ('Serbian(Cyrillic)_Serbia and Montenegro', '1251'),
'sv': ('Swedish_Sweden', '1252'),
'tr': ('Turkish_Turkey', '1254'),
'uk': ('Ukrainian_Ukraine', '1251'),
'vi': ('Vietnamese_Viet Nam', '1258'),
'zh_CN': ('Chinese_China', '936'),
}
def _check_mswin_locale(locale):
msloc = None
try:
msloc = mslocales[locale[:5]]
locale = locale[:5]
except KeyError:
try:
msloc = mslocales[locale[:2]]
locale = locale[:2]
except KeyError:
return None
return (locale, msloc)
def _check_mswin_locale_reverse(locale):
for (loc, msloc) in mslocales.items():
if locale == msloc[0]:
return (loc, msloc[1])
return None
#------------------------------------------------------------------------
#
@ -101,53 +161,117 @@ class GrampsLocale(object):
return super(GrampsLocale, cls).__new__(cls)
def __init_from_environment(self):
if not (hasattr(self, 'lang') and self.lang):
lang = ' '
if 'LANG' in os.environ:
lang = os.environ["LANG"]
else:
lang = locale.getlocale()[0]
if not lang:
try:
lang = locale.getdefaultlocale()[0] + '.UTF-8'
except TypeError:
LOG.warning('Unable to determine your Locale, using English')
lang = 'C.UTF-8'
self.lang = lang
def _win_init_environment(self):
"""
The Windows implementation of Python ignores environment
variables when setting the locale; it only pays attention to
the control panel language settings -- which for practical
purposes limits one to the language for which one purchased
Windows. This function enables using alternative
localizations.
"""
if not self.language:
if "LANGUAGE" in os.environ:
if not (hasattr(self, 'lang') and self.lang):
self.lang = None
if 'LANG' in os.environ:
lang = os.environ['LANG']
(lang, loc) = _check_mswin_locale(lang)
if loc:
locale.setlocale(locale.LC_ALL, '.'.join(loc))
self.lang = lang
self.language = [self.lang]
self.encoding = loc[1]
if not self.lang:
locale.setlocale(locale.LC_ALL, '')
(lang, encoding) = locale.getlocale()
loc = _check_mswin_locale_reverse(lang)
if loc:
self.lang = loc[0]
self.languages = [loc[0]]
self.encoding = loc[1]
if not self.lang:
self.lang = 'C'
self.language = ['en']
self.encoding = 'cp1252'
if not (hasattr(self, 'language') and self.language):
if 'LC_MESSAGES' in os.environ:
lang = self.check_available_translations(os.environ['LC_MESSAGES'])
if lang:
self.language = [lang]
if 'LANGUAGE' in os.environ:
language = [x for x in [self.check_available_translations(l)
for l in os.environ["LANGUAGE"].split(":")]
if x]
self.language = language
elif 'LC_MESSAGES' in os.environ:
lang = self.check_available_translations(os.environ['LC_MESSAGES'])
if lang:
self.language = [lang]
elif not self.lang == "C.UTF-8":
l = self.check_available_translations(lang)
if l:
self.language = [l]
else:
self.language = ["en"]
if not (hasattr(self, 'language') and self.language):
self.language = [self.lang]
if "LC_MONETARY" not in os.environ:
self.currency = self.lang
if 'LC_COLLATE' in os.environ:
coll = os.environ['LC_COLLATE']
if HAVE_ICU:
if coll[:5] in ICU_LOCALES:
self.collation = coll
else:
self.collation = self.lang
else:
self.currency = os.environ["LC_MONETARY"]
(coll, loc) = _check_mswin_locale(coll)
if loc:
locale.setlocale(locale.LC_COLLATE, '.'.join(loc))
self.collation = coll
else: #can't set the collation locale if MS doesn't support it
self.collation = self.lang
if "LC_TIME" not in os.environ:
self.calendar = self.lang
else:
self.calendar = os.environ["LC_TIME"]
else:
self.collation = self.lang
if "LC_COLLATE" not in os.environ:
self.collation = self.lang
# We can't import datahandler stuff or we'll get a circular
# dependency, so we rely on the available translations list
if 'LC_TIME' in os.environ:
self.calendar = self.check_available_translations(os.environ['LC_TIME']) or self.lang
else:
self.calendar = self.lang
def _init_from_environment(self):
try:
locale.setlocale(locale.LC_ALL, '')
except locale.Error as err:
LOG.warning("Locale error %s, localization will be US English.",
err);
self.lang = self.calendar = self.collate = 'C'
self.encoding = 'ascii'
self.language = ['en']
return
if not (hasattr(self, 'lang') and self.lang):
(lang, encoding) = locale.getlocale()
if self.check_available_translations(lang):
self.lang = lang
self.encoding = encoding
else:
self.collation = os.environ["LC_COLLATE"]
lang = '.'.join(locale.getlocale(locale.LC_MESSAGES))
if not lang:
try:
lang = locale.getdefaultlocale()[0] + '.UTF-8'
except TypeError:
LOG.warning('Unable to determine your Locale, using English')
lang = 'C'
self.lang = lang
if not (hasattr(self, 'language') and self.language):
if "LANGUAGE" in os.environ:
language = [x for x in [self.check_available_translations(l)
for l in os.environ["LANGUAGE"].split(":")]
if x]
else:
language = [self.lang[:5]]
self.language = language
self.calendar = locale.getlocale(locale.LC_TIME)[0]
self.collation = locale.getlocale(locale.LC_COLLATE)[0]
def _win_bindtextdomain(self, localedomain, localedir):
"""
@ -161,7 +285,7 @@ class GrampsLocale(object):
localedir.encode(sys.getfilesystemencoding()))
libintl.textdomain(localedomain)
libintl.bind_textdomain_codeset(localedomain, "UTF-8")
print("Set domain %s in %s" % (localedomain, localedir))
except WindowsError:
LOG.warning("Localization library libintl not on %PATH%, localization will be incomplete")
@ -172,18 +296,16 @@ class GrampsLocale(object):
LOG.addHandler(_hdlr)
#First, globally set the locale to what's in the environment:
try:
locale.setlocale(locale.LC_ALL, '')
except locale.Error:
pass
if not (hasattr(self, 'lang') and self.lang
and hasattr(self, 'language') and self.language):
if mac():
if sys.platform == 'darwin':
from . import maclocale
maclocale.mac_setup_localization(self)
elif sys.platform == 'win32':
self._win_init_environment()
else:
self.__init_from_environment()
self._init_from_environment()
else:
self.currency = self.calendar = self.collation = self.lang
@ -204,11 +326,10 @@ class GrampsLocale(object):
#translations and date formats with lang, we can't affect currency or
#numeric format. Those are fixed by the user's system settings.
if not win():
if not sys.platform == 'win32':
try:
locale.setlocale(locale.LC_COLLATE, self.collation)
locale.setlocale(locale.LC_TIME, self.calendar)
locale.setlocale(locale.LC_MONETARY, self.currency)
except locale.Error:
pass
#Next, we need to know what is the encoding from the native
@ -244,7 +365,7 @@ class GrampsLocale(object):
# GtkBuilder uses GLib's g_dgettext wrapper, which oddly is bound
# with locale instead of gettext. Win32 doesn't support bindtextdomain.
if self.have_localedir:
if not win():
if not sys.platform == 'win32':
locale.bindtextdomain(self.localedomain, self.localedir)
else:
self._win_bindtextdomain(self.localedomain, self.localedir)
@ -559,6 +680,9 @@ class GrampsLocale(object):
if not hasattr(self, 'languages'):
self.languages = self.get_available_translations()
if not locale:
return None
if locale[:2] in self.languages:
return locale[:2]
if locale[:5] in self.languages: