GrampsLocale: Refactor/clean up initialization
Includes moving encoding to be a class variable. svn: r21961
This commit is contained in:
parent
25315ceece
commit
a422b30fd6
@ -144,6 +144,8 @@ class GrampsLocale(object):
|
|||||||
subidrectries in the localedir, e.g. "fr" or "zh_CN".
|
subidrectries in the localedir, e.g. "fr" or "zh_CN".
|
||||||
"""
|
"""
|
||||||
__first_instance = None
|
__first_instance = None
|
||||||
|
encoding = None
|
||||||
|
|
||||||
def __new__(cls, localedir=None, lang=None, domain=None, languages=None):
|
def __new__(cls, localedir=None, lang=None, domain=None, languages=None):
|
||||||
if not GrampsLocale.__first_instance:
|
if not GrampsLocale.__first_instance:
|
||||||
cls.__first_instance = super(GrampsLocale, cls).__new__(cls)
|
cls.__first_instance = super(GrampsLocale, cls).__new__(cls)
|
||||||
@ -315,16 +317,21 @@ class GrampsLocale(object):
|
|||||||
except WindowsError:
|
except WindowsError:
|
||||||
LOG.warning("Localization library libintl not on %PATH%, localization will be incomplete")
|
LOG.warning("Localization library libintl not on %PATH%, localization will be incomplete")
|
||||||
|
|
||||||
def __init_first_instance(self, localedir):
|
def __init_first_instance(self):
|
||||||
|
"""
|
||||||
|
Initialize the primary locale from whatever might be
|
||||||
|
available. We only do this once, and the resulting
|
||||||
|
GrampsLocale is returned by default.
|
||||||
|
"""
|
||||||
global _hdlr
|
global _hdlr
|
||||||
_hdlr = logging.StreamHandler()
|
_hdlr = logging.StreamHandler()
|
||||||
_hdlr.setFormatter(logging.Formatter(fmt="%(name)s.%(levelname)s: %(message)s"))
|
_hdlr.setFormatter(logging.Formatter(fmt="%(name)s.%(levelname)s: %(message)s"))
|
||||||
LOG.addHandler(_hdlr)
|
LOG.addHandler(_hdlr)
|
||||||
|
|
||||||
#First, globally set the locale to what's in the environment:
|
# Even the first instance can be overridden by passing lang
|
||||||
|
# and languages to the constructor. If it isn't (which is the
|
||||||
if not (hasattr(self, 'lang') and self.lang
|
# expected behavior), do platform-specific setup:
|
||||||
and hasattr(self, 'language') and self.language):
|
if not (self.lang and self.language):
|
||||||
if sys.platform == 'darwin':
|
if sys.platform == 'darwin':
|
||||||
from . import maclocale
|
from . import maclocale
|
||||||
maclocale.mac_setup_localization(self)
|
maclocale.mac_setup_localization(self)
|
||||||
@ -339,15 +346,15 @@ class GrampsLocale(object):
|
|||||||
self.lang = 'en_US.UTF-8'
|
self.lang = 'en_US.UTF-8'
|
||||||
if not self.language:
|
if not self.language:
|
||||||
self.language.append('en')
|
self.language.append('en')
|
||||||
if not self.have_localedir and not self.lang.startswith('en'):
|
if not self.localedir and not self.lang.startswith('en'):
|
||||||
LOG.warning("No translations for %s were found, setting localization to U.S. English", self.localedomain)
|
LOG.warning("No translations for %s were found, setting localization to U.S. English", self.localedomain)
|
||||||
self.lang = 'en_US.UTF-8'
|
self.lang = 'en_US.UTF-8'
|
||||||
self.language = ['en']
|
self.language = ['en']
|
||||||
|
|
||||||
#Next, we need to know what is the encoding from the native
|
#Next, we need to know what is the encoding from the native
|
||||||
#environment. This is used by python standard library funcions which
|
#environment. This is used by python standard library funcions which
|
||||||
#localize their output, e.g. time.strftime():
|
#localize their output, e.g. time.strftime(). NB: encoding is a class variable.
|
||||||
if not (hasattr(self, 'encoding') and self.encoding):
|
if not self.encoding:
|
||||||
self.encoding = (locale.getpreferredencoding()
|
self.encoding = (locale.getpreferredencoding()
|
||||||
or sys.getdefaultencoding())
|
or sys.getdefaultencoding())
|
||||||
#Ensure that output is encoded correctly to stdout and stderr. This is
|
#Ensure that output is encoded correctly to stdout and stderr. This is
|
||||||
@ -366,27 +373,64 @@ class GrampsLocale(object):
|
|||||||
'backslashreplace')
|
'backslashreplace')
|
||||||
|
|
||||||
|
|
||||||
#GtkBuilder depends on reading Glade files as UTF-8 and crashes if it
|
# Make sure that self.lang and self.language are reflected
|
||||||
#doesn't, so set $LANG to have a UTF-8 locale. NB: This does *not*
|
# back into the environment for Gtk to use when its
|
||||||
#affect locale.getpreferredencoding() or sys.getfilesystemencoding()
|
# initialized. If self.lang isn't 'C', make sure that it has a
|
||||||
#which are set by python long before we get here.
|
# 'UTF-8' suffix, because that's all that GtkBuilder can
|
||||||
check_lang = self.lang.split('.')
|
# digest.
|
||||||
if len(check_lang) < 2 or check_lang[1] not in ["utf-8", "UTF-8"]:
|
|
||||||
self.lang = '.'.join((check_lang[0], 'UTF-8'))
|
# Linux note: You'll get unsupported locale errors from Gtk
|
||||||
if self.lang == 'C.UTF-8':
|
# and untranslated strings if the requisite UTF-8 locale isn't
|
||||||
os.environ["LANG"] = 'C'
|
# installed. This is particularly a problem on Debian and
|
||||||
else:
|
# Debian-derived distributions which by default don't install
|
||||||
os.environ["LANG"] = self.lang
|
# a lot of locales.
|
||||||
os.environ["LANGUAGE"] = ':'.join(['C' if l.startswith('en') else l for l in self.language])
|
if self.lang != 'C':
|
||||||
|
check_lang = self.lang.split('.')
|
||||||
|
if len(check_lang) < 2 or check_lang[1] not in ["utf-8", "UTF-8"]:
|
||||||
|
self.lang = '.'.join((check_lang[0], 'UTF-8'))
|
||||||
|
|
||||||
|
os.environ["LANG"] = self.lang
|
||||||
|
os.environ["LANGUAGE"] = ':'.join(['C' if l in ('en', 'en_US') else l
|
||||||
|
for l in self.language])
|
||||||
|
|
||||||
# GtkBuilder uses GLib's g_dgettext wrapper, which oddly is bound
|
# GtkBuilder uses GLib's g_dgettext wrapper, which oddly is bound
|
||||||
# with locale instead of gettext. Win32 doesn't support bindtextdomain.
|
# with locale instead of gettext. Win32 doesn't support bindtextdomain.
|
||||||
if self.have_localedir:
|
if self.localedir:
|
||||||
if not sys.platform == 'win32':
|
if not sys.platform == 'win32':
|
||||||
locale.bindtextdomain(self.localedomain, self.localedir)
|
locale.bindtextdomain(self.localedomain, self.localedir)
|
||||||
else:
|
else:
|
||||||
self._win_bindtextdomain(self.localedomain, self.localedir)
|
self._win_bindtextdomain(self.localedomain, self.localedir)
|
||||||
|
|
||||||
|
def _init_secondary_locale(self):
|
||||||
|
"""
|
||||||
|
Init a secondary locale. Secondary locales are used to provide
|
||||||
|
an alternate localization to the one used for the UI; for
|
||||||
|
example, some reports offer the option to use a different
|
||||||
|
language.
|
||||||
|
"""
|
||||||
|
if not self.localedir:
|
||||||
|
LOG.warning("No Localedir provided, unable to find translations")
|
||||||
|
|
||||||
|
if not self.localedomain:
|
||||||
|
if _firstlocaledomain:
|
||||||
|
self.localedomain = _first.localedomain
|
||||||
|
else:
|
||||||
|
self.localedomain = "gramps"
|
||||||
|
|
||||||
|
_first = self._GrampsLocale__first_instance
|
||||||
|
if not self.lang and _first.lang:
|
||||||
|
self.lang = _first.lang
|
||||||
|
|
||||||
|
if not self.language:
|
||||||
|
if self.lang:
|
||||||
|
trans = self.check_available_translations(self.lang)
|
||||||
|
if trans:
|
||||||
|
self.language = [trans]
|
||||||
|
|
||||||
|
if not self.language and _first.language:
|
||||||
|
self.language = _first.language
|
||||||
|
|
||||||
|
self.calendar = self.collation = self.lang
|
||||||
|
|
||||||
def __init__(self, localedir=None, lang=None, domain=None, languages=None):
|
def __init__(self, localedir=None, lang=None, domain=None, languages=None):
|
||||||
"""
|
"""
|
||||||
@ -395,53 +439,39 @@ class GrampsLocale(object):
|
|||||||
otherwise if called without arguments.
|
otherwise if called without arguments.
|
||||||
"""
|
"""
|
||||||
global _hdlr
|
global _hdlr
|
||||||
|
#initialized is special, used only for the "first instance",
|
||||||
|
#and created by __new__(). It's used to prevent re-__init__ing
|
||||||
|
#__first_instance when __new__() returns its pointer.
|
||||||
if hasattr(self, 'initialized') and self.initialized:
|
if hasattr(self, 'initialized') and self.initialized:
|
||||||
return
|
return
|
||||||
|
|
||||||
_first = self._GrampsLocale__first_instance
|
_first = self._GrampsLocale__first_instance
|
||||||
self.have_localedir = True
|
|
||||||
|
|
||||||
if domain:
|
# Everything breaks without localedir, so get that set up
|
||||||
self.localedomain = domain
|
# first. Warnings are logged in _init_first_instance or
|
||||||
elif hasattr(_first, 'localedomain'):
|
# _init_secondary_locale if this comes up empty.
|
||||||
self.localedomain = _first.localedomain
|
if localedir and os.path.exists(os.path.abspath(localedir)):
|
||||||
else:
|
|
||||||
self.localedomain = "gramps"
|
|
||||||
if localedir and os.path.exists(localedir):
|
|
||||||
self.localedir = localedir
|
self.localedir = localedir
|
||||||
elif hasattr(_first, 'localedir'):
|
elif _first and _first.localedir:
|
||||||
self.localedir = _first.localedir
|
self.localedir = _first.localedir
|
||||||
else:
|
else:
|
||||||
self.localedir = None
|
self.localedir = None
|
||||||
if localedir:
|
|
||||||
LOG.warning("Localedir %s doesn't exist, unable to set localization", localedir);
|
|
||||||
else:
|
|
||||||
LOG.warning("No Localedir provided, unable to set localization")
|
|
||||||
self.have_localedir = False
|
|
||||||
|
|
||||||
if lang:
|
self.lang = lang
|
||||||
self.lang = lang
|
self.localedomain = domain or 'gramps'
|
||||||
elif hasattr(_first, 'lang'):
|
|
||||||
self.lang = _first.lang
|
|
||||||
|
|
||||||
self.language = []
|
|
||||||
if languages:
|
if languages:
|
||||||
self.language = [x for x in [self.check_available_translations(l)
|
self.language = [x for x in [self.check_available_translations(l)
|
||||||
for l in languages]
|
for l in languages.split(":")]
|
||||||
if x]
|
if x]
|
||||||
elif hasattr(self, 'lang') and self.lang:
|
|
||||||
trans = self.check_available_translations(lang)
|
|
||||||
if trans:
|
|
||||||
self.language.append(trans)
|
|
||||||
|
|
||||||
if not self.language and hasattr(_first, 'language'):
|
|
||||||
self.language = _first.language
|
|
||||||
|
|
||||||
if self == _first:
|
|
||||||
self._GrampsLocale__init_first_instance(localedir)
|
|
||||||
else:
|
else:
|
||||||
self.calendar = self.collation = self.lang
|
self.language = None
|
||||||
|
|
||||||
|
_first = self._GrampsLocale__first_instance
|
||||||
|
if self == _first:
|
||||||
|
self._GrampsLocale__init_first_instance()
|
||||||
|
else:
|
||||||
|
self._init_secondary_locale()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
self.icu_locales = {}
|
self.icu_locales = {}
|
||||||
@ -692,7 +722,7 @@ class GrampsLocale(object):
|
|||||||
Test a locale for having a translation available
|
Test a locale for having a translation available
|
||||||
locale -- string with standard language code, locale code, or name
|
locale -- string with standard language code, locale code, or name
|
||||||
"""
|
"""
|
||||||
if not self.have_localedir:
|
if not self.localedir:
|
||||||
return None
|
return None
|
||||||
if not hasattr(self, 'languages'):
|
if not hasattr(self, 'languages'):
|
||||||
self.languages = self.get_available_translations()
|
self.languages = self.get_available_translations()
|
||||||
|
Loading…
Reference in New Issue
Block a user