Localization: Re-implement localization as a class, GrampsLocale

GrampsLocale is effectively a singleton: An instance is created in
const.py and retrieved everywhere.

Translations are provided via Translations classes, which are derived
from GNUTranslations and NullTranslations to provide extra functions
like sgettext.

svn: r21143
This commit is contained in:
John Ralls 2013-01-17 19:42:11 +00:00
parent eecf57a0f6
commit d3c2a8a490
15 changed files with 517 additions and 322 deletions

View File

@ -42,8 +42,6 @@ import uuid
# Gramps modules # Gramps modules
# #
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
from .ggettext import sgettext as _
from .svn_revision import get_svn_revision
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
# #
@ -94,6 +92,12 @@ APP_GRAMPS_PKG = "application/x-gramps-package"
APP_GENEWEB = "application/x-geneweb" APP_GENEWEB = "application/x-geneweb"
APP_VCARD = ["text/x-vcard", "text/x-vcalendar"] APP_VCARD = ["text/x-vcard", "text/x-vcalendar"]
#-------------------------------------------------------------------------
#
# system paths
#
#-------------------------------------------------------------------------
LOCALE_DIR = "@LOCALE_DIR@"
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
# #
# Platforms # Platforms
@ -213,6 +217,15 @@ LOGO = os.path.join(IMAGE_DIR, "logo.png")
SPLASH = os.path.join(IMAGE_DIR, "splash.jpg") SPLASH = os.path.join(IMAGE_DIR, "splash.jpg")
LICENSE_FILE = os.path.join(DOC_DIR, 'COPYING') LICENSE_FILE = os.path.join(DOC_DIR, 'COPYING')
#-------------------------------------------------------------------------
#
# Init Localization
#
#-------------------------------------------------------------------------
from .utils.grampslocale import GrampsLocale
GRAMPS_LOCALE = GrampsLocale()
from .ggettext import sgettext as _
>>>>>>> GrampsLocale: Replace use of the GNU Gettext API with the Gettext Class API
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
# #
@ -326,6 +339,7 @@ SHORTOPTS = "O:C:i:e:f:a:p:d:c:lLhuv?s"
GRAMPS_UUID = uuid.UUID('516cd010-5a41-470f-99f8-eb22f1098ad6') GRAMPS_UUID = uuid.UUID('516cd010-5a41-470f-99f8-eb22f1098ad6')
<<<<<<< HEAD
def need_to_update_const(): def need_to_update_const():
""" Check to see if this file is older than """ Check to see if this file is older than
setup.py or const.py.in """ setup.py or const.py.in """
@ -353,4 +367,9 @@ if need_to_update_const():
print("Outdated gramps.gen.const; please run 'python setup.py build'") print("Outdated gramps.gen.const; please run 'python setup.py build'")
GRAMPS_LOCALE = 0 GRAMPS_LOCALE = 0
from .utils.grampslocale import GrampsLocale
GRAMPS_LOCALE = GrampsLocale()
=======
>>>>>>> GrampsLocale: Replace use of the GNU Gettext API with the Gettext Class API

View File

@ -30,65 +30,17 @@ This module ("Gramps Gettext") is an extension to the Python gettext module.
# python modules # python modules
# #
#------------------------------------------------------------------------ #------------------------------------------------------------------------
import gettext as pgettext from gramps.gen.const import GRAMPS_LOCALE as _gl
_tl = _gl.get_translation()
import sys gettext = _tl.gettext
if sys.version_info[0] < 3: # When in the 'C' locale, get_translation returns a NULLTranslation
cuni = unicode # which doesn't provide sgettext. This traps that case and uses
else: # gettext instead -- which is fine, because there's no translation
cuni = str # file involved and it's just going to return the msgid anyeay.
sgettext = None
def gettext(msgid): try:
""" _tl.__getattr__(sgettext)
Obtain translation of gettext, return a unicode object sgettext = _tl.sgettext
:param msgid: The string to translated. except AttributeError:
:type msgid: unicode sgettext = _tl.gettext
:returns: Translation or the original. ngettext = _tl.ngettext
:rtype: unicode
"""
# If msgid =="" then gettext will return po file header
# and that's not what we want.
if len(msgid.strip()) == 0:
return msgid
return cuni(pgettext.gettext(msgid))
def ngettext(singular, plural, n):
"""
The translation of singular/plural is returned unless the translation is
not available and the singular contains the separator. In that case,
the returned value is the singular.
:param singular: The singular form of the string to be translated.
may contain a context seperator
:type singular: unicode
:param plural: The plural form of the string to be translated.
:type plural: unicode
:param n: the amount for which to decide the translation
:type n: int
:returns: Translation or the original.
:rtype: unicode
"""
return cuni(pgettext.ngettext(singular, plural, n))
def sgettext(msgid, sep='|'):
"""
Strip the context used for resolving translation ambiguities.
The translation of msgid is returned unless the translation is
not available and the msgid contains the separator. In that case,
the returned value is the portion of msgid following the last
separator. Default separator is '|'.
:param msgid: The string to translated.
:type msgid: unicode
:param sep: The separator marking the context.
:type sep: unicode
:returns: Translation or the original with context stripped.
:rtype: unicode
"""
msgval = pgettext.gettext(msgid)
if msgval == msgid:
sep_idx = msgid.rfind(sep)
msgval = msgid[sep_idx+1:]
return cuni(msgval)

View File

@ -42,9 +42,8 @@ import traceback
# GRAMPS modules # GRAMPS modules
# #
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
from ..const import VERSION as GRAMPSVERSION, VERSION_TUPLE from ..const import VERSION as GRAMPSVERSION, VERSION_TUPLE, GRAMPS_LOCALE as glocale
from ..const import IMAGE_DIR from ..const import IMAGE_DIR
from ..utils.grampslocale import get_addon_translator
from ..ggettext import gettext as _ from ..ggettext import gettext as _
from ..constfunc import STRTYPE from ..constfunc import STRTYPE
@ -836,8 +835,9 @@ class PluginData(object):
def _set_gramplet_title(self, gramplet_title): def _set_gramplet_title(self, gramplet_title):
if not self._ptype == GRAMPLET: if not self._ptype == GRAMPLET:
raise ValueError('gramplet_title may only be set for GRAMPLET plugins') raise ValueError('gramplet_title may only be set for GRAMPLET plugins')
if not isinstance(gramplet_title, str): if not (sys.version_info[0] < 3 and isinstance(gramplet_title, unicode)
raise ValueError('Plugin must have a string as gramplet_title') or isinstance(gramplet_title, str)):
raise ValueError('gramplet_title is type %s, string or unicode required' % type(gramplet_title))
self._gramplet_title = gramplet_title self._gramplet_title = gramplet_title
def _get_gramplet_title(self): def _get_gramplet_title(self):
@ -1091,7 +1091,7 @@ class PluginRegister(object):
full_filename = os.path.join(dir, filename) full_filename = os.path.join(dir, filename)
if sys.version_info[0] < 3: if sys.version_info[0] < 3:
full_filename = full_filename.encode(sys.getfilesystemencoding()) full_filename = full_filename.encode(sys.getfilesystemencoding())
local_gettext = get_addon_translator(full_filename).gettext local_gettext = glocale.get_addon_translator(full_filename).gettext
try: try:
#execfile(full_filename, #execfile(full_filename,
exec(compile(open(full_filename).read(), full_filename, 'exec'), exec(compile(open(full_filename).read(), full_filename, 'exec'),

View File

@ -170,7 +170,7 @@ def get_unicode_path_from_env_var(path):
""" """
# make only unicode of path of type 'str' # make only unicode of path of type 'str'
if not (isinstance(path, str)): if not (isinstance(path, str)):
return path raise TypeError("path %s isn't a str" % str(path))
if win(): if win():
# In Windows path/filename returned from a environment variable is in filesystemencoding # In Windows path/filename returned from a environment variable is in filesystemencoding

View File

@ -37,109 +37,45 @@ import logging
# gramps modules # gramps modules
# #
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
from ..const import ROOT_DIR from ..const import LOCALE_DIR
from ..constfunc import mac, UNITYPE from ..constfunc import mac, win, UNITYPE
class GrampsLocale(locale): #------------------------------------------------------------------------
"""
Encapsulate a locale
"""
def __init__(self):
def _get_prefix(self):
"""
Find the root path for share/locale
"""
if sys.platform == "win32":
if sys.prefix == os.path.dirname(os.getcwd()):
return sys.prefix
else:
return os.path.join(os.path.dirname(__file__), os.pardir)
elif sys.platform == "darwin" and sys.prefix != sys.exec_prefix:
return sys.prefix
else:
return os.path.join(os.path.dirname(__file__), os.pardir)
def _init_gettext(self):
"""
Set up the gettext domain
"""
#the order in which bindtextdomain on gettext and on locale is called
#appears important, so we refrain from doing first all gettext.
# #
#setup_gettext() # GrampsLocale Class
gettext.bindtextdomain(self.localedomain, self.localedir) #
try: #------------------------------------------------------------------------
locale.setlocale(locale.LC_ALL,'') class GrampsLocale(object):
except: """
logging.warning(_("WARNING: Setting locale failed. Please fix" Encapsulate a locale
" the LC_* and/or the LANG environment " """
"variables to prevent this error")) def __init__(self):
try:
# It is probably not necessary to set the locale to 'C'
# because the locale will just stay at whatever it was,
# which at startup is "C".
# however this is done here just to make sure that the locale
# functions are working
locale.setlocale(locale.LC_ALL,'C')
except:
logging.warning(_("ERROR: Setting the 'C' locale didn't "
"work either"))
# FIXME: This should propagate the exception,
# if that doesn't break Gramps under Windows
raise
gettext.textdomain(slef.localedomain)
if sys.version_info[0] < 3:
gettext.install(self.localedomain, localedir=None, unicode=1) #None is sys default locale
else:
gettext.install(self.localedomain, localedir=None) #None is sys default locale
if hasattr(os, "uname"):
operating_system = os.uname()[0]
else:
operating_system = sys.platform
if win(): # Windows
setup_windows_gettext()
elif operating_system == 'FreeBSD':
try:
gettext.bindtextdomain(self.localedomain, self.localedir)
except locale.Error:
logging.warning('No translation in some Gtk.Builder strings, ')
elif operating_system == 'OpenBSD':
pass
else: # normal case
try:
locale.bindtextdomain(self.localedomain, self.localedir)
#locale.textdomain(self.localedomain)
except locale.Error:
logging.warning('No translation in some Gtk.Builder strings, ')
prefixdir = self._get_prefix()
if "GRAMPSI18N" in os.environ:
if os.path.exists(os.environ["GRAMPSI18N"]):
self.localedir = os.environ["GRAMPSI18N"]
else:
self.localedir = None
elif os.path.exists( os.path.join(ROOT_DIR, "lang") ):
self.localedir = os.path.join(ROOT_DIR, "lang")
elif os.path.exists(os.path.join(prefixdir, "share/locale")):
self.localedir = os.path.join(prefixdir, "share/locale")
else:
self.lang = os.environ.get('LANG', 'en')
if self.lang and self.lang[:2] == 'en':
pass # No need to display warning, we're in English
else:
logging.warning('Locale dir does not exist at ' +
os.path.join(prefixdir, "share/locale"))
logging.warning('Running python setup.py install --prefix=YourPrefixDir might fix the problem')
self.localedir = None 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")
else:
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' self.localedomain = 'gramps'
if mac(): if mac():
from . import maclocale from . import maclocale
maclocale.mac_setup_localization(self.localedir, self.localedomain) (self.lang, self.language) = maclocale.mac_setup_localization(self)
else: else:
self.lang = ' ' self.lang = ' '
try: try:
@ -151,25 +87,142 @@ Encapsulate a locale
self.lang = locale.getdefaultlocale()[0] + '.UTF-8' self.lang = locale.getdefaultlocale()[0] + '.UTF-8'
except TypeError: except TypeError:
logging.warning('Unable to determine your Locale, using English') logging.warning('Unable to determine your Locale, using English')
self.lang = 'en.UTF-8' self.lang = 'C.UTF-8'
os.environ["LANG"] = self.lang if "LANGUAGE" in os.environ:
os.environ["LANGUAGE"] = self.lang language = [l for l in os.environ["LANGUAGE"].split(":")
self._init_gettext() if l in self.get_available_translations()]
self.language = language
else:
self.language = [self.lang[0:2]]
#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*
#affect locale.getpreferredencoding() or sys.getfilesystemencoding()
#which are set by python long before we get here.
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
# 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)
except locale.Error:
logging.warning("Unable to set translations to %s, locale not found.", self.lang)
except locale.Error:
# That's not a valid locale -- on Linux, probably not installed.
try:
# First fallback is self.lang
locale.setlocale(locale.LC_ALL, self.lang)
logging.warning("Setting locale to individual LC_ variables failed, falling back to %s.", self.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)
# $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 # Public Functions
# #
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
def get_localedomain(self): def get_localedomain(self):
""" """
Get the LOCALEDOMAIN used for the Gramps application. Get the LOCALEDOMAIN used for the Gramps application.
Required by gui/glade.py to pass to Gtk.Builder
""" """
return self.localedomain return self.localedomain
def get_addon_translator(self, filename=None, domain="addon", def _get_translation(self, domain = None,
localedir = None,
languages=None):
"""
Get a translation of one of our classes. Doesn't return the
singleton so that it can be used by get_addon_translation()
"""
if not domain:
domain = self.localedomain
if not languages:
languages = self.language
if not localedir:
localedir = self.localedir
if gettext.find(domain, localedir, languages):
return gettext.translation(domain, localedir,
languages,
class_ = GrampsTranslations)
else:
logging.debug("Unable to find translations for %s and %s in %s"
, domain, languages, localedir)
return GrampsNullTranslations()
#-------------------------------------------------------------------------
#
# Public Functions
#
#-------------------------------------------------------------------------
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):
"""
Return the list of configured languages. Used by
ViewManager.check_for_updates to select the language for the
addons descriptions.
"""
return self.language
def get_translation(self, domain = None, languages = None):
"""
Get a translation object for a particular language.
See the gettext documentation for the available functions
>>> glocale = GrampsLocale()
>>> _ = glocale.get_translation('foo', 'French')
>>> _ = tr.gettext
"""
if ((domain and not domain == self.localedomain)
or (languages and not languages == self.language)):
if not domain:
domain = self.localedomain
if not languages:
languages = self.language
fallback = False
if "en" in languages:
fallback = True
try:
# Don't use _get_translation because we want to fall
# back on the singleton rather than a NullTranslation
return gettext.translation(domain, self.localedir,
languages,
class_ = GrampsTranslations,
fallback = fallback)
except IOError:
logging.warning("None of the requested languages (%s) were available, using %s instead", ', '.join(languages), self.lang)
return self.translation
else:
return self.translation
def get_addon_translator(self, filename, domain="addon",
languages=None): languages=None):
""" """
Get a translator for an addon. Get a translator for an addon.
@ -181,43 +234,32 @@ Encapsulate a locale
returns - a gettext.translation object returns - a gettext.translation object
Example: Example:
_ = get_addon_translator(languages=["fr_BE.utf8"]).gettext _ = glocale.get_addon_translator(languages=["fr_BE.utf8"]).gettext
The return object has the following properties and methods:
.gettext
.info
.lgettext
.lngettext
.ngettext
.output_charset
.plural
.set_output_charset
.ugettext
.ungettext
See the python gettext documentation.
Assumes path/filename Assumes path/filename
path/locale/LANG/LC_MESSAGES/addon.mo. path/locale/LANG/LC_MESSAGES/addon.mo.
""" """
if filename is None: path = self.localedir
filename = sys._getframe(1).f_code.co_filename # If get the path of the calling module's uncompiled file. This seems a remarkably bad idea.
gramps_translator = gettext.translation(LOCALEDOMAIN, LOCALEDIR, # if filename is None:
fallback=True) # filename = sys._getframe(1).f_code.co_filename
path = os.path.dirname(os.path.abspath(filename))
gramps_translator = self._get_translation()
path = os.path.dirname(os.path.abspath(filename))
# Check if path is of type str. Do import and conversion if so. # Check if path is of type str. Do import and conversion if so.
# The import cannot be done at the top as that will conflict with the translation system. # The import cannot be done at the top as that will conflict with the translation system.
if not isinstance(path, UNITYPE) == str: if not isinstance(path, UNITYPE) == str:
from .file import get_unicode_path_from_env_var from .file import get_unicode_path_from_env_var
path = get_unicode_path_from_env_var(path) path = get_unicode_path_from_env_var(path)
if languages: if languages:
addon_translator = gettext.translation(domain, addon_translator = self._get_translation(domain,
os.path.join(path, "locale"), path,
languages=languages, languages=languages)
fallback=True) else:
else: addon_translator = self._get_translation(domain, path)
addon_translator = gettext.translation(domain,
os.path.join(path, "locale"),
fallback=True)
gramps_translator.add_fallback(addon_translator) gramps_translator.add_fallback(addon_translator)
return gramps_translator # with a language fallback return gramps_translator # with a language fallback
@ -231,12 +273,13 @@ Encapsulate a locale
""" """
languages = ["en"] languages = ["en"]
if slef.localedir is None: if self.localedir is None:
return languages return languages
for langdir in os.listdir(self.localedir): for langdir in os.listdir(self.localedir):
mofilename = os.path.join(self.localedir, langdir, mofilename = os.path.join(self.localedir, langdir,
"LC_MESSAGES", "%s.mo" % self.localedomain ) "LC_MESSAGES",
"%s.mo" % self.localedomain )
if os.path.exists(mofilename): if os.path.exists(mofilename):
languages.append(langdir) languages.append(langdir)
@ -249,7 +292,7 @@ Encapsulate a locale
Translates objclass_str into "... %s", where objclass_str Translates objclass_str into "... %s", where objclass_str
is 'Person', 'person', 'Family', 'family', etc. is 'Person', 'person', 'Family', 'family', etc.
""" """
from ..ggettext import gettext as _ _ = self.translation.gettext
objclass = objclass_str.lower() objclass = objclass_str.lower()
if objclass == "person": if objclass == "person":
return _("the person") return _("the person")
@ -271,3 +314,184 @@ Encapsulate a locale
return _("the filter") return _("the filter")
else: else:
return _("See details") return _("See details")
def getfilesystemencoding(self):
"""
If the locale isn't configured correctly, this will return
'ascii' or 'ANSI_X3.4-1968' or some other unfortunate
result. Current unix systems all encode filenames in utf-8,
and Microsoft Windows uses utf-16 (which they call mbcs). Make
sure we return the right value.
"""
encoding = sys.getfilesystemencoding()
if encoding in ("utf-8", "UTF-8", "utf8", "UTF8", "mbcs", "MBCS"):
return encoding
return "utf-8"
#-------------------------------------------------------------------------
#
# GrampsTranslation Class
#
#-------------------------------------------------------------------------
class GrampsTranslations(gettext.GNUTranslations):
"""
Overrides and extends gettext.GNUTranslations. See the Python gettext
"Class API" documentation for how to use this.
"""
def language(self):
"""
Return the target languge of this translations object.
"""
return self.info()["language"]
def gettext(self, msgid):
"""
Obtain translation of gettext, return a unicode object
:param msgid: The string to translated.
:type msgid: unicode
:returns: Translation or the original.
:rtype: unicode
"""
# If msgid =="" then gettext will return po file header
# and that's not what we want.
if len(msgid.strip()) == 0:
return msgid
if sys.version_info[0] < 3:
return gettext.GNUTranslations.ugettext(self, msgid)
else:
return gettext.GNUTranslations.gettext(self, msgid)
def ngettext(self, singular, plural, num):
"""
The translation of singular/plural is returned unless the translation is
not available and the singular contains the separator. In that case,
the returned value is the singular.
:param singular: The singular form of the string to be translated.
may contain a context seperator
:type singular: unicode
:param plural: The plural form of the string to be translated.
:type plural: unicode
:param num: the amount for which to decide the translation
:type num: int
:returns: Translation or the original.
:rtype: unicode
"""
if sys.version_info[0] < 3:
return gettext.GNUTranslations.ungettext(self, singular,
plural, num)
else:
return gettext.GNUTranslations.ngettext(self, singular,
plural, num)
def sgettext(self, msgid, sep='|'):
"""
Even with a null translator we need to filter out the translator hint.
"""
msgval = self.gettext(msgid)
if msgval == msgid:
sep_idx = msgid.rfind(sep)
msgval = msgid[sep_idx+1:]
return msgval
#-------------------------------------------------------------------------
#
# Translations Classes
#
#-------------------------------------------------------------------------
class GrampsTranslations(gettext.GNUTranslations):
"""
Overrides and extends gettext.GNUTranslations. See the Python gettext
"Class API" documentation for how to use this.
"""
def language(self):
"""
Return the target languge of this translations object.
"""
return self.info()["language"]
def gettext(self, msgid):
"""
Obtain translation of gettext, return a unicode object
:param msgid: The string to translated.
:type msgid: unicode
:returns: Translation or the original.
:rtype: unicode
"""
# If msgid =="" then gettext will return po file header
# and that's not what we want.
if len(msgid.strip()) == 0:
return msgid
if sys.version_info[0] < 3:
return gettext.GNUTranslations.ugettext(self, msgid)
else:
return gettext.GNUTranslations.gettext(self, msgid)
def ngettext(self, singular, plural, num):
"""
The translation of singular/plural is returned unless the translation is
not available and the singular contains the separator. In that case,
the returned value is the singular.
:param singular: The singular form of the string to be translated.
may contain a context seperator
:type singular: unicode
:param plural: The plural form of the string to be translated.
:type plural: unicode
:param num: the amount for which to decide the translation
:type num: int
:returns: Translation or the original.
:rtype: unicode
"""
if sys.version_info[0] < 3:
return gettext.GNUTranslations.ungettext(self, singular,
plural, num)
else:
return gettext.GNUTranslations.ngettext(self, singular,
plural, num)
def sgettext(self, msgid, sep='|'):
"""
Strip the context used for resolving translation ambiguities.
The translation of msgid is returned unless the translation is
not available and the msgid contains the separator. In that case,
the returned value is the portion of msgid following the last
separator. Default separator is '|'.
:param msgid: The string to translated.
:type msgid: unicode
:param sep: The separator marking the context.
:type sep: unicode
:returns: Translation or the original with context stripped.
:rtype: unicode
"""
msgval = self.gettext(msgid)
if msgval == msgid:
sep_idx = msgid.rfind(sep)
msgval = msgid[sep_idx+1:]
return msgval
class GrampsNullTranslations(gettext.NullTranslations):
"""
Extends gettext.NullTranslations to provide the sgettext method.
Note that it's necessary for msgid to be unicode. If it's not,
neither will be the returned string.
"""
def sgettext(self, msgid):
msgval = self.gettext(msgid)
if msgval == msgid:
sep_idx = msgid.rfind(sep)
msgval = msgid[sep_idx+1:]
return msgval
def language(self):
"""
The null translation returns the raw msgids, which are in English
"""
return "en"

View File

@ -50,8 +50,8 @@ Keyword translation interface
# 'n' : nickname = nick name # 'n' : nickname = nick name
# 'g' : familynick = family nick name # 'g' : familynick = family nick name
import gettext from gramps.gen.const import GRAMPS_LOCALE as glocale
_ = gettext.gettext _ = glocale.get_translation().gettext
KEYWORDS = [("title", "t", _("Person|Title"), _("Person|TITLE")), KEYWORDS = [("title", "t", _("Person|Title"), _("Person|TITLE")),
("given", "f", _("Given"), _("GIVEN")), ("given", "f", _("Given"), _("GIVEN")),

View File

@ -73,36 +73,23 @@ locale, leaving $LANGUAGE unset (which is the same as setting it to
import sys, os, subprocess import sys, os, subprocess
def get_available_translations(dir, domain): def mac_setup_localization(glocale):
""" """
Get a list of available translations. Set up the localization parameters from OSX's "defaults" system,
permitting environment variables to override the settings.
:returns: A list of translation languages.
:rtype: unicode[]
""" """
languages = ["en"]
if dir is None:
return languages
for langdir in os.listdir(dir):
mofilename = os.path.join( dir, langdir,
"LC_MESSAGES", "%s.mo" % domain )
if os.path.exists(mofilename):
languages.append(langdir)
languages.sort()
return languages
def mac_setup_localization(dir, domain):
defaults = "/usr/bin/defaults" defaults = "/usr/bin/defaults"
find = "/usr/bin/find" find = "/usr/bin/find"
locale_dir = "/usr/share/locale" locale_dir = "/usr/share/locale"
available = get_available_translations(dir, domain) if glocale:
available = glocale.get_available_translations()
else:
available = ['en']
def mac_language_list(): def mac_language_list():
"""
Extract the languages list from defaults.
"""
languages = [] languages = []
try: try:
languages = subprocess.Popen( languages = subprocess.Popen(
@ -140,6 +127,9 @@ def mac_setup_localization(dir, domain):
return usable return usable
def mac_get_locale(): def mac_get_locale():
"""
Get the locale and specifiers from defaults.
"""
locale = "" locale = ""
calendar = "" calendar = ""
currency = "" currency = ""
@ -177,6 +167,9 @@ def mac_setup_localization(dir, domain):
return (locale, calendar, currency) return (locale, calendar, currency)
def mac_get_collation(): def mac_get_collation():
"""
Extract the collation (sort order) locale from the defaults string.
"""
collation = "" collation = ""
try: try:
collation = subprocess.Popen( collation = subprocess.Popen(
@ -196,11 +189,13 @@ def mac_setup_localization(dir, domain):
return collation return collation
# Locale.setlocale() will throw if any LC_* environment variable isn't
# a fully qualified one present in
# /usr/share/locale. mac_resolve_locale ensures that a locale meets
# that requirement.
def mac_resolve_locale(loc): def mac_resolve_locale(loc):
"""
Locale.setlocale() will throw if any LC_* environment variable
isn't a fully qualified one present in
/usr/share/locale. mac_resolve_locale ensures that a locale
meets that requirement.
"""
if len(loc) < 2: if len(loc) < 2:
return None return None
if len(loc) >= 5 and os.path.exists(os.path.join(locale_dir, loc[:5])): if len(loc) >= 5 and os.path.exists(os.path.join(locale_dir, loc[:5])):
@ -214,11 +209,10 @@ def mac_setup_localization(dir, domain):
else: else:
# OK, no, look through the translation list, but that's not likely # OK, no, look through the translation list, but that's not likely
# to be 5 letters long either # to be 5 letters long either
for l in translations: for _la in translations:
if (l.startswith(loc) and len(l) >= 5 if (_la.startswith(loc) and len(_la) >= 5
and os.path.exists(os.path.join(locale_dir, l[:5]))): and os.path.exists(os.path.join(locale_dir, _la[:5]))):
return l[:5] return _la[:5]
break
else: else:
# so as a last resort, pick the first one for that language. # so as a last resort, pick the first one for that language.
@ -237,20 +231,22 @@ def mac_setup_localization(dir, domain):
collation = mac_get_collation() collation = mac_get_collation()
translations = mac_language_list() translations = mac_language_list()
if "LANGUAGE" not in os.environ: if currency and "LC_MONETARY" not in os.environ:
if len(translations) > 0: os.environ["LC_MONETARY"] = currency
if "MULTI_TRANSLATION" in os.environ:
os.environ["LANGUAGE"] = ":".join(translations)
else:
os.environ["LANGUAGE"] = translations[0]
elif (len(loc) > 0 and loc in available
and not locale.starts_with("en")):
os.environ["LANGUAGE"] = locale
elif (len(collation) > 0 and collation in available
and not collation.starts_with("en")):
os.environ["LANGUAGE"] = collation
if "LANG" not in os.environ: if calendar and "LC_TIME" not in os.environ:
os.environ["LC_TIME"] = calendar
if currency and "LC_MONETARY" not in os.environ:
os.environ["LC_MONETARY"] = currency
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" lang = "en_US"
loc = mac_resolve_locale(loc) loc = mac_resolve_locale(loc)
if loc != None: if loc != None:
@ -261,6 +257,20 @@ def mac_setup_localization(dir, domain):
elif len(collation) > 0: elif len(collation) > 0:
lang = mac_resolve_locale(collation) lang = mac_resolve_locale(collation)
if lang != None:
os.environ["LANG"] = lang if "LANGUAGE" in os.environ:
os.environ["LC_CTYPE"] = lang + ".UTF-8" 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]
return (lang, language)

View File

@ -39,8 +39,7 @@ if sys.version_info[0] < 3:
## ##
import os import os
import signal import signal
import gettext
_ = gettext.gettext
import locale import locale
import logging import logging
@ -53,8 +52,9 @@ from subprocess import Popen, PIPE
# GRAMPS modules # GRAMPS modules
# #
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
from .gen.const import APP_GRAMPS, USER_DIRLIST, HOME_DIR, VERSION_TUPLE, GRAMPS_LOCALE from .gen.const import APP_GRAMPS, USER_DIRLIST, HOME_DIR, VERSION_TUPLE
from .gen.constfunc import win from .gen.constfunc import win
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
# #
# Setup logging # Setup logging
@ -113,14 +113,15 @@ def exc_hook(type, value, tb):
sys.excepthook = exc_hook sys.excepthook = exc_hook
from .gen.mime import mime_type_is_defined from .gen.mime import mime_type_is_defined
from .gen.utils.grampslocale import GrampsLocale
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
# #
# Load internationalization setup # Instantiate Localization
# #
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
const.GRAMPS_LOCALE = GrampsLocale() from .gen.const import GRAMPS_LOCALE as glocale
_ = glocale.get_translation().gettext
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
# #

View File

@ -50,14 +50,13 @@ from gi.repository import GdkPixbuf
# gramps modules # gramps modules
# #
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
from gramps.gen.const import IMAGE_DIR, URL_MANUAL_PAGE from gramps.gen.const import IMAGE_DIR, URL_MANUAL_PAGE, GRAMPS_LOCALE as glocale
from gramps.gen.config import config from gramps.gen.config import config
from gramps.gen.lib import NoteType from gramps.gen.lib import NoteType
from gramps.gen.datehandler import get_date from gramps.gen.datehandler import get_date
from .display import display_help from .display import display_help
from .managedwindow import ManagedWindow from .managedwindow import ManagedWindow
from gramps.gen.ggettext import sgettext as _ from gramps.gen.ggettext import sgettext as _
from gramps.gen.utils.grampslocale import trans_objclass
from gramps.gen.constfunc import mac from gramps.gen.constfunc import mac
from .glade import Glade from .glade import Glade
from .ddtargets import DdTargets from .ddtargets import DdTargets
@ -1470,13 +1469,13 @@ class MultiTreeView(Gtk.TreeView):
objclass, handle = None, None objclass, handle = None, None
if objclass in ['Person', 'Event', 'Media', 'Source', if objclass in ['Person', 'Event', 'Media', 'Source',
'Repository', 'Family', 'Note', 'Place']: 'Repository', 'Family', 'Note', 'Place']:
menu_item = Gtk.MenuItem(label=_("the object|See %s details") % trans_objclass(objclass)) menu_item = Gtk.MenuItem(label=_("the object|See %s details") % glocale.trans_objclass(objclass))
menu_item.connect("activate", menu_item.connect("activate",
lambda widget: self.edit_obj(objclass, handle)) lambda widget: self.edit_obj(objclass, handle))
popup.append(menu_item) popup.append(menu_item)
menu_item.show() menu_item.show()
# --------------------------- # ---------------------------
menu_item = Gtk.MenuItem(label=_("the object|Make %s active") % trans_objclass(objclass)) menu_item = Gtk.MenuItem(label=_("the object|Make %s active") % glocale.trans_objclass(objclass))
menu_item.connect("activate", menu_item.connect("activate",
lambda widget: self.uistate.set_active(handle, objclass)) lambda widget: self.uistate.set_active(handle, objclass))
popup.append(menu_item) popup.append(menu_item)
@ -1492,7 +1491,7 @@ class MultiTreeView(Gtk.TreeView):
obj = self.dbstate.db.get_table_metadata(objclass)["handle_func"](my_handle) obj = self.dbstate.db.get_table_metadata(objclass)["handle_func"](my_handle)
if obj: if obj:
gids.add(obj.gramps_id) gids.add(obj.gramps_id)
menu_item = Gtk.MenuItem(label=_("the object|Create Filter from %s selected...") % trans_objclass(objclass)) menu_item = Gtk.MenuItem(label=_("the object|Create Filter from %s selected...") % glocale.trans_objclass(objclass))
menu_item.connect("activate", menu_item.connect("activate",
lambda widget: make_filter(self.dbstate, self.uistate, lambda widget: make_filter(self.dbstate, self.uistate,
objclass, gids, title=self.title)) objclass, gids, title=self.title))

View File

@ -48,8 +48,7 @@ from gi.repository import Gtk
# gramps modules # gramps modules
# #
#------------------------------------------------------------------------ #------------------------------------------------------------------------
from gramps.gen.const import GLADE_DIR from gramps.gen.const import GLADE_DIR, GRAMPS_LOCALE as glocale
from gramps.gen.utils.grampslocale import LOCALEDOMAIN
from gramps.gen.constfunc import STRTYPE from gramps.gen.constfunc import STRTYPE
#------------------------------------------------------------------------ #------------------------------------------------------------------------
@ -82,7 +81,7 @@ class Glade(Gtk.Builder):
:returns: reference to the newly-created Glade instance :returns: reference to the newly-created Glade instance
""" """
GObject.GObject.__init__(self) GObject.GObject.__init__(self)
self.set_translation_domain(LOCALEDOMAIN) self.set_translation_domain(glocale.get_localedomain())
filename_given = filename is not None filename_given = filename is not None
dirname_given = dirname is not None dirname_given = dirname is not None

View File

@ -52,9 +52,9 @@ from gi.repository import Gtk
# Gramps modules # Gramps modules
# #
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
from gramps.gen.const import GRAMPS_LOCALE as glocale
from gramps.gen.ggettext import sgettext as _ from gramps.gen.ggettext import sgettext as _
from gramps.gen.simple import SimpleTable from gramps.gen.simple import SimpleTable
from gramps.gen.utils.grampslocale import trans_objclass
from gramps.gen.errors import WindowActiveError from gramps.gen.errors import WindowActiveError
from ...widgets.multitreeview import MultiTreeView from ...widgets.multitreeview import MultiTreeView
from ...ddtargets import DdTargets from ...ddtargets import DdTargets
@ -127,7 +127,7 @@ class QuickTable(SimpleTable):
if (index is not None and self._link[index]): if (index is not None and self._link[index]):
# See details (edit, etc): # See details (edit, etc):
objclass, handle = self._link[index] objclass, handle = self._link[index]
menu_item = Gtk.MenuItem(label=_("the object|See %s details") % trans_objclass(objclass)) menu_item = Gtk.MenuItem(label=_("the object|See %s details") % glocale.trans_objclass(objclass))
menu_item.connect("activate", menu_item.connect("activate",
lambda widget: self.on_table_doubleclick(treeview)) lambda widget: self.on_table_doubleclick(treeview))
popup.append(menu_item) popup.append(menu_item)
@ -137,7 +137,7 @@ class QuickTable(SimpleTable):
(index is not None and self._link[index])): (index is not None and self._link[index])):
objclass, handle = self._link[index] objclass, handle = self._link[index]
if objclass == 'Person': if objclass == 'Person':
menu_item = Gtk.MenuItem(label=_("the object|Make %s active") % trans_objclass('Person')) menu_item = Gtk.MenuItem(label=_("the object|Make %s active") % glocale.trans_objclass('Person'))
menu_item.connect("activate", menu_item.connect("activate",
lambda widget: self.on_table_click(treeview)) lambda widget: self.on_table_click(treeview))
popup.append(menu_item) popup.append(menu_item)

View File

@ -8,7 +8,7 @@
# the Free Software Foundation; either version 2 of the License, or # the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version. # (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
@ -29,15 +29,15 @@ Translator class for use by plugins.
# python modules # python modules
# #
#------------------------------------------------------------------------ #------------------------------------------------------------------------
import gettext
_ = gettext.gettext
from gramps.gen.const import GRAMPS_LOCALE as glocale
from gramps.gen.ggettext import gettext as _
#------------------------------------------------------------------------ #------------------------------------------------------------------------
# #
# GRAMPS modules # GRAMPS modules
# #
#------------------------------------------------------------------------ #------------------------------------------------------------------------
from gramps.gen.utils.grampslocale import get_localedomain from gramps.gen.const import GRAMPS_LOCALE as glocale
from gramps.gen.datehandler import displayer, LANG_TO_DISPLAY from gramps.gen.datehandler import displayer, LANG_TO_DISPLAY
from gramps.gen.config import config from gramps.gen.config import config
from gramps.gen.lib.grampstype import GrampsType from gramps.gen.lib.grampstype import GrampsType
@ -97,15 +97,15 @@ _COUNTRY_MAP = {
#------------------------------------------------------------------------ #------------------------------------------------------------------------
def get_language_string(lang_code): def get_language_string(lang_code):
""" """
Given a language code of the form "lang_region", return a text string Given a language code of the form "lang_region", return a text string
representing that language. representing that language.
""" """
code_parts = lang_code.rsplit("_") code_parts = lang_code.rsplit("_")
lang = code_parts[0] lang = code_parts[0]
if lang in _LANG_MAP: if lang in _LANG_MAP:
lang = _LANG_MAP[lang] lang = _LANG_MAP[lang]
if len(code_parts) > 1: if len(code_parts) > 1:
country = code_parts[1] country = code_parts[1]
if country in _COUNTRY_MAP: if country in _COUNTRY_MAP:
@ -114,7 +114,7 @@ def get_language_string(lang_code):
{ 'language' : lang, 'country' : country } { 'language' : lang, 'country' : country }
else: else:
retstr = lang retstr = lang
return retstr return retstr
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
@ -122,62 +122,57 @@ def get_language_string(lang_code):
# Translator # Translator
# #
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
class Translator: class Translator(object):
""" """
This class provides translated strings for the configured language. This class provides translated strings for the configured language.
""" """
DEFAULT_TRANSLATION_STR = "default" DEFAULT_TRANSLATION_STR = "default"
def __init__(self, lang=DEFAULT_TRANSLATION_STR): def __init__(self, lang=DEFAULT_TRANSLATION_STR):
""" """
:param lang: The language to translate to. :param lang: The language to translate to.
The language can be: The language can be:
* The name of any installed .mo file * The name of any installed .mo file
* "en" to use the message strings in the code * "en" to use the message strings in the code
* "default" to use the default translation being used by gettext. * "default" to use the default translation being used by gettext.
:type lang: string :type lang: string
:return: nothing :return: nothing
""" """
if lang == Translator.DEFAULT_TRANSLATION_STR: if lang == Translator.DEFAULT_TRANSLATION_STR:
self.__trans = None self.__trans = glocale.get_translation()
self.__dd = displayer self.__dd = displayer
else: else:
# fallback=True will cause the translator to use English if # If lang isn't supported, this will fallback to the
# lang = "en" or if something goes wrong. # current global language
self.__trans = gettext.translation(get_localedomain(), self.__trans = glocale.get_translation(languages=[lang])
languages=[lang],
fallback=True)
val = config.get('preferences.date-format') val = config.get('preferences.date-format')
if lang in LANG_TO_DISPLAY: if lang in LANG_TO_DISPLAY:
self.__dd = LANG_TO_DISPLAY[lang](val) self.__dd = LANG_TO_DISPLAY[lang](val)
else: else:
self.__dd = displayer self.__dd = displayer
def gettext(self, message): def gettext(self, message):
""" """
Return the unicode translated string. Return the unicode translated string.
:param message: The message to be translated. :param message: The message to be translated.
:type message: string :type message: string
:returns: The translated message :returns: The translated message
:rtype: unicode :rtype: unicode
""" """
if self.__trans is None: return self.__trans.gettext(message)
return cuni(gettext.gettext(message))
else:
return self.__trans.ugettext(message)
def ngettext(self, singular, plural, n): def ngettext(self, singular, plural, n):
""" """
Return the unicode translated singular/plural string. Return the unicode translated singular/plural string.
The translation of singular/plural is returned unless the translation is The translation of singular/plural is returned unless the translation is
not available and the singular contains the separator. In that case, not available and the singular contains the separator. In that case,
the returned value is the portion of singular following the last the returned value is the portion of singular following the last
separator. Default separator is '|'. separator. Default separator is '|'.
:param singular: The singular form of the string to be translated. :param singular: The singular form of the string to be translated.
may contain a context separator may contain a context separator
:type singular: unicode :type singular: unicode
@ -187,53 +182,49 @@ class Translator:
:type n: int :type n: int
:returns: The translated singular/plural message :returns: The translated singular/plural message
:rtype: unicode :rtype: unicode
""" """
if self.__trans is None: return self.__trans.ngettext(singular, plural, n)
return cuni(gettext.ngettext(singular, plural, n))
else:
return self.__trans.ungettext(singular, plural, n)
def sgettext(self, msgid, sep='|'): def sgettext(self, msgid, sep='|'):
""" """
Strip the context used for resolving translation ambiguities. Strip the context used for resolving translation ambiguities.
The translation of msgid is returned unless the translation is The translation of msgid is returned unless the translation is
not available and the msgid contains the separator. In that case, not available and the msgid contains the separator. In that case,
the returned value is the portion of msgid following the last the returned value is the portion of msgid following the last
separator. Default separator is '|'. separator. Default separator is '|'.
:param msgid: The string to translated. :param msgid: The string to translated.
:type msgid: unicode :type msgid: unicode
:param sep: The separator marking the context. :param sep: The separator marking the context.
:type sep: unicode :type sep: unicode
:returns: Translation or the original with context stripped. :returns: Translation or the original with context stripped.
:rtype: unicode :rtype: unicode
""" """
msgval = self.gettext(msgid) try:
if msgval == msgid: return self.__trans.sgettext(msgid)
sep_idx = msgid.rfind(sep) except AttributeError:
msgval = msgid[sep_idx+1:] return self.__trans.gettext(msgid)
return cuni(msgval)
def get_date(self, date): def get_date(self, date):
""" """
Return a string representing the date appropriate for the language being Return a string representing the date appropriate for the language being
translated. translated.
:param date: The date to be represented. :param date: The date to be represented.
:type date: :class:`~gen.lib.date.Date` :type date: :class:`~gen.lib.date.Date`
:returns: The date as text in the proper language. :returns: The date as text in the proper language.
:rtype: unicode :rtype: unicode
""" """
return self.__dd.display(date) return self.__dd.display(date)
def get_type(self, name): def get_type(self, name):
""" """
Return a string representing the name appropriate for the language being Return a string representing the name appropriate for the language being
translated. translated.
:param name: The name type to be represented. :param name: The name type to be represented.
:returns: The name as text in the proper language. :returns: The name as text in the proper language.
:rtype: unicode :rtype: unicode

View File

@ -39,6 +39,7 @@ from gramps.gen.ggettext import gettext as _
# gramps modules # gramps modules
# #
#------------------------------------------------------------------------ #------------------------------------------------------------------------
from gramps.gen.const import GRAMPS_LOCALE as glocale
from gramps.gen.display.name import displayer as global_name_display from gramps.gen.display.name import displayer as global_name_display
from gramps.gen.errors import ReportError from gramps.gen.errors import ReportError
from gramps.gen.lib import ChildRefType from gramps.gen.lib import ChildRefType
@ -50,7 +51,6 @@ from gramps.gen.plug.docgen import (IndexMark, FontStyle, ParagraphStyle,
from gramps.gen.plug.report import Report from gramps.gen.plug.report import Report
from gramps.gen.plug.report import utils as ReportUtils from gramps.gen.plug.report import utils as ReportUtils
from gramps.gen.plug.report import MenuReportOptions from gramps.gen.plug.report import MenuReportOptions
from gramps.gen.utils.grampslocale import get_available_translations
from gramps.plugins.lib.libnarrate import Narrator from gramps.plugins.lib.libnarrate import Narrator
from gramps.plugins.lib.libtranslate import Translator, get_language_string from gramps.plugins.lib.libtranslate import Translator, get_language_string
@ -299,7 +299,7 @@ class AncestorOptions(MenuReportOptions):
trans = EnumeratedListOption(_("Translation"), trans = EnumeratedListOption(_("Translation"),
Translator.DEFAULT_TRANSLATION_STR) Translator.DEFAULT_TRANSLATION_STR)
trans.add_item(Translator.DEFAULT_TRANSLATION_STR, _("Default")) trans.add_item(Translator.DEFAULT_TRANSLATION_STR, _("Default"))
for language in get_available_translations(): for language in glocale.get_available_translations():
trans.add_item(language, get_language_string(language)) trans.add_item(language, get_language_string(language))
trans.set_help(_("The translation to be used for the report.")) trans.set_help(_("The translation to be used for the report."))
menu.add_option(category_name, "trans", trans) menu.add_option(category_name, "trans", trans)

View File

@ -42,6 +42,7 @@ from gramps.gen.ggettext import gettext as _
# GRAMPS modules # GRAMPS modules
# #
#------------------------------------------------------------------------ #------------------------------------------------------------------------
from gramps.gen.const import GRAMPS_LOCALE as glocale
from gramps.gen.display.name import displayer as global_name_display from gramps.gen.display.name import displayer as global_name_display
from gramps.gen.errors import ReportError from gramps.gen.errors import ReportError
from gramps.gen.lib import EventType, FamilyRelType, Person, NoteType from gramps.gen.lib import EventType, FamilyRelType, Person, NoteType
@ -54,7 +55,6 @@ from gramps.gen.plug.report import endnotes
from gramps.gen.plug.report import utils as ReportUtils from gramps.gen.plug.report import utils as ReportUtils
from gramps.gen.plug.report import MenuReportOptions from gramps.gen.plug.report import MenuReportOptions
from gramps.plugins.lib.libnarrate import Narrator from gramps.plugins.lib.libnarrate import Narrator
from gramps.gen.utils.grampslocale import get_available_translations
from gramps.plugins.lib.libtranslate import Translator, get_language_string from gramps.plugins.lib.libtranslate import Translator, get_language_string
#------------------------------------------------------------------------ #------------------------------------------------------------------------
@ -753,7 +753,7 @@ class DetAncestorOptions(MenuReportOptions):
trans = EnumeratedListOption(_("Translation"), trans = EnumeratedListOption(_("Translation"),
Translator.DEFAULT_TRANSLATION_STR) Translator.DEFAULT_TRANSLATION_STR)
trans.add_item(Translator.DEFAULT_TRANSLATION_STR, _("Default")) trans.add_item(Translator.DEFAULT_TRANSLATION_STR, _("Default"))
for language in get_available_translations(): for language in glocale.get_available_translations():
trans.add_item(language, get_language_string(language)) trans.add_item(language, get_language_string(language))
trans.set_help(_("The translation to be used for the report.")) trans.set_help(_("The translation to be used for the report."))
addopt("trans", trans) addopt("trans", trans)

View File

@ -45,6 +45,7 @@ from functools import partial
# GRAMPS modules # GRAMPS modules
# #
#------------------------------------------------------------------------ #------------------------------------------------------------------------
from gramps.gen.const import GRAMPS_LOCALE as glocale
from gramps.gen.display.name import displayer as global_name_display from gramps.gen.display.name import displayer as global_name_display
from gramps.gen.errors import ReportError from gramps.gen.errors import ReportError
from gramps.gen.lib import FamilyRelType, Person, NoteType from gramps.gen.lib import FamilyRelType, Person, NoteType
@ -58,7 +59,6 @@ from gramps.gen.plug.report import endnotes
from gramps.gen.plug.report import utils as ReportUtils from gramps.gen.plug.report import utils as ReportUtils
from gramps.gen.plug.report import MenuReportOptions from gramps.gen.plug.report import MenuReportOptions
from gramps.plugins.lib.libnarrate import Narrator from gramps.plugins.lib.libnarrate import Narrator
from gramps.gen.utils.grampslocale import get_available_translations
from gramps.plugins.lib.libtranslate import Translator, get_language_string from gramps.plugins.lib.libtranslate import Translator, get_language_string
#------------------------------------------------------------------------ #------------------------------------------------------------------------
@ -928,7 +928,7 @@ class DetDescendantOptions(MenuReportOptions):
trans = EnumeratedListOption(_("Translation"), trans = EnumeratedListOption(_("Translation"),
Translator.DEFAULT_TRANSLATION_STR) Translator.DEFAULT_TRANSLATION_STR)
trans.add_item(Translator.DEFAULT_TRANSLATION_STR, _("Default")) trans.add_item(Translator.DEFAULT_TRANSLATION_STR, _("Default"))
for language in get_available_translations(): for language in glocale.get_available_translations():
trans.add_item(language, get_language_string(language)) trans.add_item(language, get_language_string(language))
trans.set_help(_("The translation to be used for the report.")) trans.set_help(_("The translation to be used for the report."))
add_option("trans", trans) add_option("trans", trans)