GrampsLocale: Restructure so that multiple GrampsLocale objects can safely be created for different locales
Only the first dependent upon the environment All may be created with parameters which override environment variables or OS settings. See the GrampsLocale docstring for details. svn: r21182
This commit is contained in:
parent
795b45c82f
commit
5e505f2c21
@ -47,54 +47,110 @@ from ..constfunc import mac, win, UNITYPE
|
||||
#------------------------------------------------------------------------
|
||||
class GrampsLocale(object):
|
||||
"""
|
||||
Encapsulate a locale
|
||||
Encapsulate a locale. This class is a sort-of-singleton: The
|
||||
first instance created will query the environment and OSX defaults
|
||||
for missing parameters (precedence is parameters passed to the
|
||||
constructor, environment variables LANG, LC_COLLATE, LC_TIME,
|
||||
etc., and LANGUAGE, OSX defaults settings when that's the
|
||||
platform). Subsequent calls to the constructor with no or
|
||||
identical parameters will return the same Grampslocale
|
||||
object. Construction with different parameters will result in a
|
||||
new GrampsLocale instance with the specified parameters, but any
|
||||
parameters left out will be filled in from the first instance.
|
||||
|
||||
@localedir: The full path to the top level directory containing
|
||||
the translation files. Defaults to sys.prefix/share/locale.
|
||||
|
||||
@lang: A single locale value which is used for unset locale.LC_FOO
|
||||
settings.
|
||||
|
||||
@domain: The name of the applicable translation file. The default is
|
||||
"gramps", indicating files in LC_MESSAGES named gramps.mo.
|
||||
|
||||
@languages: A list of two or five character codes corresponding to
|
||||
subidrectries in the localedir, e.g. "fr" or "zh_CN".
|
||||
"""
|
||||
def __init__(self):
|
||||
self.localedir = None
|
||||
self.lang = None
|
||||
self.language = []
|
||||
if ("GRAMPSI18N" in os.environ
|
||||
and os.path.exists(os.environ["GRAMPSI18N"])):
|
||||
self.localedir = os.environ["GRAMPSI18N"]
|
||||
elif os.path.exists(LOCALE_DIR):
|
||||
self.localedir = LOCALE_DIR
|
||||
elif os.path.exists(os.path.join(sys.prefix, "share", "locale")):
|
||||
self.localedir = os.path.join(sys.prefix, "share", "locale")
|
||||
__first_instance = None
|
||||
def __new__(cls, localedir=None, lang=None, domain=None, languages=None):
|
||||
if not GrampsLocale.__first_instance:
|
||||
cls.__first_instance = super(GrampsLocale, cls).__new__(cls)
|
||||
cls.__first_instance.initialized = False
|
||||
return cls.__first_instance
|
||||
|
||||
if not cls.__first_instance.initialized:
|
||||
raise RuntimeError("Second GrampsLocale created before first one was initialized")
|
||||
if ((lang is None or lang == cls.__first_instance.lang)
|
||||
and (localedir is None or localedir == cls.__first_instance.localedir)
|
||||
and (domain is None or domain == cls.__first_instance.localedomain)
|
||||
and (languages is None or len(languages) == 0 or
|
||||
languages == cls.__first_instance.languages)):
|
||||
return cls.__first_instance
|
||||
|
||||
return super(GrampsLocale, cls).__new__(cls)
|
||||
|
||||
def __init_first_instance(self, localedir=None, lang=None,
|
||||
domain=None, language=None):
|
||||
|
||||
if localedir and os.path.exists(localedir):
|
||||
self.localedir = localedir
|
||||
else:
|
||||
lang = os.environ.get('LANG', 'en')
|
||||
if lang and lang[:2] == 'en':
|
||||
pass # No need to display warning, we're in English
|
||||
if ("GRAMPSI18N" in os.environ
|
||||
and os.path.exists(os.environ["GRAMPSI18N"])):
|
||||
self.localedir = os.environ["GRAMPSI18N"]
|
||||
elif os.path.exists(LOCALE_DIR):
|
||||
self.localedir = LOCALE_DIR
|
||||
elif os.path.exists(os.path.join(sys.prefix, "share", "locale")):
|
||||
self.localedir = os.path.join(sys.prefix, "share", "locale")
|
||||
else:
|
||||
logging.warning('Locale dir does not exist at %s', LOCALE_DIR)
|
||||
logging.warning('Running python setup.py install --prefix=YourPrefixDir might fix the problem')
|
||||
if not lang:
|
||||
lang = os.environ.get('LANG', 'en')
|
||||
if lang and lang[:2] == 'en':
|
||||
pass # No need to display warning, we're in English
|
||||
else:
|
||||
logging.warning('Locale dir does not exist at %s', LOCALE_DIR)
|
||||
logging.warning('Running python setup.py install --prefix=YourPrefixDir might fix the problem')
|
||||
|
||||
if not self.localedir:
|
||||
#No localization files, no point in continuing
|
||||
return
|
||||
self.localedomain = 'gramps'
|
||||
if domain:
|
||||
self.localedomain = domain
|
||||
else:
|
||||
self.localedomain = 'gramps'
|
||||
|
||||
if not language or not isinstance(language, list):
|
||||
language = []
|
||||
else:
|
||||
language = [l for l in languages
|
||||
if l in get_available_translations()]
|
||||
|
||||
if mac():
|
||||
from . import maclocale
|
||||
(self.lang, self.language) = maclocale.mac_setup_localization(self)
|
||||
(self.lang, self.language) = maclocale.mac_setup_localization(self, lang, language)
|
||||
else:
|
||||
self.lang = ' '
|
||||
try:
|
||||
self.lang = os.environ["LANG"]
|
||||
except KeyError:
|
||||
self.lang = locale.getlocale()[0]
|
||||
if not self.lang:
|
||||
if not lang:
|
||||
lang = ' '
|
||||
try:
|
||||
self.lang = locale.getdefaultlocale()[0] + '.UTF-8'
|
||||
except TypeError:
|
||||
logging.warning('Unable to determine your Locale, using English')
|
||||
self.lang = 'C.UTF-8'
|
||||
lang = os.environ["LANG"]
|
||||
except KeyError:
|
||||
lang = locale.getlocale()[0]
|
||||
if not lang:
|
||||
try:
|
||||
lang = locale.getdefaultlocale()[0] + '.UTF-8'
|
||||
except TypeError:
|
||||
logging.warning('Unable to determine your Locale, using English')
|
||||
lang = 'C.UTF-8'
|
||||
self.lang = lang
|
||||
|
||||
if "LANGUAGE" in os.environ:
|
||||
language = [l for l in os.environ["LANGUAGE"].split(":")
|
||||
if l in self.get_available_translations()]
|
||||
self.language = language
|
||||
else:
|
||||
self.language = [self.lang[0:2]]
|
||||
if not language or len(language) == 0:
|
||||
if "LANGUAGE" in os.environ:
|
||||
language = [l for l in os.environ["LANGUAGE"].split(":")
|
||||
if l in get_available_translations()]
|
||||
self.language = language
|
||||
elif not lang == "C.UTF-8":
|
||||
self.language = [lang[0:2]]
|
||||
else:
|
||||
self.language = ["en"]
|
||||
|
||||
#GtkBuilder depends on reading Glade files as UTF-8 and crashes if it
|
||||
#doesn't, so set $LANG to have a UTF-8 locale. NB: This does *not*
|
||||
@ -105,55 +161,71 @@ class GrampsLocale(object):
|
||||
self.lang = '.'.join((check_lang[0], 'UTF-8'))
|
||||
os.environ["LANG"] = self.lang
|
||||
# Set Gramps's translations
|
||||
self.translation = self._get_translation(self.localedomain, self.localedir, self.language)
|
||||
# Now set the locale for everything besides translations.
|
||||
|
||||
try:
|
||||
# First try the environment to preserve individual variables
|
||||
locale.setlocale(locale.LC_ALL, '')
|
||||
try:
|
||||
#Then set LC_MESSAGES to self.lang
|
||||
locale.setlocale(locale.LC_MESSAGES, self.lang)
|
||||
#Then set LC_MESSAGES to lang
|
||||
locale.setlocale(locale.LC_MESSAGES, lang)
|
||||
except locale.Error:
|
||||
logging.warning("Unable to set translations to %s, locale not found.", self.lang)
|
||||
logging.warning("Unable to set translations to %s, locale not found.", lang)
|
||||
except locale.Error:
|
||||
# That's not a valid locale -- on Linux, probably not installed.
|
||||
try:
|
||||
# First fallback is self.lang
|
||||
# First fallback is lang
|
||||
locale.setlocale(locale.LC_ALL, self.lang)
|
||||
logging.warning("Setting locale to individual LC_ variables failed, falling back to %s.", self.lang)
|
||||
logging.warning("Setting locale to individual LC_ variables failed, falling back to %s.", lang)
|
||||
|
||||
except locale.Error:
|
||||
# No good, set the default encoding to C.UTF-8. Don't
|
||||
# mess with anything else.
|
||||
locale.setlocale(locale.LC_ALL, 'C.UTF-8')
|
||||
logging.error("Failed to set locale %s, falling back to English", self.lang)
|
||||
logging.error("Failed to set locale %s, falling back to English", lang)
|
||||
# $LANGUAGE is what sets the Gtk+ translations
|
||||
os.environ["LANGUAGE"] = ':'.join(self.language)
|
||||
# GtkBuilder uses GLib's g_dgettext wrapper, which oddly is bound
|
||||
# with locale instead of gettext.
|
||||
locale.bindtextdomain(self.localedomain, self.localedir)
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# Public Functions
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
self.initialized = True
|
||||
|
||||
def get_localedomain(self):
|
||||
"""
|
||||
Get the LOCALEDOMAIN used for the Gramps application.
|
||||
Required by gui/glade.py to pass to Gtk.Builder
|
||||
"""
|
||||
return self.localedomain
|
||||
|
||||
def get_language_list(self):
|
||||
def __init__(self, lang=None, localedir=None, domain=None, languages=None):
|
||||
"""
|
||||
Return the list of configured languages. Used by
|
||||
ViewManager.check_for_updates to select the language for the
|
||||
addons descriptions.
|
||||
Init a GrampsLocale. Run __init_first_instance() to set up the
|
||||
environement if this is the first run. Return __first_instance
|
||||
otherwise if called without arguments.
|
||||
"""
|
||||
return self.language
|
||||
if self == self._GrampsLocale__first_instance:
|
||||
if not self.initialized:
|
||||
self._GrampsLocale__init_first_instance(lang, localedir,
|
||||
domain, languages)
|
||||
else:
|
||||
return
|
||||
|
||||
else:
|
||||
if domain:
|
||||
self.localedomain = domain
|
||||
else:
|
||||
self.localedomain = self._GrampsLocale__first_instance.localedomain
|
||||
if localedir:
|
||||
self.localedir = localedir
|
||||
else:
|
||||
self.localedir = self._GrampsLocale__first_instance.localedir
|
||||
|
||||
self.language = []
|
||||
if languages and len(languages) > 0:
|
||||
self.language = [l for l in languages
|
||||
if l in get_available_translations()]
|
||||
if len(self.language) == 0:
|
||||
self.language = self._GrampsLocale__first_instance.language
|
||||
|
||||
|
||||
self.translation = self._get_translation(self.localedomain,
|
||||
self.localedir, self.language)
|
||||
|
||||
|
||||
|
||||
|
||||
def _get_translation(self, domain = None,
|
||||
localedir = None,
|
||||
|
@ -73,7 +73,7 @@ locale, leaving $LANGUAGE unset (which is the same as setting it to
|
||||
|
||||
import sys, os, subprocess
|
||||
|
||||
def mac_setup_localization(glocale):
|
||||
def mac_setup_localization(glocale, lang, language):
|
||||
"""
|
||||
Set up the localization parameters from OSX's "defaults" system,
|
||||
permitting environment variables to override the settings.
|
||||
@ -244,33 +244,35 @@ def mac_setup_localization(glocale):
|
||||
if calendar and "LC_TIME" not in os.environ:
|
||||
os.environ["LC_TIME"] = calendar
|
||||
|
||||
if "LANG" in os.environ:
|
||||
lang = os.environ["LANG"]
|
||||
else:
|
||||
lang = "en_US"
|
||||
loc = mac_resolve_locale(loc)
|
||||
if loc != None:
|
||||
lang = loc
|
||||
collation = mac_resolve_locale(collation)
|
||||
if "LC_COLLATE" not in os.environ and collation != None:
|
||||
os.environ["LC_COLLATE"] = collation
|
||||
if not lang:
|
||||
if "LANG" in os.environ:
|
||||
lang = os.environ["LANG"]
|
||||
else:
|
||||
lang = "en_US"
|
||||
loc = mac_resolve_locale(loc)
|
||||
if loc != None:
|
||||
lang = loc
|
||||
collation = mac_resolve_locale(collation)
|
||||
if "LC_COLLATE" not in os.environ and collation != None:
|
||||
os.environ["LC_COLLATE"] = collation
|
||||
|
||||
elif len(collation) > 0:
|
||||
lang = mac_resolve_locale(collation)
|
||||
elif len(collation) > 0:
|
||||
lang = mac_resolve_locale(collation)
|
||||
|
||||
if "LANGUAGE" in os.environ:
|
||||
language = [l for l in os.environ["LANGUAGE"].split(":")
|
||||
if l in available]
|
||||
elif "LANG" in os.environ:
|
||||
language = [lang[0:2]]
|
||||
else:
|
||||
if len(translations) > 0:
|
||||
language = translations
|
||||
elif (len(loc) > 0 and loc in available
|
||||
and not loc.startswith("en")):
|
||||
language = [loc]
|
||||
elif (len(collation) > 0 and collation in available
|
||||
and not collation.startswith("en")):
|
||||
language = [collation]
|
||||
if not language or len(language) == 0:
|
||||
if "LANGUAGE" in os.environ:
|
||||
language = [l for l in os.environ["LANGUAGE"].split(":")
|
||||
if l in available]
|
||||
elif lang != "en_US":
|
||||
language = [lang[0:2]]
|
||||
else:
|
||||
if len(translations) > 0:
|
||||
language = translations
|
||||
elif (len(loc) > 0 and loc in available
|
||||
and not loc.startswith("en")):
|
||||
language = [loc]
|
||||
elif (len(collation) > 0 and collation in available
|
||||
and not collation.startswith("en")):
|
||||
language = [collation]
|
||||
|
||||
return (lang, language)
|
||||
|
Loading…
Reference in New Issue
Block a user