diff --git a/gramps/gen/db/read.py b/gramps/gen/db/read.py index edf5923c3..c96349d6f 100644 --- a/gramps/gen/db/read.py +++ b/gramps/gen/db/read.py @@ -40,7 +40,6 @@ else: import pickle import time import random -import locale import os from sys import maxsize @@ -81,6 +80,7 @@ from . import (BsddbBaseCursor, DbReadBase) from ..utils.id import create_id from ..errors import DbError from ..constfunc import UNITYPE, STRTYPE, cuni +from ..const import GRAMPS_LOCALE as glocale LOG = logging.getLogger(DBLOGNAME) LOG = logging.getLogger(".citation") @@ -1645,7 +1645,7 @@ class DbBsddbRead(DbReadBase, Callback): def __sortbyperson_key(self, handle): if isinstance(handle, UNITYPE): handle = handle.encode('utf-8') - return locale.strxfrm(find_surname(handle, + return glocale.sort_key(find_surname(handle, self.person_map.get(handle))) def __sortbyplace(self, first, second): @@ -1653,13 +1653,13 @@ class DbBsddbRead(DbReadBase, Callback): first = first.encode('utf-8') if isinstance(second, UNITYPE): second = second.encode('utf-8') - return locale.strcoll(self.place_map.get(first)[2], + return glocale.strcoll(self.place_map.get(first)[2], self.place_map.get(second)[2]) def __sortbyplace_key(self, place): if isinstance(place, UNITYPE): place = place.encode('utf-8') - return locale.strxfrm(self.place_map.get(place)[2]) + return glocale.sort_key(self.place_map.get(place)[2]) def __sortbysource(self, first, second): if isinstance(first, UNITYPE): @@ -1668,13 +1668,13 @@ class DbBsddbRead(DbReadBase, Callback): second = second.encode('utf-8') source1 = cuni(self.source_map[first][2]) source2 = cuni(self.source_map[second][2]) - return locale.strcoll(source1, source2) + return glocale.strcoll(source1, source2) def __sortbysource_key(self, key): if isinstance(key, UNITYPE): key = key.encode('utf-8') source = cuni(self.source_map[key][2]) - return locale.strxfrm(source) + return glocale.sort_key(source) def __sortbycitation(self, first, second): if isinstance(first, UNITYPE): @@ -1683,13 +1683,13 @@ class DbBsddbRead(DbReadBase, Callback): second = second.encode('utf-8') citation1 = cuni(self.citation_map[first][3]) citation2 = cuni(self.citation_map[second][3]) - return locale.strcoll(citation1, citation2) + return glocale.strcoll(citation1, citation2) def __sortbycitation_key(self, key): if isinstance(key, UNITYPE): key = key.encode('utf-8') citation = cuni(self.citation_map[key][3]) - return locale.strxfrm(citation) + return glocale.sort_key(citation) def __sortbymedia(self, first, second): if isinstance(first, UNITYPE): @@ -1698,13 +1698,13 @@ class DbBsddbRead(DbReadBase, Callback): second = second.encode('utf-8') media1 = self.media_map[first][4] media2 = self.media_map[second][4] - return locale.strcoll(media1, media2) + return glocale.strcoll(media1, media2) def __sortbymedia_key(self, key): if isinstance(key, UNITYPE): key = key.encode('utf-8') media = self.media_map[key][4] - return locale.strxfrm(media) + return glocale.sort_key(media) def __sortbytag(self, first, second): if isinstance(first, UNITYPE): @@ -1713,13 +1713,13 @@ class DbBsddbRead(DbReadBase, Callback): second = second.encode('utf-8') tag1 = self.tag_map[first][1] tag2 = self.tag_map[second][1] - return locale.strcoll(tag1, tag2) + return glocale.strcoll(tag1, tag2) def __sortbytag_key(self, key): if isinstance(key, UNITYPE): key = key.encode('utf-8') tag = self.tag_map[key][1] - return locale.strxfrm(tag) + return glocale.sort_key(tag) def set_mediapath(self, path): """Set the default media path for database, path should be utf-8.""" diff --git a/gramps/gen/db/write.py b/gramps/gen/db/write.py index aadd976fe..a3f12ff03 100644 --- a/gramps/gen/db/write.py +++ b/gramps/gen/db/write.py @@ -40,14 +40,11 @@ else: import pickle import os import time -import locale import bisect from functools import wraps import logging from sys import maxsize -from ..const import GRAMPS_LOCALE as glocale -_ = glocale.get_translation().gettext from ..config import config if config.get('preferences.use-bsddb3') or sys.version_info[0] >= 3: from bsddb3 import dbshelve, db @@ -78,10 +75,12 @@ from . import (DbBsddbRead, DbWriteBase, BSDDBTxn, find_byte_surname, find_surname_name, DbUndoBSDDB as DbUndo) from .dbconst import * from ..utils.callback import Callback -from ..utils.cast import (conv_unicode_tosrtkey, conv_dbstr_to_unicode) +from ..utils.cast import conv_dbstr_to_unicode from ..updatecallback import UpdateCallback from ..errors import DbError from ..constfunc import win, conv_to_unicode, cuni, UNITYPE, handle2internal +from ..const import GRAMPS_LOCALE as glocale +_ = glocale.get_translation().gettext _LOG = logging.getLogger(DBLOGNAME) LOG = logging.getLogger(".citation") @@ -1499,7 +1498,7 @@ class DbBsddb(DbBsddbRead, DbWriteBase, UpdateCallback): self.emit('person-groupname-rebuild', (name, grouppar)) def sort_surname_list(self): - self.surname_list.sort(key=conv_unicode_tosrtkey) + self.surname_list.sort(key=glocale.sort_key) @catch_db_error def build_surname_list(self): @@ -1511,7 +1510,7 @@ class DbBsddb(DbBsddbRead, DbWriteBase, UpdateCallback): #TODO GTK3: Why double conversion? Convert to a list of str objects! self.surname_list = sorted( map(conv_dbstr_to_unicode, set(self.surnames.keys())), - key=conv_unicode_tosrtkey) + key=glocale.sort_key) def add_to_surname_list(self, person, batch_transaction): """ diff --git a/gramps/gen/sort.py b/gramps/gen/sort.py index 14dd635f4..ceb3f9e2b 100644 --- a/gramps/gen/sort.py +++ b/gramps/gen/sort.py @@ -32,7 +32,6 @@ to make sure these remain in sync with the rest of the design. # Standard python modules # #------------------------------------------------------------------------- -import locale #------------------------------------------------------------------------- # @@ -42,6 +41,7 @@ import locale from .lib import Date from .utils.db import get_birth_or_fallback from .display.name import displayer as _nd +from .const import GRAMPS_LOCALE as glocale #------------------------------------------------------------------------- # @@ -70,11 +70,11 @@ class Sort(object): ## ffn = name1.get_first_name() ## sfn = name2.get_first_name() ## if ffn == sfn: -## return locale.strcoll(name1.get_suffix(), name2.get_suffix()) +## return glocale.strcoll(name1.get_suffix(), name2.get_suffix()) ## else: -## return locale.strcoll(ffn, sfn) +## return glocale.strcoll(ffn, sfn) ## else: -## return locale.strcoll(fsn, ssn) +## return glocale.strcoll(fsn, ssn) def by_last_name_key(self, first_id): """Sort routine for comparing two last names. If last names are equal, @@ -86,7 +86,7 @@ class Sort(object): fsn = name1.get_surname() ffn = name1.get_first_name() fsu = name1.get_suffix() - return locale.strxfrm(fsn + ffn + fsu) + return glocale.sort_key(fsn + ffn + fsu) ## def by_sorted_name(self, first_id, second_id): ## """ @@ -99,7 +99,7 @@ class Sort(object): ## name1 = _nd.sorted(first) ## name2 = _nd.sorted(second) ## -## return locale.strcoll(name1, name2) +## return glocale.strcoll(name1, name2) def by_sorted_name_key(self, first_id): """ @@ -110,7 +110,7 @@ class Sort(object): name1 = _nd.sorted(first) - return locale.strxfrm(name1) + return glocale.sort_key(name1) ## def by_birthdate(self, first_id, second_id): ## """Sort routine for comparing two people by birth dates. If the birth dates @@ -175,14 +175,14 @@ class Sort(object): ## return 0 ## a_obj = self.database.get_place_from_handle(a_id) ## b_obj = self.database.get_place_from_handle(b_id) -## return locale.strcoll(a_obj.title, b_obj.title) +## return glocale.strcoll(a_obj.title, b_obj.title) def by_place_title_key(self, a_id): """Sort routine for comparing two places. """ if not a_id: return 0 a_obj = self.database.get_place_from_handle(a_id) - return locale.strxfrm(a_obj.title) + return glocale.sort_key(a_obj.title) ## def by_event_place(self, a_id, b_id): ## """Sort routine for comparing two events by their places. """ @@ -198,7 +198,7 @@ class Sort(object): ## plc_a_title = plc_a.title ## if plc_b: ## plc_b_title = plc_b.title -## return locale.strcoll(plc_a_title, plc_b_title) +## return glocale.strcoll(plc_a_title, plc_b_title) def by_event_place_key(self, a_id): """Sort routine for comparing two events by their places. """ @@ -207,7 +207,7 @@ class Sort(object): evt_a = self.database.get_event_from_handle(a_id) plc_a = self.database.get_place_from_handle(evt_a.get_place_handle()) plc_a_title = plc_a.title if plc_a else "" - return locale.strxfrm(plc_a_title) + return glocale.sort_key(plc_a_title) ## def by_event_description(self, a_id, b_id): ## """Sort routine for comparing two events by their descriptions. """ @@ -215,14 +215,14 @@ class Sort(object): ## return 0 ## evt_a = self.database.get_event_from_handle(a_id) ## evt_b = self.database.get_event_from_handle(b_id) -## return locale.strcoll(evt_a.get_description(), evt_b.get_description()) +## return glocale.strcoll(evt_a.get_description(), evt_b.get_description()) def by_event_description_key(self, a_id): """Sort routine for comparing two events by their descriptions. """ if not a_id: return 0 evt_a = self.database.get_event_from_handle(a_id) - return locale.strxfrm(evt_a.get_description()) + return glocale.sort_key(evt_a.get_description()) ## def by_event_id(self, a_id, b_id): ## """Sort routine for comparing two events by their ID. """ @@ -230,14 +230,14 @@ class Sort(object): ## return 0 ## evt_a = self.database.get_event_from_handle(a_id) ## evt_b = self.database.get_event_from_handle(b_id) -## return locale.strcoll(evt_a.get_gramps_id(), evt_b.get_gramps_id()) +## return glocale.strcoll(evt_a.get_gramps_id(), evt_b.get_gramps_id()) def by_event_id_key(self, a_id): """Sort routine for comparing two events by their ID. """ if not a_id: return 0 evt_a = self.database.get_event_from_handle(a_id) - return locale.strxfrm(evt_a.get_gramps_id()) + return glocale.sort_key(evt_a.get_gramps_id()) ## def by_event_type(self, a_id, b_id): ## """Sort routine for comparing two events by their type. """ @@ -245,14 +245,14 @@ class Sort(object): ## return 0 ## evt_a = self.database.get_event_from_handle(a_id) ## evt_b = self.database.get_event_from_handle(b_id) -## return locale.strcoll(str(evt_a.get_type()), str(evt_b.get_type())) +## return glocale.strcoll(str(evt_a.get_type()), str(evt_b.get_type())) def by_event_type_key(self, a_id): """Sort routine for comparing two events by their type. """ if not a_id: return 0 evt_a = self.database.get_event_from_handle(a_id) - return locale.strxfrm(str(evt_a.get_type())) + return glocale.sort_key(str(evt_a.get_type())) ## def by_media_title(self,a_id,b_id): ## """Sort routine for comparing two media objects by their title. """ @@ -260,11 +260,11 @@ class Sort(object): ## return False ## a = self.database.get_object_from_handle(a_id) ## b = self.database.get_object_from_handle(b_id) -## return locale.strcoll(a.desc, b.desc) +## return glocale.strcoll(a.desc, b.desc) def by_media_title_key(self, a_id): """Sort routine for comparing two media objects by their title. """ if not a_id: return False a = self.database.get_object_from_handle(a_id) - return locale.strxfrm(a.desc) + return glocale.sort_key(a.desc) diff --git a/gramps/gen/utils/cast.py b/gramps/gen/utils/cast.py index f9e7fa1f8..75c5f2a9f 100644 --- a/gramps/gen/utils/cast.py +++ b/gramps/gen/utils/cast.py @@ -44,56 +44,6 @@ LOG = logging.getLogger(".") from ..datehandler import codeset from ..constfunc import conv_to_unicode, conv_to_unicode_direct, UNITYPE, STRTYPE -try: - import PyICU - if os.environ.has_key("LC_COLLATE"): - collation = os.environ['LC_COLLATE'] - else: - collation = os.environ["LANG"] - language_and_country = collation.rsplit('.', 1)[0] - if language_and_country in PyICU.Collator.getAvailableLocales().keys(): - loc = language_and_country - else: - language = collation.rsplit('_', 1)[0] - if language in PyICU.Collator.getAvailableLocales().keys(): - LOG.warn(_("Language and country %s not supported by ICU: " - "but language %s is supported and will be used" % - (language_and_country, language))) - loc = language - else: - LOG.warn(_("Neither Language and country %s nor language %s " - "supported by ICU: using en_GB" % - (language_and_country, language))) - loc = "en_GB" - - collator = PyICU.Collator.createInstance(PyICU.Locale(loc)) - # on ICU, the functions need to receive unicode - conv_unicode_tosrtkey = lambda x: collator.getCollationKey( - x).getByteArray() - conv_str_tosrtkey = lambda x: collator.getCollationKey( - x.decode("UTF-8")).getByteArray() -except: - """ - strxfrm needs it's unicode argument correctly cast before used. - """ - if sys.version_info[0] < 3: - conv_unicode_tosrtkey = lambda x: locale.strxfrm(x.encode(codeset, 'replace')) - else: - conv_unicode_tosrtkey = lambda x: locale.strxfrm(x) - - if codeset == 'UTF-8': - conv_str_tosrtkey = lambda x: locale.strxfrm(x) - else: - conv_str_tosrtkey = lambda x: locale.strxfrm( - conv_to_unicode(x,'UTF-8').encode(codeset, 'replace')) - -def conv_tosrtkey(value): - if isinstance(value, UNITYPE): - return conv_unicode_tosrtkey(value) - elif not isinstance(value, STRTYPE): - return conv_str_tosrtkey(str(value)) - return conv_str_tosrtkey(value) - #strings in database are utf-8 conv_dbstr_to_unicode = lambda x: conv_to_unicode(x, 'UTF-8') diff --git a/gramps/gen/utils/grampslocale.py b/gramps/gen/utils/grampslocale.py index 4d4b409c4..4ad53c275 100644 --- a/gramps/gen/utils/grampslocale.py +++ b/gramps/gen/utils/grampslocale.py @@ -32,6 +32,13 @@ import os import locale import logging LOG = logging.getLogger("gramps.gen.util.grampslocale") +LOG.addHandler(logging.StreamHandler()) +HAVE_ICU = False +try: + from icu import Locale, Collator + HAVE_ICU = True +except ImportError as err: + LOG.warning("ICU is not installed because %s, localization will be impaired", str(err)) #------------------------------------------------------------------------- # # gramps modules @@ -239,6 +246,19 @@ class GrampsLocale(object): if len(self.language) == 0: self.language = self._GrampsLocale__first_instance.language + self.icu_locales = {} + self.collator = None + if HAVE_ICU: + self.icu_locales["default"] = Locale.createFromName(self.lang) + if self.collation != self.lang: + self.icu_locales["collation"] = Locale.createFromName(self.collation) + else: + self.icu_locales["collation"] = self.icu_locales["default"] + try: + self.collator = Collator.createInstance(self.icu_locales["collation"]) + except ICUError as err: + LOG.warning("Unable to create collator: %s", str(err)) + self.collator = None self.translation = self._get_translation(self.localedomain, self.localedir, self.language) @@ -513,6 +533,36 @@ class GrampsLocale(object): return "utf-8" + def sort_key(self, string): + """ + Return a value suitable to pass to the "key" parameter of sorted() + """ + + if HAVE_ICU and self.collator: + #ICU can digest strings and unicode + return self.collator.getCollationKey(string).getByteArray() + else: + base_locale = locale.getlocale(locale.LC_COLLATE) + locale.setlocale(locale.LC_COLLATE, self.collation) + #locale in Python2 can't. + if sys.version_info[0] < 3 and isinstance(string, unicode): + key = locale.strxfrm(string.encode("utf-8", "replace")) + else: + key = locale.strxfrm(string) + + locale.setlocale(locale.LC_COLLATE, base_locale) + return key + + def strcoll(self, string1, string2): + """ + Given two localized strings, compare them and return -1 if + string1 would sort first, 1 if string2 would, and 0 if + they are the same. + """ + key1 = self.sort_key(string1) + key2 = self.sort_key(string2) + return (-1 if key1 < key2 else (1 if key1 > key2 else 0)) + #------------------------------------------------------------------------- # # Translations Classes diff --git a/gramps/gui/autocomp.py b/gramps/gui/autocomp.py index 7dacdd6ca..200d3ccbb 100644 --- a/gramps/gui/autocomp.py +++ b/gramps/gui/autocomp.py @@ -31,8 +31,6 @@ Provide autocompletion functionality. #------------------------------------------------------------------------- from __future__ import print_function -import locale - #------------------------------------------------------------------------- # # GNOME modules @@ -41,8 +39,8 @@ import locale from gi.repository import Gtk from gi.repository import GObject - from gramps.gen.constfunc import STRTYPE +from gramps.gen.const import GRAMPS_LOCALE as glocale def fill_combo(combo, data_list): """ @@ -194,7 +192,7 @@ class StandardCustomSelector(object): """ Method for sorting keys based on the values. """ - return locale.strxfrm(self.mapping[val]) + return glocale.sort_key(self.mapping[val]) def get_values(self): """ diff --git a/gramps/gui/editors/displaytabs/surnametab.py b/gramps/gui/editors/displaytabs/surnametab.py index c36954755..93da8fd99 100644 --- a/gramps/gui/editors/displaytabs/surnametab.py +++ b/gramps/gui/editors/displaytabs/surnametab.py @@ -28,7 +28,6 @@ #------------------------------------------------------------------------- from gramps.gen.const import GRAMPS_LOCALE as glocale _ = glocale.get_translation().sgettext -import locale #------------------------------------------------------------------------- # @@ -116,7 +115,7 @@ class SurnameTab(EmbeddedList): self.cmborig = Gtk.ListStore(GObject.TYPE_INT, GObject.TYPE_STRING) self.cmborigmap = no.get_map().copy() #sort the keys based on the value - keys = sorted(self.cmborigmap, key=lambda x: locale.strxfrm(self.cmborigmap[x])) + keys = sorted(self.cmborigmap, key=lambda x: glocale.sort_key(self.cmborigmap[x])) for key in keys: if key != no.get_custom(): self.cmborig.append(row=[key, self.cmborigmap[key]]) @@ -162,7 +161,7 @@ class SurnameTab(EmbeddedList): ## """ ## fvalue = self.cmborigmap[first] ## svalue = self.cmborigmap[second] -## return locale.strcoll(fvalue, svalue) +## return glocale.strcoll(fvalue, svalue) def get_data(self): return self.obj.get_surname_list() diff --git a/gramps/gui/editors/filtereditor.py b/gramps/gui/editors/filtereditor.py index 9e963d5bd..68187183f 100644 --- a/gramps/gui/editors/filtereditor.py +++ b/gramps/gui/editors/filtereditor.py @@ -30,7 +30,6 @@ Custom Filter Editor tool. # Python modules # #------------------------------------------------------------------------- -import locale #------------------------------------------------------------------------ # @@ -903,7 +902,7 @@ class ShowResults(ManagedWindow): new_list = sorted( (self.sort_val_from_handle(h) for h in handle_list), - key=lambda x: locale.strxfrm(x[0]) + key=lambda x: glocale.sort_key(x[0]) ) for s_, handle in new_list: diff --git a/gramps/gui/views/treemodels/citationbasemodel.py b/gramps/gui/views/treemodels/citationbasemodel.py index 37c5e8d99..0386d6651 100644 --- a/gramps/gui/views/treemodels/citationbasemodel.py +++ b/gramps/gui/views/treemodels/citationbasemodel.py @@ -33,7 +33,6 @@ import cgi import logging log = logging.getLogger(".") LOG = logging.getLogger(".citation") -import locale #------------------------------------------------------------------------- # @@ -45,6 +44,7 @@ from gramps.gen.lib import Citation from gramps.gen.utils.string import confidence from gramps.gen.config import config from gramps.gen.constfunc import cuni +from gramps.gen.const import GRAMPS_LOCALE as glocale #------------------------------------------------------------------------- # @@ -130,7 +130,7 @@ class CitationBaseModel(object): Return the sorted list of tags. """ tag_list = list(map(self.get_tag_name, data[COLUMN_TAGS])) - return ', '.join(sorted(tag_list, key=locale.strxfrm)) + return ', '.join(sorted(tag_list, key=glocale.sort_key)) def citation_tag_color(self, data): """ @@ -213,7 +213,7 @@ class CitationBaseModel(object): try: source = self.db.get_source_from_handle(source_handle) tag_list = list(map(self.get_tag_name, source.get_tag_list())) - return ', '.join(sorted(tag_list, key=locale.strxfrm)) + return ', '.join(sorted(tag_list, key=glocale.sort_key)) except: return '' @@ -254,7 +254,7 @@ class CitationBaseModel(object): Return the sorted list of tags. """ tag_list = list(map(self.get_tag_name, data[COLUMN2_TAGS])) - return ', '.join(sorted(tag_list, key=locale.strxfrm)) + return ', '.join(sorted(tag_list, key=glocale.sort_key)) def source_src_tag_color(self, data): """ diff --git a/gramps/gui/views/treemodels/eventmodel.py b/gramps/gui/views/treemodels/eventmodel.py index 5218dc144..ac92e5409 100644 --- a/gramps/gui/views/treemodels/eventmodel.py +++ b/gramps/gui/views/treemodels/eventmodel.py @@ -27,7 +27,6 @@ import cgi import logging log = logging.getLogger(".") -import locale #------------------------------------------------------------------------- # @@ -47,6 +46,7 @@ from gramps.gen.utils.db import get_participant_from_event from gramps.gen.config import config from gramps.gen.constfunc import cuni from .flatbasemodel import FlatBaseModel +from gramps.gen.const import GRAMPS_LOCALE as glocale #------------------------------------------------------------------------- # @@ -206,4 +206,4 @@ class EventModel(FlatBaseModel): Return the sorted list of tags. """ tag_list = list(map(self.get_tag_name, data[COLUMN_TAGS])) - return ', '.join(sorted(tag_list, key=locale.strxfrm)) + return ', '.join(sorted(tag_list, key=glocale.sort_key)) diff --git a/gramps/gui/views/treemodels/familymodel.py b/gramps/gui/views/treemodels/familymodel.py index 9d658ca66..dcfa42d59 100644 --- a/gramps/gui/views/treemodels/familymodel.py +++ b/gramps/gui/views/treemodels/familymodel.py @@ -27,7 +27,6 @@ #------------------------------------------------------------------------- import logging log = logging.getLogger(".") -import locale #------------------------------------------------------------------------- # @@ -48,6 +47,7 @@ from .flatbasemodel import FlatBaseModel from gramps.gen.utils.db import get_marriage_or_fallback from gramps.gen.config import config from gramps.gen.constfunc import cuni +from gramps.gen.const import GRAMPS_LOCALE as glocale invalid_date_format = config.get('preferences.invalid-date-format') @@ -200,4 +200,4 @@ class FamilyModel(FlatBaseModel): Return the sorted list of tags. """ tag_list = list(map(self.get_tag_name, data[13])) - return ', '.join(sorted(tag_list, key=locale.strxfrm)) + return ', '.join(sorted(tag_list, key=glocale.sort_key)) diff --git a/gramps/gui/views/treemodels/flatbasemodel.py b/gramps/gui/views/treemodels/flatbasemodel.py index 0bf1993da..8551426d8 100644 --- a/gramps/gui/views/treemodels/flatbasemodel.py +++ b/gramps/gui/views/treemodels/flatbasemodel.py @@ -75,9 +75,9 @@ from gi.repository import Gtk # #------------------------------------------------------------------------- from gramps.gen.filters import SearchFilter, ExactSearchFilter -from gramps.gen.utils.cast import conv_unicode_tosrtkey, conv_tosrtkey from gramps.gen.constfunc import cuni, UNITYPE, conv_to_unicode, handle2internal - +from gramps.gen.const import GRAMPS_LOCALE as glocale + #------------------------------------------------------------------------- # # FlatNodeMap @@ -112,7 +112,7 @@ class FlatNodeMap(object): the path, and a dictionary mapping hndl to index. To obtain index given a path, method real_index() is available - ..Note: conv_unicode_tosrtkey is applied to the underlying sort key, + ..Note: glocale.sort_key is applied to the underlying sort key, so as to have localized sort """ @@ -456,7 +456,7 @@ class FlatBaseModel(GObject.Object, Gtk.TreeModel): """ The base class for all flat treeview models. It keeps a FlatNodeMap, and obtains data from database as needed - ..Note: conv_unicode_tosrtkey is applied to the underlying sort key, + ..Note: glocale.sort_key is applied to the underlying sort key, so as to have localized sort """ @@ -482,7 +482,7 @@ class FlatBaseModel(GObject.Object, Gtk.TreeModel): col = self.sort_map[scol][1] else: col = scol - self.sort_func = lambda x: conv_unicode_tosrtkey(self.smap[col](x)) + self.sort_func = lambda x: glocale.sort_key(self.smap[col](x)) self.sort_col = scol self.skip = skip self._in_build = False diff --git a/gramps/gui/views/treemodels/mediamodel.py b/gramps/gui/views/treemodels/mediamodel.py index f4cc84098..a7e0306a9 100644 --- a/gramps/gui/views/treemodels/mediamodel.py +++ b/gramps/gui/views/treemodels/mediamodel.py @@ -29,7 +29,6 @@ from gramps.gen.const import GRAMPS_LOCALE as glocale _ = glocale.get_translation().gettext import logging log = logging.getLogger(".") -import locale #------------------------------------------------------------------------- # @@ -46,6 +45,7 @@ from gi.repository import Gtk from gramps.gen.datehandler import displayer, format_time from gramps.gen.lib import Date, MediaObject from gramps.gen.constfunc import cuni, conv_to_unicode, UNITYPE +from gramps.gen.const import GRAMPS_LOCALE as glocale from .flatbasemodel import FlatBaseModel #------------------------------------------------------------------------- @@ -196,4 +196,4 @@ class MediaModel(FlatBaseModel): Return the sorted list of tags. """ tag_list = list(map(self.get_tag_name, data[10])) - return ', '.join(sorted(tag_list, key=locale.strxfrm)) + return ', '.join(sorted(tag_list, key=glocale.sort_key)) diff --git a/gramps/gui/views/treemodels/notemodel.py b/gramps/gui/views/treemodels/notemodel.py index 29290537f..0188beb29 100644 --- a/gramps/gui/views/treemodels/notemodel.py +++ b/gramps/gui/views/treemodels/notemodel.py @@ -27,7 +27,6 @@ #------------------------------------------------------------------------- import logging _LOG = logging.getLogger(".gui.notemodel") -import locale #------------------------------------------------------------------------- # @@ -43,6 +42,7 @@ from gi.repository import Gtk #------------------------------------------------------------------------- from gramps.gen.datehandler import format_time from gramps.gen.constfunc import cuni +from gramps.gen.const import GRAMPS_LOCALE as glocale from .flatbasemodel import FlatBaseModel from gramps.gen.lib import (Note, NoteType, StyledText) @@ -161,4 +161,4 @@ class NoteModel(FlatBaseModel): Return the sorted list of tags. """ tag_list = list(map(self.get_tag_name, data[Note.POS_TAGS])) - return ', '.join(sorted(tag_list, key=locale.strxfrm)) + return ', '.join(sorted(tag_list, key=glocale.sort_key)) diff --git a/gramps/gui/views/treemodels/peoplemodel.py b/gramps/gui/views/treemodels/peoplemodel.py index 9b7228dc3..1948312be 100644 --- a/gramps/gui/views/treemodels/peoplemodel.py +++ b/gramps/gui/views/treemodels/peoplemodel.py @@ -33,7 +33,6 @@ TreeModel for the GRAMPS Person tree. # #------------------------------------------------------------------------- import cgi -import locale #------------------------------------------------------------------------- # @@ -65,6 +64,7 @@ from .flatbasemodel import FlatBaseModel from .treebasemodel import TreeBaseModel from gramps.gen.config import config from gramps.gen.constfunc import cuni, UNITYPE +from gramps.gen.const import GRAMPS_LOCALE as glocale #------------------------------------------------------------------------- # @@ -460,7 +460,7 @@ class PeopleBaseModel(object): Return the sorted list of tags. """ tag_list = list(map(self.get_tag_name, data[COLUMN_TAGS])) - return ', '.join(sorted(tag_list, key=locale.strxfrm)) + return ', '.join(sorted(tag_list, key=glocale.sort_key)) class PersonListModel(PeopleBaseModel, FlatBaseModel): """ diff --git a/gramps/gui/views/treemodels/placemodel.py b/gramps/gui/views/treemodels/placemodel.py index 2928ea846..c0523e6d3 100644 --- a/gramps/gui/views/treemodels/placemodel.py +++ b/gramps/gui/views/treemodels/placemodel.py @@ -33,7 +33,6 @@ Place Model. import cgi import logging _LOG = logging.getLogger(".gui.views.treemodels.placemodel") -import locale #------------------------------------------------------------------------- # @@ -264,7 +263,7 @@ class PlaceBaseModel(object): Return the sorted list of tags. """ tag_list = list(map(self.get_tag_name, data[12])) - return ', '.join(sorted(tag_list, key=locale.strxfrm)) + return ', '.join(sorted(tag_list, key=glocale.sort_key)) #------------------------------------------------------------------------- # diff --git a/gramps/gui/views/treemodels/repomodel.py b/gramps/gui/views/treemodels/repomodel.py index dd37dbf87..27fbf8a72 100644 --- a/gramps/gui/views/treemodels/repomodel.py +++ b/gramps/gui/views/treemodels/repomodel.py @@ -26,7 +26,6 @@ #------------------------------------------------------------------------- import logging log = logging.getLogger(".") -import locale #------------------------------------------------------------------------- # @@ -44,7 +43,7 @@ from gramps.gen.lib import Address, RepositoryType, Url, UrlType from gramps.gen.datehandler import format_time from gramps.gen.constfunc import cuni from .flatbasemodel import FlatBaseModel - +from gramps.gen.const import GRAMPS_LOCALE as glocale #------------------------------------------------------------------------- # # RepositoryModel @@ -264,4 +263,4 @@ class RepositoryModel(FlatBaseModel): Return the sorted list of tags. """ tag_list = list(map(self.get_tag_name, data[8])) - return ', '.join(sorted(tag_list, key=locale.strxfrm)) + return ', '.join(sorted(tag_list, key=glocale.sort_key)) diff --git a/gramps/gui/views/treemodels/sourcemodel.py b/gramps/gui/views/treemodels/sourcemodel.py index 52d34e980..569cfebf0 100644 --- a/gramps/gui/views/treemodels/sourcemodel.py +++ b/gramps/gui/views/treemodels/sourcemodel.py @@ -26,7 +26,6 @@ #------------------------------------------------------------------------- import logging log = logging.getLogger(".") -import locale #------------------------------------------------------------------------- # @@ -43,6 +42,7 @@ from gi.repository import Gtk from gramps.gen.datehandler import format_time from gramps.gen.constfunc import cuni from .flatbasemodel import FlatBaseModel +from gramps.gen.const import GRAMPS_LOCALE as glocale #------------------------------------------------------------------------- # @@ -154,4 +154,4 @@ class SourceModel(FlatBaseModel): Return the sorted list of tags. """ tag_list = list(map(self.get_tag_name, data[11])) - return ', '.join(sorted(tag_list, key=locale.strxfrm)) + return ', '.join(sorted(tag_list, key=glocale.sort_key)) diff --git a/gramps/gui/views/treemodels/treebasemodel.py b/gramps/gui/views/treemodels/treebasemodel.py index daa943e83..71db3b19a 100644 --- a/gramps/gui/views/treemodels/treebasemodel.py +++ b/gramps/gui/views/treemodels/treebasemodel.py @@ -57,7 +57,7 @@ from gi.repository import Gtk # GRAMPS modules # #------------------------------------------------------------------------- -from gramps.gen.utils.cast import conv_str_tosrtkey, conv_unicode_tosrtkey +from gramps.gen.const import GRAMPS_LOCALE as glocale import gramps.gui.widgets.progressdialog as progressdlg from gramps.gen.constfunc import cuni, UNITYPE from .lru import LRU @@ -91,17 +91,9 @@ class Node(object): def __init__(self, ref, parent, sortkey, handle, secondary): if sortkey: - if isinstance(sortkey, UNITYPE): - self.name = sortkey - #sortkey must be localized sort, so - self.sortkey = conv_unicode_tosrtkey(sortkey) - else: - self.name = sortkey.decode('utf-8') - #sortkey must be localized sort, so - if sys.version_info[0] < 3: - self.sortkey = conv_str_tosrtkey(sortkey) - else: - self.sortkey = conv_unicode_tosrtkey(self.name) + self.name = sortkey + #sortkey must be localized sort, so + self.sortkey = glocale.sort_key(sortkey) else: self.name = '' self.sortkey = '' diff --git a/gramps/gui/widgets/monitoredwidgets.py b/gramps/gui/widgets/monitoredwidgets.py index 643e5fb72..0aec13ae3 100644 --- a/gramps/gui/widgets/monitoredwidgets.py +++ b/gramps/gui/widgets/monitoredwidgets.py @@ -34,7 +34,6 @@ __all__ = ["MonitoredCheckbox", "MonitoredEntry", #------------------------------------------------------------------------- import logging _LOG = logging.getLogger(".widgets.monitoredwidgets") -import locale import sys #------------------------------------------------------------------------- @@ -749,13 +748,13 @@ class MonitoredComboSelectedEntry(object): """ fvalue = self.mapping[first] svalue = self.mapping[second] - return locale.strcoll(fvalue, svalue) + return glocale.strcoll(fvalue, svalue) def __by_value_key(self, first): """ Method for sorting keys based on the values. """ - return locale.strxfrm(self.mapping[first]) + return glocale.sort_key(self.mapping[first]) def on_combochange(self, obj): """ diff --git a/gramps/plugins/lib/libgrdb.py b/gramps/plugins/lib/libgrdb.py index 0a7944199..470c9e826 100644 --- a/gramps/plugins/lib/libgrdb.py +++ b/gramps/plugins/lib/libgrdb.py @@ -37,7 +37,6 @@ else: import pickle import time import random -import locale import os from sys import maxsize from gramps.gen.config import config @@ -60,6 +59,7 @@ from gramps.gen.lib import (MediaObject, Person, Family, Source, Event, Place, Repository, Note, GenderStats, Researcher) from gramps.gen.utils.callback import Callback from gramps.gen.constfunc import STRTYPE, cuni +from gramps.gen.const import GRAMPS_LOCALE as glocale #------------------------------------------------------------------------- # @@ -1888,7 +1888,7 @@ class DbGrdb(Callback): raise NotImplementedError def sort_surname_list(self): - self.surname_list.sort(key=locale.strxfrm) + self.surname_list.sort(key=glocale.sort_key) def add_to_surname_list(self, person, batch_transaction): if batch_transaction: @@ -2267,29 +2267,29 @@ class DbGrdb(Callback): return str(handle) in self.note_map def __sortbyplace(self, first, second): - return locale.strcoll(self.place_map.get(str(first))[2], + return glocale.strcoll(self.place_map.get(str(first))[2], self.place_map.get(str(second))[2]) def __sortbyplace_key(self, place): - return locale.strxfrm(self.place_map.get(str(place))[2]) + return glocale.sort_key(self.place_map.get(str(place))[2]) def __sortbysource(self, first, second): source1 = cuni(self.source_map[str(first)][2]) source2 = cuni(self.source_map[str(second)][2]) - return locale.strcoll(source1, source2) + return glocale.strcoll(source1, source2) def __sortbysource_key(self, key): source = cuni(self.source_map[str(key)][2]) - return locale.strxfrm(source) + return glocale.sort_key(source) def __sortbymedia(self, first, second): media1 = self.media_map[str(first)][4] media2 = self.media_map[str(second)][4] - return locale.strcoll(media1, media2) + return glocale.strcoll(media1, media2) def __sortbymedia_key(self, key): media = self.media_map[str(key)][4] - return locale.strxfrm(media) + return glocale.sort_key(media) def set_mediapath(self, path): """Set the default media path for database, path should be utf-8.""" diff --git a/gramps/plugins/textreport/ancestorreport.py b/gramps/plugins/textreport/ancestorreport.py index c5ea761dc..089459b16 100644 --- a/gramps/plugins/textreport/ancestorreport.py +++ b/gramps/plugins/textreport/ancestorreport.py @@ -301,7 +301,7 @@ class AncestorOptions(MenuReportOptions): Translator.DEFAULT_TRANSLATION_STR) trans.add_item(Translator.DEFAULT_TRANSLATION_STR, _("Default")) languages = glocale.get_language_dict() - for language in sorted(languages): + for language in sorted(languages, key=glocale.sort_key): trans.add_item(languages[language], language) trans.set_help(_("The translation to be used for the report.")) menu.add_option(category_name, "trans", trans) diff --git a/gramps/plugins/textreport/detancestralreport.py b/gramps/plugins/textreport/detancestralreport.py index 0d1e51040..b5291b2de 100644 --- a/gramps/plugins/textreport/detancestralreport.py +++ b/gramps/plugins/textreport/detancestralreport.py @@ -755,7 +755,7 @@ class DetAncestorOptions(MenuReportOptions): Translator.DEFAULT_TRANSLATION_STR) trans.add_item(Translator.DEFAULT_TRANSLATION_STR, _("Default")) languages = glocale.get_language_dict() - for language in sorted(languages): + for language in sorted(languages, key=glocale.sort_key): trans.add_item(languages[language], language) trans.set_help(_("The translation to be used for the report.")) addopt("trans", trans) diff --git a/gramps/plugins/textreport/detdescendantreport.py b/gramps/plugins/textreport/detdescendantreport.py index 160028270..b536737aa 100644 --- a/gramps/plugins/textreport/detdescendantreport.py +++ b/gramps/plugins/textreport/detdescendantreport.py @@ -930,7 +930,7 @@ class DetDescendantOptions(MenuReportOptions): Translator.DEFAULT_TRANSLATION_STR) trans.add_item(Translator.DEFAULT_TRANSLATION_STR, _("Default")) languages = glocale.get_language_dict() - for language in sorted(languages): + for language in sorted(languages, key=glocale.sort_key): trans.add_item(languages[language], language) trans.set_help(_("The translation to be used for the report.")) add_option("trans", trans) diff --git a/gramps/plugins/tool/changetypes.py b/gramps/plugins/tool/changetypes.py index 20f06a7f2..20365749e 100644 --- a/gramps/plugins/tool/changetypes.py +++ b/gramps/plugins/tool/changetypes.py @@ -31,16 +31,14 @@ #------------------------------------------------------------------------ from __future__ import print_function -from gramps.gen.const import GRAMPS_LOCALE as glocale -_ = glocale.get_translation().gettext - #------------------------------------------------------------------------ # # GRAMPS modules # #------------------------------------------------------------------------ from gramps.gui.utils import ProgressMeter -import locale +from gramps.gen.const import GRAMPS_LOCALE as glocale +_ = glocale.get_translation().gettext from gramps.gui.managedwindow import ManagedWindow from gramps.gui.autocomp import fill_combo from gramps.gen.lib import EventType @@ -80,7 +78,7 @@ class ChangeTypes(tool.BatchTool, ManagedWindow): # Need to display localized event names etype = EventType() - event_names = sorted(etype.get_standard_names(), key=locale.strxfrm) + event_names = sorted(etype.get_standard_names(), key=glocale.sort_key) fill_combo(self.auto1,event_names) fill_combo(self.auto2,event_names) diff --git a/gramps/plugins/tool/notrelated.py b/gramps/plugins/tool/notrelated.py index e1e799abe..18ea718ab 100644 --- a/gramps/plugins/tool/notrelated.py +++ b/gramps/plugins/tool/notrelated.py @@ -25,13 +25,6 @@ "Find people who are not related to the selected person" -#------------------------------------------------------------------------ -# -# Python modules -# -#------------------------------------------------------------------------ -import locale - #------------------------------------------------------------------------ # # GNOME/GTK modules @@ -472,7 +465,7 @@ class NotRelated(tool.ActivePersonTool, ManagedWindow) : for handle in person.get_tag_list(): tag = self.db.get_tag_from_handle(handle) tags.append(tag.get_name()) - tags.sort(key=locale.strxfrm) + tags.sort(key=glocale.sort_key) return ', '.join(tags) #------------------------------------------------------------------------ diff --git a/gramps/plugins/webreport/narrativeweb.py b/gramps/plugins/webreport/narrativeweb.py index 8608b318f..6e1ea9412 100644 --- a/gramps/plugins/webreport/narrativeweb.py +++ b/gramps/plugins/webreport/narrativeweb.py @@ -79,7 +79,6 @@ try: except ImportError: from md5 import md5 import time, datetime -import locale import shutil import io import codecs @@ -122,12 +121,11 @@ from gramps.gen.plug.menu import PersonOption, NumberOption, StringOption, \ from gramps.gen.plug.report import ( Report, Bibliography) from gramps.gen.plug.report import utils as ReportUtils from gramps.gen.plug.report import MenuReportOptions - + from gramps.gen.utils.config import get_researcher from gramps.gen.utils.string import confidence from gramps.gen.utils.file import media_path_full from gramps.gen.utils.db import get_source_and_citation_referents -from gramps.gen.utils.cast import conv_unicode_tosrtkey, conv_tosrtkey from gramps.gen.constfunc import win, cuni, conv_to_unicode, UNITYPE from gramps.gui.thumbnails import get_thumbnail_path, run_thumbnailer from gramps.gen.utils.image import image_size, resize_to_jpeg_buffer @@ -2415,7 +2413,7 @@ class BasePage(object): ordered = Html("ol") section += ordered - sortlist = sorted(handlelist, key=lambda x:locale.strxfrm(x[1])) + sortlist = sorted(handlelist, key=lambda x:glocale.sort_key(x[1])) for (path, name, gid) in sortlist: list = Html("li") @@ -3966,7 +3964,7 @@ class SurnameListPage(BasePage): temp_list[index_val] = (surname, data_list) ppl_handle_list = (temp_list[key] - for key in sorted(temp_list, key = locale.strxfrm)) + for key in sorted(temp_list, key = glocale.sort_key)) last_letter = '' last_surname = '' @@ -4175,7 +4173,7 @@ class SourcePages(BasePage): key = source.get_title() + str(source.get_gramps_id()) source_dict[key] = (source, handle) - keys = sorted(source_dict, key=locale.strxfrm) + keys = sorted(source_dict, key=glocale.sort_key) msg = _("This page contains an index of all the sources in the " "database, sorted by their title. Clicking on a source’s " @@ -6523,7 +6521,7 @@ class RepositoryPages(BasePage): key = repository.get_name() + str(repository.get_gramps_id()) repos_dict[key] = (repository, repository_handle) - keys = sorted(repos_dict, key = locale.strxfrm) + keys = sorted(repos_dict, key = glocale.sort_key) # RepositoryListPage Class self.RepositoryListPage(self.report, title, repos_dict, keys) @@ -8482,14 +8480,14 @@ def sort_people(dbase, handle_list): sorted_lists = [] # According to the comment in flatbasemodel: This list is sorted - # ascending, via localized string sort. conv_unicode_tosrtkey which + # ascending, via localized string sort. glocale.sort_key which # uses strxfrm, which is apparently broken in Win ?? --> they should fix # base lib, we need strxfrm, fix it in the Utils module. - temp_list = sorted(sname_sub, key=conv_unicode_tosrtkey) + temp_list = sorted(sname_sub, key=glocale.sort_key) for name in temp_list: slist = sorted(((sortnames[x], x) for x in sname_sub[name]), - key=lambda x:conv_unicode_tosrtkey(x[0])) + key=lambda x:glocale.sort_key(x[0])) entries = [x[1] for x in slist] sorted_lists.append((name, entries)) @@ -8622,7 +8620,7 @@ def alphabet_navigation(menu_set): sorted_set[menu_item] += 1 # remove the number of each occurance of each letter - sorted_alpha_index = sorted(sorted_set, key = locale.strxfrm) + sorted_alpha_index = sorted(sorted_set, key = glocale.sort_key) # if no letters, return None to its callers if not sorted_alpha_index: