Meinert Jordan has proposed merging lp:~m2j/openlp/i18n into lp:openlp. Requested reviews: Tim Bentley (trb143)
For more details, see: https://code.launchpad.net/~m2j/openlp/i18n/+merge/88937 I've enabled translation of bible references. Some replacement hypens should are introduced. (reopened Bug #687638) locale.strcoll does not work correct on Windows with utf-8 [http://sgehrig.wordpress.com/2008/12/08/update-on-strcoll-utf-8-issue/]. The performance ICU is similar to locale.strcoll on Linux (12% faster for a English word list, 10% slower on a German one) ICU is said to give better results and makes less cross platform troubles. It is optional, but I suggest to include it in Windows builds. -- https://code.launchpad.net/~m2j/openlp/i18n/+merge/88937 Your team OpenLP Core is subscribed to branch lp:openlp.
=== modified file 'openlp/core/ui/exceptionform.py' --- openlp/core/ui/exceptionform.py 2011-12-27 10:33:55 +0000 +++ openlp/core/ui/exceptionform.py 2012-01-17 21:00:32 +0000 @@ -81,6 +81,11 @@ WEBKIT_VERSION = QtWebKit.qWebKitVersion() except AttributeError: WEBKIT_VERSION = u'-' +try: + import icu + ICU_VERSION = u'OK' +except ImportError: + ICU_VERSION = u'-' from openlp.core.lib import translate, SettingsManager @@ -125,7 +130,8 @@ u'PyEnchant: %s\n' % ENCHANT_VERSION + \ u'PySQLite: %s\n' % SQLITE_VERSION + \ u'Mako: %s\n' % MAKO_VERSION + \ - u'pyUNO bridge: %s\n' % UNO_VERSION + u'pyUNO bridge: %s\n' % UNO_VERSION + \ + u'PyICU: %s\n' % ICU_VERSION if platform.system() == u'Linux': if os.environ.get(u'KDE_FULL_SESSION') == u'true': system = system + u'Desktop: KDE SC\n' === modified file 'openlp/core/ui/thememanager.py' --- openlp/core/ui/thememanager.py 2012-01-04 17:19:49 +0000 +++ openlp/core/ui/thememanager.py 2012-01-17 21:00:32 +0000 @@ -29,7 +29,6 @@ import zipfile import shutil import logging -import locale import re from xml.etree.ElementTree import ElementTree, XML @@ -44,7 +43,8 @@ context_menu_action, context_menu_separator from openlp.core.theme import Theme from openlp.core.ui import FileRenameForm, ThemeForm -from openlp.core.utils import AppLocation, delete_file, get_filesystem_encoding +from openlp.core.utils import AppLocation, delete_file, \ + get_filesystem_encoding, get_local_collator log = logging.getLogger(__name__) @@ -459,7 +459,7 @@ # Sort the themes by its name considering language specific characters. # lower() is needed for windows! files.sort(key=lambda filename: unicode(filename).lower(), - cmp=locale.strcoll) + cmp=get_local_collator) # now process the file list of png files for name in files: # check to see file is in theme root directory === modified file 'openlp/core/utils/__init__.py' --- openlp/core/utils/__init__.py 2011-12-27 10:33:55 +0000 +++ openlp/core/utils/__init__.py 2012-01-17 21:00:32 +0000 @@ -33,6 +33,7 @@ import sys import time import urllib2 +import locale from datetime import datetime from subprocess import Popen, PIPE @@ -45,6 +46,18 @@ except ImportError: XDG_BASE_AVAILABLE = False +LOCALE_COLLATOR = locale.strcoll +if sys.platform == u'win32': + try: + import icu + try: + icu_locale = icu.Locale(locale.getlocale()[0]) + LOCALE_COLLATOR = icu.Collator.createInstance(icu_locale).compare + except icu.InvalidArgsError: + pass + except ImportError: + pass + import openlp from openlp.core.lib import Receiver, translate, check_directory_exists @@ -482,10 +495,16 @@ return resolver.resolve(u'uno:socket,host=localhost,port=2002;' \ + u'urp;StarOffice.ComponentContext') +def get_local_collator(string1, string2): + """ + Returns a collator for locale aware string sorting. + """ + return LOCALE_COLLATOR(string1, string2) + from languagemanager import LanguageManager from actions import ActionList __all__ = [u'AppLocation', u'get_application_version', u'check_latest_version', u'add_actions', u'get_filesystem_encoding', u'LanguageManager', u'ActionList', u'get_web_page', u'get_uno_command', u'get_uno_instance', - u'delete_file', u'clean_filename'] + u'get_local_collator', u'delete_file', u'clean_filename'] === modified file 'openlp/plugins/bibles/forms/bibleimportform.py' --- openlp/plugins/bibles/forms/bibleimportform.py 2011-12-27 10:33:55 +0000 +++ openlp/plugins/bibles/forms/bibleimportform.py 2012-01-17 21:00:32 +0000 @@ -30,7 +30,6 @@ import logging import os import os.path -import locale from PyQt4 import QtCore, QtGui @@ -38,7 +37,7 @@ from openlp.core.lib.db import delete_database from openlp.core.lib.ui import UiStrings, critical_error_message_box from openlp.core.ui.wizard import OpenLPWizard, WizardStrings -from openlp.core.utils import AppLocation +from openlp.core.utils import AppLocation, get_local_collator from openlp.plugins.bibles.lib.manager import BibleFormat from openlp.plugins.bibles.lib.db import BiblesResourcesDB, clean_filename @@ -522,7 +521,7 @@ """ self.webTranslationComboBox.clear() bibles = self.web_bible_list[index].keys() - bibles.sort(cmp=locale.strcoll) + bibles.sort(cmp=get_local_collator) self.webTranslationComboBox.addItems(bibles) def onOsisBrowseButtonClicked(self): === modified file 'openlp/plugins/bibles/lib/__init__.py' --- openlp/plugins/bibles/lib/__init__.py 2011-12-27 10:33:55 +0000 +++ openlp/plugins/bibles/lib/__init__.py 2012-01-17 21:00:32 +0000 @@ -31,6 +31,8 @@ import logging import re +from openlp.core.lib import translate + log = logging.getLogger(__name__) class LayoutStyle(object): @@ -60,28 +62,40 @@ ``match_type`` The type of reference information trying to be extracted in this call. """ - local_separator = unicode(u':;;\s*[:vV]\s*;;-;;\s*-\s*;;,;;\s*,\s*;;end' - ).split(u';;') # English - # local_separator = unicode(u',;;\s*,\s*;;-;;\s*-\s*;;.;;\.;;[Ee]nde' - # ).split(u';;') # German + local_separator = unicode(translate('BiblesPlugin', + ':;;:|v|V;;-;;-;;,;;,;;end', + 'Seperators for parsing references. There are 7 values separated each ' + 'by two semicolons. Verse, range and list separators have each one ' + 'display symbol which appears on slides and in the GUI and a regular ' + 'expression for detecting this symbols.\n' + 'Please ask a developer to double check your translation or make ' + 'yourself familar with regular experssions on: ' + 'http://docs.python.org/library/re.html') + ).split(u';;') separators = { - u'sep_v_display': local_separator[0], u'sep_v': local_separator[1], - u'sep_r_display': local_separator[2], u'sep_r': local_separator[3], - u'sep_l_display': local_separator[4], u'sep_l': local_separator[5], - u'sep_e': local_separator[6]} - + u'sep_v_display': local_separator[0], + u'sep_v': u'\s*(?:' + local_separator[1] + u')\s*', + u'sep_r_display': local_separator[2], + u'sep_r': u'\s*(?:' + local_separator[3] + u')\s*', + u'sep_l_display': local_separator[4], + u'sep_l': u'\s*(?:' + local_separator[5] + u')\s*', + u'sep_e': u'\s*(?:' + local_separator[6] + u')\s*'} + for role in [u'sep_v', u'sep_r', u'sep_l', u'sep_e']: + separators[role] = separators[role].replace(u'-', + u'(?:[-\u00AD\u2010\u2011\u2012\u2013\u2014\u2212\uFE63\uFF0D])') + separators[role] = separators[role].replace(u',', u'(?:[,\u201A])') # verse range match: (<chapter>:)?<verse>(-((<chapter>:)?<verse>|end)?)? - range_string = str(r'(?:(?P<from_chapter>[0-9]+)%(sep_v)s)?(?P<from_verse>' - r'[0-9]+)(?P<range_to>%(sep_r)s(?:(?:(?P<to_chapter>[0-9]+)%(sep_v)s)?' - r'(?P<to_verse>[0-9]+)|%(sep_e)s)?)?') % separators + range_string = unicode(u'(?:(?P<from_chapter>[0-9]+)%(sep_v)s)?' + u'(?P<from_verse>[0-9]+)(?P<range_to>%(sep_r)s(?:(?:(?P<to_chapter>' + u'[0-9]+)%(sep_v)s)?(?P<to_verse>[0-9]+)|%(sep_e)s)?)?') % separators if match_type == u'range': - return re.compile(r'^\s*' + range_string + r'\s*$', re.UNICODE) + return re.compile(u'^\s*' + range_string + u'\s*$', re.UNICODE) elif match_type == u'range_separator': - return re.compile(separators[u'sep_l']) + return re.compile(separators[u'sep_l'], re.UNICODE) elif match_type == u'full': # full reference match: <book>(<range>(,|(?=$)))+ - return re.compile(str(r'^\s*(?!\s)(?P<book>[\d]*[^\d]+)(?<!\s)\s*' - r'(?P<ranges>(?:' + range_string + r'(?:%(sep_l)s|(?=\s*$)))+)\s*$') + return re.compile(unicode(u'^\s*(?!\s)(?P<book>[\d]*[^\d]+)(?<!\s)\s*' + u'(?P<ranges>(?:' + range_string + u'(?:%(sep_l)s|(?=\s*$)))+)\s*$') % separators, re.UNICODE) else: return separators[match_type] === modified file 'openlp/plugins/bibles/lib/mediaitem.py' --- openlp/plugins/bibles/lib/mediaitem.py 2011-12-27 10:33:55 +0000 +++ openlp/plugins/bibles/lib/mediaitem.py 2012-01-17 21:00:32 +0000 @@ -26,7 +26,6 @@ ############################################################################### import logging -import locale from PyQt4 import QtCore, QtGui @@ -36,6 +35,7 @@ from openlp.core.lib.ui import UiStrings, add_widget_completer, \ media_item_combo_box, critical_error_message_box, \ find_and_set_in_combo_box, build_icon +from openlp.core.utils import get_local_collator from openlp.plugins.bibles.forms import BibleImportForm from openlp.plugins.bibles.lib import LayoutStyle, DisplayStyle, \ VerseReferenceList, get_reference_match @@ -373,7 +373,7 @@ self.advancedSecondComboBox.addItem(u'') # Get all bibles and sort the list. bibles = self.plugin.manager.get_bibles().keys() - bibles.sort(cmp=locale.strcoll) + bibles.sort(cmp=get_local_collator) # Load the bibles into the combo boxes. for bible in bibles: if bible: @@ -481,7 +481,7 @@ book_data_temp.append(book) book_data = book_data_temp books = [book.name + u' ' for book in book_data] - books.sort(cmp=locale.strcoll) + books.sort(cmp=get_local_collator) add_widget_completer(books, self.quickSearchEdit) def onQuickVersionComboBox(self): === modified file 'openlp/plugins/custom/lib/mediaitem.py' --- openlp/plugins/custom/lib/mediaitem.py 2011-12-30 21:40:13 +0000 +++ openlp/plugins/custom/lib/mediaitem.py 2012-01-17 21:00:32 +0000 @@ -26,7 +26,6 @@ ############################################################################### import logging -import locale from PyQt4 import QtCore, QtGui from sqlalchemy.sql import or_, func @@ -34,6 +33,7 @@ from openlp.core.lib import MediaManagerItem, Receiver, ItemCapabilities, \ check_item_selected, translate from openlp.core.lib.ui import UiStrings +from oprnlp.core.utils import get_local_collator from openlp.plugins.custom.forms import EditCustomForm from openlp.plugins.custom.lib import CustomXMLParser from openlp.plugins.custom.lib.db import CustomSlide @@ -109,7 +109,7 @@ # Sort the customs by its title considering language specific # characters. lower() is needed for windows! custom_slides.sort( - cmp=locale.strcoll, key=lambda custom: custom.title.lower()) + cmp=get_local_collator, key=lambda custom: custom.title.lower()) for custom_slide in custom_slides: custom_name = QtGui.QListWidgetItem(custom_slide.title) custom_name.setData( === modified file 'openlp/plugins/images/lib/mediaitem.py' --- openlp/plugins/images/lib/mediaitem.py 2011-12-27 10:33:55 +0000 +++ openlp/plugins/images/lib/mediaitem.py 2012-01-17 21:00:32 +0000 @@ -27,7 +27,6 @@ import logging import os -import locale from PyQt4 import QtCore, QtGui @@ -35,7 +34,8 @@ SettingsManager, translate, check_item_selected, check_directory_exists, \ Receiver, create_thumb, validate_thumb from openlp.core.lib.ui import UiStrings, critical_error_message_box -from openlp.core.utils import AppLocation, delete_file, get_images_filter +from openlp.core.utils import AppLocation, delete_file, get_images_filter, \ + get_local_collator log = logging.getLogger(__name__) @@ -120,7 +120,7 @@ self.plugin.formparent.displayProgressBar(len(images)) # Sort the themes by its filename considering language specific # characters. lower() is needed for windows! - images.sort(cmp=locale.strcoll, + images.sort(cmp=get_local_collator, key=lambda filename: os.path.split(unicode(filename))[1].lower()) for imageFile in images: if not initialLoad: === modified file 'openlp/plugins/media/lib/mediaitem.py' --- openlp/plugins/media/lib/mediaitem.py 2011-12-27 10:33:55 +0000 +++ openlp/plugins/media/lib/mediaitem.py 2012-01-17 21:00:32 +0000 @@ -27,7 +27,6 @@ import logging import os -import locale from PyQt4 import QtCore, QtGui @@ -37,6 +36,7 @@ from openlp.core.lib.ui import UiStrings, critical_error_message_box, \ media_item_combo_box from openlp.core.ui import Controller, Display +from openlp.core.utils import get_local_collator log = logging.getLogger(__name__) @@ -278,7 +278,7 @@ def loadList(self, media): # Sort the themes by its filename considering language specific # characters. lower() is needed for windows! - media.sort(cmp=locale.strcoll, + media.sort(cmp=get_local_collator, key=lambda filename: os.path.split(unicode(filename))[1].lower()) for track in media: track_info = QtCore.QFileInfo(track) @@ -298,7 +298,7 @@ def getList(self, type=MediaType.Audio): media = SettingsManager.load_list(self.settingsSection, u'media') - media.sort(cmp=locale.strcoll, + media.sort(cmp=get_local_collator, key=lambda filename: os.path.split(unicode(filename))[1].lower()) ext = [] if type == MediaType.Audio: === modified file 'openlp/plugins/presentations/lib/mediaitem.py' --- openlp/plugins/presentations/lib/mediaitem.py 2011-12-27 10:33:55 +0000 +++ openlp/plugins/presentations/lib/mediaitem.py 2012-01-17 21:00:32 +0000 @@ -27,7 +27,6 @@ import logging import os -import locale from PyQt4 import QtCore, QtGui @@ -36,6 +35,7 @@ validate_thumb from openlp.core.lib.ui import UiStrings, critical_error_message_box, \ media_item_combo_box +from openlp.core.utils import get_local_collator from openlp.plugins.presentations.lib import MessageListener log = logging.getLogger(__name__) @@ -168,7 +168,7 @@ self.plugin.formparent.displayProgressBar(len(files)) # Sort the themes by its filename considering language specific # characters. lower() is needed for windows! - files.sort(cmp=locale.strcoll, + files.sort(cmp=get_local_collator, key=lambda filename: os.path.split(unicode(filename))[1].lower()) for file in files: if not initialLoad: === modified file 'openlp/plugins/songs/forms/songexportform.py' --- openlp/plugins/songs/forms/songexportform.py 2011-12-27 10:33:55 +0000 +++ openlp/plugins/songs/forms/songexportform.py 2012-01-17 21:00:32 +0000 @@ -28,7 +28,6 @@ The :mod:`songexportform` module provides the wizard for exporting songs to the OpenLyrics format. """ -import locale import logging from PyQt4 import QtCore, QtGui @@ -36,6 +35,7 @@ from openlp.core.lib import build_icon, Receiver, SettingsManager, translate from openlp.core.lib.ui import UiStrings, critical_error_message_box from openlp.core.ui.wizard import OpenLPWizard, WizardStrings +from openlp.core.utils import get_local_collator from openlp.plugins.songs.lib.db import Song from openlp.plugins.songs.lib.openlyricsexport import OpenLyricsExport @@ -250,7 +250,7 @@ # Load the list of songs. Receiver.send_message(u'cursor_busy') songs = self.plugin.manager.get_all_objects(Song) - songs.sort(cmp=locale.strcoll, key=lambda song: song.title.lower()) + songs.sort(cmp=get_local_collator, key=lambda song: song.title.lower()) for song in songs: # No need to export temporary songs. if song.temporary: === modified file 'openlp/plugins/songs/lib/mediaitem.py' --- openlp/plugins/songs/lib/mediaitem.py 2011-12-30 21:40:13 +0000 +++ openlp/plugins/songs/lib/mediaitem.py 2012-01-17 21:00:32 +0000 @@ -26,7 +26,6 @@ ############################################################################### import logging -import locale import re import os import shutil @@ -38,7 +37,7 @@ translate, check_item_selected, PluginStatus from openlp.core.lib.ui import UiStrings, context_menu_action, \ context_menu_separator -from openlp.core.utils import AppLocation +from openlp.core.utils import AppLocation, get_local_collator from openlp.plugins.songs.forms import EditSongForm, SongMaintenanceForm, \ SongImportForm, SongExportForm from openlp.plugins.songs.lib import OpenLyrics, SongXML, VerseType, \ @@ -240,7 +239,7 @@ # Sort the songs by its title considering language specific characters. # lower() is needed for windows! searchresults.sort( - cmp=locale.strcoll, key=lambda song: song.title.lower()) + cmp=get_local_collator, key=lambda song: song.title.lower()) for song in searchresults: # Do not display temporary songs if song.temporary: === modified file 'scripts/check_dependencies.py' --- scripts/check_dependencies.py 2011-10-26 07:40:12 +0000 +++ scripts/check_dependencies.py 2012-01-17 21:00:32 +0000 @@ -74,6 +74,7 @@ 'mako', 'migrate', 'uno', + 'icu', ]
_______________________________________________ Mailing list: https://launchpad.net/~openlp-core Post to : openlp-core@lists.launchpad.net Unsubscribe : https://launchpad.net/~openlp-core More help : https://help.launchpad.net/ListHelp