gramps/src/Spell.py

318 lines
10 KiB
Python

#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2005-2006 Donald N. Allingham
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# $Id$
"""
Provide an interface to the gtkspell interface. This requires
python-gnome-extras package. If the gtkspell package is not
present, we default to no spell checking.
"""
#-------------------------------------------------------------------------
#
# Python classes
#
#-------------------------------------------------------------------------
from gen.ggettext import gettext as _
import locale
#-------------------------------------------------------------------------
#
# Set up logging
#
#-------------------------------------------------------------------------
import logging
LOG = logging.getLogger(".Spell")
#-------------------------------------------------------------------------
#
# GTK libraries
#
#-------------------------------------------------------------------------
import gtk
try:
import enchant
HAVE_ENCHANT = True
except ImportError:
HAVE_ENCHANT = False
try:
import gtkspell
HAVE_GTKSPELL = True
except ImportError:
HAVE_GTKSPELL = False
if not HAVE_GTKSPELL:
LOG.warn(_("Spelling checker is not installed"))
#-------------------------------------------------------------------------
#
# GRAMPS classes
#
#-------------------------------------------------------------------------
import config
#-------------------------------------------------------------------------
#
# Constants
#
#-------------------------------------------------------------------------
# All official dictionaries available for GNU Aspell.
# ftp://ftp.gnu.org/gnu/aspell/dict/0index.html
LANGUAGES = {
'af': _('Afrikaans'),
'am': _('Amharic'),
'ar': _('Arabic'),
'az': _('Azerbaijani'),
'be': _('Belarusian'),
'bg': _('Bulgarian'),
'bn': _('Bengali'),
'br': _('Breton'),
'ca': _('Catalan'),
'cs': _('Czech'),
'csb': _('Kashubian'),
'cy': _('Welsh'),
'da': _('Danish'),
'de': _('German'),
'de-alt': _('German - Old Spelling'),
'el': _('Greek'),
'en': _('English'),
'eo': _('Esperanto'),
'es': _('Spanish'),
'et': _('Estonian'),
'fa': _('Persian'),
'fi': _('Finnish'),
'fo': _('Faroese'),
'fr': _('French'),
'fy': _('Frisian'),
'ga': _('Irish'),
'gd': _('Scottish Gaelic'),
'gl': _('Galician'),
'gu': _('Gujarati'),
'gv': _('Manx Gaelic'),
'he': _('Hebrew'),
'hi': _('Hindi'),
'hil': _('Hiligaynon'),
'hr': _('Croatian'),
'hsb': _('Upper Sorbian'),
'hu': _('Hungarian'),
'hy': _('Armenian'),
'ia': _('Interlingua'),
'id': _('Indonesian'),
'is': _('Icelandic'),
'it': _('Italian'),
'ku': _('Kurdi'),
'la': _('Latin'),
'lt': _('Lithuanian'),
'lv': _('Latvian'),
'mg': _('Malagasy'),
'mi': _('Maori'),
'mk': _('Macedonian'),
'mn': _('Mongolian'),
'mr': _('Marathi'),
'ms': _('Malay'),
'mt': _('Maltese'),
'nb': _('Norwegian Bokmal'),
'nds': _('Low Saxon'),
'nl': _('Dutch'),
'nn': _('Norwegian Nynorsk'),
'ny': _('Chichewa'),
'or': _('Oriya'),
'pa': _('Punjabi'),
'pl': _('Polish'),
'pt': _('Portuguese'),
'pt_BR': _('Brazilian Portuguese'),
'pt_PT': _('Portuguese'),
'qu': _('Quechua'),
'ro': _('Romanian'),
'ru': _('Russian'),
'rw': _('Kinyarwanda'),
'sc': _('Sardinian'),
'sk': _('Slovak'),
'sl': _('Slovenian'),
'sr': _('Serbian'),
'sv': _('Swedish'),
'sw': _('Swahili'),
'ta': _('Tamil'),
'te': _('Telugu'),
'tet': _('Tetum'),
'tl': _('Tagalog'),
'tn': _('Setswana'),
'tr': _('Turkish'),
'uk': _('Ukrainian'),
'uz': _('Uzbek'),
'vi': _('Vietnamese'),
'wa': _('Walloon'),
'yi': _('Yiddish'),
'zu': _('Zulu'),
}
class Spell(object):
"""Attach a gtkspell instance to the passed TextView instance.
"""
lang = locale.getlocale()[0]
_installed_languages = {'off': _('None')}
if HAVE_ENCHANT and HAVE_GTKSPELL:
#gtkspell depends on enchant but has no api to query the installed
#languages. Hence, we use enchant to do this if available.
for language in enchant.list_languages():
try:
name = LANGUAGES[language]
except KeyError:
name = language
if name == language:
parts = name.split('_')
if len(parts) == 2:
try:
name = LANGUAGES[parts[0]]
name += ': ' + parts[1]
except KeyError:
pass
_installed_languages[language] = " ".join(name.split('_'))
elif not HAVE_ENCHANT and HAVE_GTKSPELL:
# if lang is None, default to en:
if lang == None:
locale_lang_code = "en"
else:
locale_lang_code = lang
tested = False
#we try a hack to get the locale language.
for (lang_code, lang_name) in LANGUAGES.items():
# if this lang is the current locale:
if (locale_lang_code == lang_code):
tested = True
# if it is english, we know it works:
if locale_lang_code == "en":
_installed_languages[locale_lang_code] = lang_name
print _("Warning: spelling checker language limited to "
"locale '%s'; install pyenchant/python-enchant "
"for better options.") % "en"
elif locale.getlocale()[1] == "UTF8":
# Only worked with UTF8 versions of language.
# But, we need to test it:
try:
#work around gtkspell bug with tv
tv = gtk.TextView()
gtkspell.Spell(tv).set_language(lang_code)
_installed_languages[lang_code] = lang_name
print _("Warning: spelling checker language limited to "
"locale '%s'; install pyenchant/python-enchant "
"for better options.") % lang
except:
# FIXME: this does not work anymore since 10/2008!!!
# if pyenchant is installed we can avoid it, otherwise
# perhaps future gtkspell3 will offer a solution.
print _("Warning: spelling checker disabled; "
"install pyenchant/python-enchant to enable.")
# if we matched, we're done looking
break
if not tested:
# if we didn't see a match on lang, then there is no spell check
print _("Warning: spelling checker disabled; "
"install pyenchant/python-enchant to enable.")
def __init__(self, textview):
self.textview = textview
if self.lang and config.get('behavior.spellcheck'):
# if LANG is not a correct key (pt_BR or pt_PT),
# try only the language part of LANG
if self.lang not in self._installed_languages:
self.lang = self.lang.split('_')[0]
# if this still doesn't work we fall back to 'off'
if self.lang not in self._installed_languages:
self.lang = 'off'
else:
self.lang = 'off'
self._active_language = 'off'
self.__real_set_active_language(self.lang)
# Private
def __real_set_active_language(self, lang_code):
"""Set the active language by it's code."""
if self._active_language == 'off':
if lang_code == 'off':
return
else:
gtkspell_spell = gtkspell.Spell(self.textview)
else:
gtkspell_spell = gtkspell.get_from_text_view(self.textview)
if lang_code == 'off':
gtkspell_spell.detach()
self._active_language = lang_code
return
try:
gtkspell_spell.set_language(lang_code)
self._active_language = lang_code
except RuntimeError:
#This catches error with old gtkspell versions that generate
#this exception if dict cannot be loaded.
gtkspell_spell.detach()
self._active_language = 'off'
# Public API
def get_all_languages(self):
"""Get the list of installed language names."""
langs = self._installed_languages.values()
langs.sort(sort_languages)
return langs
def set_active_language(self, language):
"""Set active language by it's name."""
for code, name in self._installed_languages.items():
if name == language:
self.__real_set_active_language(code)
return
def get_active_language(self):
"""Get the name of the active language."""
return self._installed_languages[self._active_language]
#-------------------------------------------------------------------------
#
# sort_languages
#
#-------------------------------------------------------------------------
def sort_languages(lang_a, lang_b):
"""Put language names in alphabetical order.
Except 'None', which should be always the first.
"""
if lang_a == _('None'):
return -1
if lang_b == _('None'):
return 1
if lang_a < lang_b:
return -1
if lang_a > lang_b:
return 1
return 0