Updated pygtkspellcheck to 4.0.5

gh-pages
somas95 2018-04-13 00:23:47 +02:00
parent ac1774c848
commit db427bf1fb
5 changed files with 400 additions and 132 deletions

View File

@ -16,29 +16,25 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# Python 2/3 unicode
import sys
if sys.version_info.major == 3:
u = lambda x: x
else:
u = lambda x: x.decode('utf-8')
from __future__ import unicode_literals
# Metadata
__version__ = '3.0'
__version__ = '4.0.5'
__project__ = 'Python GTK Spellcheck'
__short_name__ = 'pygtkspellcheck'
__authors__ = u('Maximilian Köhl & Carlos Jenkins')
__emails__ = u('linuxmaxi@googlemail.com & carlos@jenkins.co.cr')
__authors__ = 'Maximilian Köhl & Carlos Jenkins'
__emails__ = 'linuxmaxi@googlemail.com & carlos@jenkins.co.cr'
__website__ = 'http://koehlma.github.com/projects/pygtkspellcheck.html'
__download_url__ = 'https://github.com/koehlma/pygtkspellcheck/tarball/master'
__source__ = 'https://github.com/koehlma/pygtkspellcheck/'
__vcs__ = 'git://github.com/koehlma/pygtkspellcheck.git'
__copyright__ = u('2012, Maximilian Köhl & Carlos Jenkins')
__desc_short__ = 'A simple but quite powerful Python spell checking library for GtkTextViews based on Enchant.'
__desc_long__ = ('It supports both Gtk\'s Python bindings, PyGObject and'
'PyGtk, and for both Python 2 and 3 with automatic switching'
'and binding autodetection. For automatic translation of the'
'user interface it can use GEdit\'s translation files.')
__copyright__ = '2012, Maximilian Köhl & Carlos Jenkins'
__desc_short__ = ('a simple but quite powerful Python spell checking library '
'for GtkTextViews based on Enchant')
__desc_long__ = ('A simple but quite powerful spellchecking library written in '
'pure Python for Gtk based on Enchant. It supports PyGObject '
'as well as PyGtk for Python 2 and 3 with automatic switching '
'and binding detection. For automatic translation of the user '
'interface it can use Gedits translation files.')
__metadata__ = {'__version__' : __version__,
'__project__' : __project__,
@ -53,5 +49,5 @@ __metadata__ = {'__version__' : __version__,
'__desc_short__' : __desc_short__,
'__desc_long__' : __desc_long__}
# import SpellChecker class
from . spellcheck import SpellChecker
from gtkspellcheck.spellcheck import (SpellChecker, NoDictionariesFound,
NoGtkBindingFound)

View File

@ -0,0 +1,294 @@
# -*- coding:utf-8 -*-
#
# Copyright (C) 2012, Carlos Jenkins <carlos@jenkins.co.cr>
# Copyright (C) 2012-2016, Maximilian Köhl <mail@koehlma.de>
#
# 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 3 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, see <http://www.gnu.org/licenses/>.
"""
This module extracts the .dic and .aff (Hunspell) dictionaries from any given
.oxt extension.
Extensions could be found at:
http://extensions.services.openoffice.org/dictionary
"""
import functools
import gettext
import logging
import os
import shutil
import sys
import warnings
import xml.dom.minidom
import xml.parsers.expat
import zipfile
# enable deprecation warnings
warnings.simplefilter('always', DeprecationWarning)
# public objects
__all__ = ['extract_oxt', 'batch_extract', 'BadXml', 'BadExtensionFile',
'ExtractPathIsNoDirectory', 'BATCH_SUCCESS', 'BATCH_ERROR',
'BATCH_WARNING']
# logger
logger = logging.getLogger(__name__)
# translation
locale_name = 'py{}gtkspellcheck'.format(sys.version_info.major)
_ = gettext.translation(locale_name, fallback=True).gettext
class BadXml(Exception):
"""
The XML dictionary registry is not valid XML.
"""
class BadExtensionFile(Exception):
"""
The extension has a wrong file format, should be a ZIP file.
"""
class ExtractPathIsNoDirectory(Exception):
"""
The given `extract_path` is no directory.
"""
def find_dictionaries(registry):
def oor_name(name, element):
return element.attributes['oor:name'].value.lower() == name
def get_property(name, properties):
property = list(filter(functools.partial(oor_name, name),
properties))
if property:
return property[0].getElementsByTagName('value')[0]
result = []
# find all "node" elements which have "dictionaries" as "oor:name" attribute
for dictionaries in filter(functools.partial(oor_name, 'dictionaries'),
registry.getElementsByTagName('node')):
# for all "node" elements in this dictionary nodes
for dictionary in dictionaries.getElementsByTagName('node'):
# get all "prop" elements
properties = dictionary.getElementsByTagName('prop')
# get the format property as text
format = get_property('format', properties).firstChild.data.strip()
if format and format == 'DICT_SPELL':
# find the locations property
locations = get_property('locations', properties)
# if the location property is text:
# %origin%/dictionary.aff %origin%/dictionary.dic
if locations.firstChild.nodeType == xml.dom.Node.TEXT_NODE:
locations = locations.firstChild.data
locations = locations.replace('%origin%/', '').strip()
result.append(locations.split())
# otherwise:
# <i>%origin%/dictionary.aff</i> <i>%origin%/dictionary.dic</i>
else:
locations = [item.firshChild.data.replace('%origin%/', '') \
.strip() for item in
locations.getElementsByTagName('it')]
result.append(locations)
return result
def extract(filename, target, override=False):
"""
Extract Hunspell dictionaries out of LibreOffice ``.oxt`` extensions.
:param filename: path to the ``.oxt`` extension
:param target: path to extract Hunspell dictionaries to
:param override: override existing files in the target directory
:rtype: list of the extracted dictionaries
This function extracts the Hunspell dictionaries (``.dic`` and ``.aff``
files) from the given ``.oxt`` extension found to ``target``.
Extensions could be found at:
http://extensions.services.openoffice.org/dictionary
"""
# TODO 5.0: remove this function
warnings.warn(('call to deprecated function "{}", '
'moved to separate package "oxt_extract", '
'will be removed in pygtkspellcheck 5.0').format(extract.__name__),
category=DeprecationWarning)
try:
with zipfile.ZipFile(filename, 'r') as extension:
files = extension.namelist()
registry = 'dictionaries.xcu'
if not registry in files:
for filename in files:
if filename.lower().endswith(registry):
registry = filename
if registry in files:
registry = xml.dom.minidom.parse(extension.open(registry))
dictionaries = find_dictionaries(registry)
extracted = []
for dictionary in dictionaries:
for filename in dictionary:
dict_file = os.path.join(target,
os.path.basename(filename))
if (not os.path.exists(dict_file)
or (override and os.path.isfile(dict_file))):
if filename in files:
with open(dict_file, 'wb') as _target:
with extension.open(filename, 'r') as _source:
extracted.append(os.path.basename(filename))
_target.write(_source.read())
else:
logger.warning('dictionary exists in registry '
'but not in the extension zip')
else:
logging.warning(('dictionary file "{}" already exists '
'and not overriding it'
).format(dict_file))
return extracted
except zipfile.BadZipfile:
raise BadExtensionFile('extension is not a valid ZIP file')
except xml.parsers.expat.ExpatError:
raise BadXml('dictionary registry is not valid XML')
BATCH_SUCCESS = 'success'
BATCH_ERROR = 'error'
BATCH_WARNING = 'warning'
def batch_extract(oxt_path, extract_path, override=False, move_path=None):
"""
Uncompress, read and install LibreOffice ``.oxt`` dictionaries extensions.
:param oxt_path: path to a directory containing the ``.oxt`` extensions
:param extract_path: path to extract Hunspell dictionaries files to
:param override: override already existing files
:param move_path: optional path to move the ``.oxt`` files after processing
:rtype: generator over all extensions, yielding result, extension name,
error, extracted dictionaries and translated error message - result
would be :const:`BATCH_SUCCESS` for success, :const:`BATCH_ERROR` if
some error happened or :const:`BATCH_WARNING` which contain some warning
messages instead of errors
This function extracts the Hunspell dictionaries (``.dic`` and ``.aff``
files) from all the ``.oxt`` extensions found on ``oxt_path`` directory to
the ``extract_path`` directory.
Extensions could be found at:
http://extensions.services.openoffice.org/dictionary
In detail, this functions does the following:
1. find all the ``.oxt`` extension files within ``oxt_path``
2. open (unzip) each extension
3. find the dictionary definition file within (*dictionaries.xcu*)
4. parse the dictionary definition file and locate the dictionaries files
5. uncompress those files to ``extract_path``
By default file overriding is disabled, set ``override`` parameter to True
if you want to enable it. As additional option, each processed extension can
be moved to ``move_path``.
Example::
for result, name, error, dictionaries, message in oxt_extract.batch_extract(...):
if result == oxt_extract.BATCH_SUCCESS:
print('successfully extracted extension "{}"'.format(name))
elif result == oxt_extract.BATCH_ERROR:
print('could not extract extension "{}"'.format(name))
print(message)
print('error {}'.format(error))
elif result == oxt_extract.BATCH_WARNING:
print('warning during processing extension "{}"'.format(name))
print(message)
print(error)
"""
# TODO 5.0: remove this function
warnings.warn(('call to deprecated function "{}", '
'moved to separate package "oxt_extract", '
'will be removed in pygtkspellcheck 5.0').format(extract.__name__),
category=DeprecationWarning)
# get the real, absolute and normalized path
oxt_path = os.path.normpath(os.path.abspath(os.path.realpath(oxt_path)))
# check that the input directory exists
if not os.path.isdir(oxt_path):
return
# create extract directory if not exists
if not os.path.exists(extract_path):
os.makedirs(extract_path)
# check that the extract path is a directory
if not os.path.isdir(extract_path):
raise ExtractPathIsNoDirectory('extract path is not a valid directory')
# get all .oxt extension at given path
oxt_files = [extension for extension in os.listdir(oxt_path)
if extension.lower().endswith('.oxt')]
for extension_name in oxt_files:
extension_path = os.path.join(oxt_path, extension_name)
try:
dictionaries = extract(extension_path, extract_path, override)
yield BATCH_SUCCESS, extension_name, None, dictionaries, ''
except BadExtensionFile as error:
logger.error(('extension "{}" is not a valid ZIP file'
).format(extension_name))
yield (BATCH_ERROR, extension_name, error, [],
_('extension "{}" is not a valid ZIP file'
).format(extension_name))
except BadXml as error:
logger.error(('extension "{}" has no valid XML dictionary registry'
).format(extension_name))
yield (BATCH_ERROR, extension_name, error, [],
_('extension "{}" has no valid XML dictionary registry'
).format(extension_name))
# move the extension after processing if user requires it
if move_path is not None:
# create move path if it doesn't exists
if not os.path.exists(move_path):
os.makedirs(move_path)
# move to the given path only if it is a directory and target
# doesn't exists
if os.path.isdir(move_path):
if (not os.path.exists(os.path.join(move_path, extension_name))
or override):
shutil.move(extension_path, move_path)
else:
logger.warning(('unable to move extension, file with same '
'name exists within move_path'))
yield (BATCH_WARNING, extension_name,
('unable to move extension, file with same name '
'exists within move_path'), [],
_('unable to move extension, file with same name '
'exists within move_path'))
else:
logger.warning(('unable to move extension, move_path is not a '
'directory'))
yield (BATCH_WARNING, extension_name,
('unable to move extension, move_path is not a '
'directory'), [],
_('unable to move extension, move_path is not a '
'directory'))

View File

@ -28,13 +28,9 @@ import gettext
import logging
import re
import sys
import pickle
import os
from ..helpers import get_media_path
import xml.etree.ElementTree as ET
from ..pylocales import code_to_name
from pylocales import code_to_name as _code_to_name
from pylocales import LanguageNotFound, CountryNotFound
# public objects
__all__ = ['SpellChecker', 'NoDictionariesFound', 'NoGtkBindingFound']
@ -53,15 +49,25 @@ class NoGtkBindingFound(Exception):
Could not find any loaded Gtk binding.
"""
# find any loaded gtk binding
if 'gi.repository.Gtk' in sys.modules:
gtk = sys.modules['gi.repository.Gtk']
_pygobject = True
elif 'gtk' in sys.modules:
gtk = sys.modules['gtk']
_pygobject = False
if sys.version_info.major == 3:
_py3k = True
else:
raise NoGtkBindingFound('could not find any loaded Gtk binding')
_py3k = False
if _py3k:
# there is only the gi binding for Python 3
from gi.repository import Gtk as gtk
_pygobject = True
else:
# find any loaded gtk binding
if 'gi.repository.Gtk' in sys.modules:
gtk = sys.modules['gi.repository.Gtk']
_pygobject = True
elif 'gtk' in sys.modules:
gtk = sys.modules['gtk']
_pygobject = False
else:
raise NoGtkBindingFound('could not find any loaded Gtk binding')
# select base list class
try:
@ -70,10 +76,7 @@ try:
except ImportError:
_list = list
if sys.version_info.major == 3:
_py3k = True
else:
_py3k = False
# select base string
if _py3k:
@ -84,7 +87,8 @@ _GEDIT_MAP = {'Languages' : 'Languages',
'Ignore All' : 'Ignore _All',
'Suggestions' : 'Suggestions',
'(no suggestions)' : '(no suggested words)',
'Add "{}" to Dictionary' : 'Add w_ord'}
'Add "{}" to Dictionary' : 'Add w_ord',
'Unknown' : 'Unknown'}
# translation
if gettext.find('gedit'):
@ -94,6 +98,12 @@ else:
locale_name = 'py{}gtkspellcheck'.format(sys.version_info.major)
_ = gettext.translation(locale_name, fallback=True).gettext
def code_to_name(code, separator='_'):
try:
return _code_to_name(code, separator)
except (LanguageNotFound, CountryNotFound):
return '{} ({})'.format(_('Unknown'), code)
class SpellChecker(object):
"""
Main spellchecking class, everything important happens here.
@ -173,7 +183,6 @@ class SpellChecker(object):
def __init__(self, view, language='en', prefix='gtkspellchecker',
collapse=True, params={}):
self._view = view
self.collapse = collapse
self._view.connect('populate-popup',
@ -181,12 +190,6 @@ class SpellChecker(object):
self._view.connect('popup-menu', self._click_move_popup)
self._view.connect('button-press-event', self._click_move_button)
self._prefix = prefix
if _pygobject:
self._misspelled = gtk.TextTag.new('{}-misspelled'\
.format(self._prefix))
else:
self._misspelled = gtk.TextTag('{}-misspelled'.format(self._prefix))
self._misspelled.set_property('underline', 4)
self._broker = enchant.Broker()
for param, value in params.items(): self._broker.set_param(param, value)
self.languages = SpellChecker._LanguageList.from_broker(self._broker)
@ -219,26 +222,6 @@ class SpellChecker(object):
self._enabled = True
self.buffer_initialize()
self.notify_language_change_functions = []
self.frequency_dict = {}
pp_pickled = 'pickled_dict'
if pp_pickled and os.path.isfile(pp_pickled):
f = open(pp_pickled, 'rb')
self.frequency_dict = pickle.load(f)
f.close()
else:
pp = get_media_path('wordlists/en_us_wordlist.xml')
frequencies = ET.parse(pp)
root = frequencies.getroot()
for child in root:
self.frequency_dict[child.text] = int(child.attrib['f'])
f = open('pickled_dict', 'wb+')
pickle.dump(self.frequency_dict, f)
f.close()
# print(self.frequency_dict)
@property
def language(self):
"""
@ -273,6 +256,12 @@ class SpellChecker(object):
have associated a new GtkTextBuffer with the GtkTextView call this
method.
"""
if _pygobject:
self._misspelled = gtk.TextTag.new('{}-misspelled'\
.format(self._prefix))
else:
self._misspelled = gtk.TextTag('{}-misspelled'.format(self._prefix))
self._misspelled.set_property('underline', 4)
self._buffer = self._view.get_buffer()
self._buffer.connect('insert-text', self._before_text_insert)
self._buffer.connect_after('insert-text', self._after_text_insert)
@ -451,24 +440,15 @@ class SpellChecker(object):
else:
self._check_word(word_start, word_end)
self._deferred_check = False
word_end.forward_word_end()
word_end.backward_word_start()
word_start = word_end.copy()
if word_start.equal(word_end):
break
def connect_language_change(self, fn):
self.notify_language_change_functions.append(fn)
word_start = word_end.copy()
def _languages_menu(self):
def _set_language(item, code):
self.language = code
for fn in self.notify_language_change_functions:
fn(code)
if _pygobject:
menu = gtk.Menu.new()
group = []
@ -508,21 +488,6 @@ class SpellChecker(object):
item.add(label)
menu.append(item)
else:
# add sorting here
# suggestions_map = []
# print(suggestions)
# for suggestion in suggestions:
# if suggestion in self.frequency_dict:
# suggestions_map.append({'suggestion': suggestion, 'freq': self.frequency_dict[suggestion]})
# else:
# suggestions_map.append({'suggestion': suggestion, 'freq': 0})
# suggestions_map.sort(key= lambda x: x['freq'])
# suggestions_map.reverse()
# print(suggestions_map)
# suggestions = []
# for suggestion in suggestions_map:
# suggestions.append(suggestion["suggestion"])
for suggestion in suggestions:
if _pygobject:
item = gtk.MenuItem.new()
@ -609,7 +574,10 @@ class SpellChecker(object):
if self._deferred_check: self._check_deferred_range(True)
x, y = self._view.window_to_buffer_coords(2, int(event.x),
int(event.y))
self._marks['click'].move(self._view.get_iter_at_location(x, y))
iter = self._view.get_iter_at_location(x, y)
if isinstance(iter, tuple):
iter = iter[1]
self._marks['click'].move(iter)
return False
def _before_text_insert(self, textbuffer, location, text, length):
@ -651,6 +619,8 @@ class SpellChecker(object):
word = self._buffer.get_text(start, end, False).strip()
else:
word = self._buffer.get_text(start, end, False).decode('utf-8').strip()
if not word:
return
if len(self._filters[SpellChecker.FILTER_WORD]):
if self._regexes[SpellChecker.FILTER_WORD].match(word):
return
@ -684,9 +654,5 @@ class SpellChecker(object):
end = self._buffer.get_iter_at_offset(match.end())
self._buffer.remove_tag(self._misspelled, start, end)
return
# Somehow needed now, checking for zero length (happens on double space)
if len(word) == 0:
return
if not self._dictionary.check(word):
self._buffer.apply_tag(self._misspelled, start, end)

View File

@ -15,29 +15,23 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# Python 2/3 unicode
import sys
if sys.version_info.major == 3:
u = lambda x: x
else:
u = lambda x: x.decode('utf-8')
from __future__ import unicode_literals
# Metadata
__version__ = '1.1'
__project__ = 'PyLocales'
__version__ = '1.2'
__project__ = 'Python Locales'
__short_name__ = 'pylocales'
__authors__ = u('Maximilian Köhl & Carlos Jenkins')
__emails__ = u('linuxmaxi@googlemail.com & carlos@jenkins.co.cr')
__website__ = 'http://pygtkspellcheck.readthedocs.org/'
__authors__ = 'Maximilian Köhl'
__emails__ = 'linuxmaxi@googlemail.com'
__website__ = 'http://koehlma.github.com/projects/pygtkspellcheck.html'
__source__ = 'https://github.com/koehlma/pygtkspellcheck/'
__vcs__ = 'git://github.com/koehlma/pygtkspellcheck.git'
__copyright__ = u('2012, Maximilian Köhl & Carlos Jenkins')
__desc_short__ = 'Query the ISO 639/3166 database about a country or a language.'
__copyright__ = '2012, Maximilian Köhl'
__desc_short__ = 'query the ISO 639/3166 database about a country or a language.'
__desc_long__ = ('Query the ISO 639/3166 database about a country or a'
'language. The locales database contains ISO 639 languages'
'definitions and ISO 3166 countries definitions. This package'
'provides translation for countries and languages names if'
'iso-codes package is installed (Ubuntu/Debian).')
'language. The locales database contains ISO 639 language'
'definitions and ISO 3166 country definitions. This package'
'provides translation for country and language names if'
'the iso-code messages are installed on your system.')
__metadata__ = {'__version__' : __version__,
'__project__' : __project__,
@ -51,5 +45,5 @@ __metadata__ = {'__version__' : __version__,
'__desc_short__' : __desc_short__,
'__desc_long__' : __desc_long__}
# Should only import Public Objects
from .locales import *
from pylocales.locales import (Country, Language, LanguageNotFound,
CountryNotFound, code_to_name)

View File

@ -18,23 +18,22 @@
"""
Query the ISO 639/3166 database about a country or a language. The locales
database contains ISO 639 languages definitions and ISO 3166 countries
definitions. This package provides translation for countries and languages names
if iso-codes package is installed (Ubuntu/Debian).
@see utils/locales/build.py to know the database tables and structure.
database contains ISO 639 language definitions and ISO 3166 country definitions.
This package provides translation for country and language names if the
iso-code messages are installed on your system.
"""
import gettext
import logging
import os
import sqlite3
import sys
# Public Objects
# public objects
__all__ = ['Country', 'Language', 'LanguageNotFound',
'CountryNotFound', 'code_to_name']
# Translation
# translation
_translator_language = gettext.translation('iso_639', fallback=True).gettext
_translator_country = gettext.translation('iso_3166', fallback=True).gettext
@ -48,14 +47,23 @@ if hasattr(os.path, 'get_module_path'):
if not os.path.isfile(os.path.join(__path__, 'locales.db')):
__path__ = None
if __path__ is None:
__path__ = os.path.abspath(os.path.realpath(os.path.dirname(__file__)))
frozen = getattr(sys, 'frozen', None)
if frozen in ('dll', 'console_exe', 'windows_exe'):
__path__ = os.path.abspath(os.path.dirname(sys.executable))
elif frozen == 'macosx_app':
__path__ = os.path.abspath(os.environ['RESOURCEPATH'])
elif frozen is True:
# Handle executables produced by PyInstaller.
__path__ = sys._MEIPASS
else:
__path__ = os.path.abspath(os.path.realpath(os.path.dirname(__file__)))
# Loading the Database
# loading the database
_database = sqlite3.connect(os.path.join(__path__, 'locales.db'))
logger = logging.getLogger(__name__)
# Exceptions
class LanguageNotFound(Exception):
"""
The specified language wasn't found in the database.
@ -68,7 +76,8 @@ class CountryNotFound(Exception):
class Country(object):
def __init__(self, rowid):
country = _database.execute('SELECT * FROM countries WHERE rowid == ?', (rowid,)).fetchone()
country = _database.execute('SELECT * FROM countries WHERE rowid == ?',
(rowid,)).fetchone()
self.name = country[0]
self.official_name = country[1]
self.alpha_2 = country[2]
@ -78,7 +87,9 @@ class Country(object):
@classmethod
def get_country(cls, code, codec):
country = _database.execute('SELECT rowid FROM countries WHERE %s == ?' % (codec), (code,)).fetchone()
country = _database.execute(
'SELECT rowid FROM countries WHERE %s == ?' % (codec),
(code,)).fetchone()
if country:
return cls(country[0])
raise CountryNotFound('code: %s, codec: %s' % (code, codec))
@ -97,7 +108,8 @@ class Country(object):
class Language(object):
def __init__(self, rowid):
language = _database.execute('SELECT * FROM languages WHERE rowid == ?', (rowid,)).fetchone()
language = _database.execute('SELECT * FROM languages WHERE rowid == ?',
(rowid,)).fetchone()
self.name = language[0]
self.iso_639_2B = language[1]
self.iso_639_2T = language[2]
@ -106,7 +118,9 @@ class Language(object):
@classmethod
def get_language(cls, code, codec):
language = _database.execute('SELECT rowid FROM languages WHERE %s == ?' % (codec), (code,)).fetchone()
language = _database.execute(
'SELECT rowid FROM languages WHERE %s == ?' % (codec),
(code,)).fetchone()
if language:
return cls(language[0])
raise LanguageNotFound('code: %s, codec: %s' % (code, codec))
@ -125,14 +139,18 @@ class Language(object):
def code_to_name(code, separator='_'):
"""
Get the natural name of a language based on it's code.
"""
Get the human readable and translated name of a language based on it's code.
:param code: the code of the language (e.g. de_DE, en_US)
:param target: separator used to separate language from country
:rtype: human readable and translated language name
"""
logger.debug('requesting name for code "{}"'.format(code))
code = code.split(separator)
if len(code) > 1:
lang = Language.by_iso_639_1(code[0]).translation
country = Country.by_alpha_2(code[1]).translation
return '{lang} ({country})'.format(lang=lang, country=country)
return '{} ({})'.format(lang, country)
else:
return Language.by_iso_639_1(code[0]).translation
return Language.by_iso_639_1(code[0]).translation