forked from Mirrors/apostrophe
157 lines
5.4 KiB
Python
157 lines
5.4 KiB
Python
|
# -*- coding:utf-8 -*-
|
||
|
#
|
||
|
# Copyright (C) 2019, Maximilian Köhl <linuxmaxi@googlemail.com>
|
||
|
# Copyright (C) 2019, Carlos Jenkins <carlos@jenkins.co.cr>
|
||
|
#
|
||
|
# 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/>.
|
||
|
|
||
|
"""
|
||
|
Query the ISO 639/3166 database about a country or a 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.
|
||
|
"""
|
||
|
|
||
|
import gettext
|
||
|
import logging
|
||
|
import os
|
||
|
import sqlite3
|
||
|
import sys
|
||
|
|
||
|
# public objects
|
||
|
__all__ = ['Country', 'Language', 'LanguageNotFound',
|
||
|
'CountryNotFound', 'code_to_name']
|
||
|
|
||
|
# translation
|
||
|
_translator_language = gettext.translation('iso_639', fallback=True).gettext
|
||
|
_translator_country = gettext.translation('iso_3166', fallback=True).gettext
|
||
|
|
||
|
# Decides where the database is located. If an application provides an
|
||
|
# os.path.get_module_path monkey patch to determine the path where the module
|
||
|
# is located it uses this. If not it searches in the directory of this source
|
||
|
# code file.
|
||
|
__path__ = None
|
||
|
if hasattr(os.path, 'get_module_path'):
|
||
|
__path__ = os.path.get_module_path(__file__)
|
||
|
if not os.path.isfile(os.path.join(__path__, 'locales.db')):
|
||
|
__path__ = None
|
||
|
if __path__ is None:
|
||
|
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
|
||
|
_database = sqlite3.connect(os.path.join(__path__, 'locales.db'))
|
||
|
|
||
|
logger = logging.getLogger(__name__)
|
||
|
|
||
|
class LanguageNotFound(Exception):
|
||
|
"""
|
||
|
The specified language wasn't found in the database.
|
||
|
"""
|
||
|
|
||
|
class CountryNotFound(Exception):
|
||
|
"""
|
||
|
The specified country wasn't found in the database.
|
||
|
"""
|
||
|
|
||
|
class Country(object):
|
||
|
def __init__(self, rowid):
|
||
|
country = _database.execute('SELECT * FROM countries WHERE rowid == ?',
|
||
|
(rowid,)).fetchone()
|
||
|
self.name = country[0]
|
||
|
self.official_name = country[1]
|
||
|
self.alpha_2 = country[2]
|
||
|
self.alpha_3 = country[3]
|
||
|
self.numeric = country[4]
|
||
|
self.translation = _translator_country(self.name)
|
||
|
|
||
|
@classmethod
|
||
|
def get_country(cls, code, codec):
|
||
|
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))
|
||
|
|
||
|
@classmethod
|
||
|
def by_alpha_2(cls, code):
|
||
|
return Country.get_country(code, 'alpha_2')
|
||
|
|
||
|
@classmethod
|
||
|
def by_alpha_3(cls, code):
|
||
|
return Country.get_country(code, 'alpha_3')
|
||
|
|
||
|
@classmethod
|
||
|
def by_numeric(cls, code):
|
||
|
return Country.get_country(code, 'numeric')
|
||
|
|
||
|
class Language(object):
|
||
|
def __init__(self, rowid):
|
||
|
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]
|
||
|
self.iso_639_1 = language[3]
|
||
|
self.translation = _translator_language(self.name)
|
||
|
|
||
|
@classmethod
|
||
|
def get_language(cls, code, codec):
|
||
|
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))
|
||
|
|
||
|
@classmethod
|
||
|
def by_iso_639_2B(cls, code):
|
||
|
return Language.get_language(code, 'iso_639_2B')
|
||
|
|
||
|
@classmethod
|
||
|
def by_iso_639_2T(cls, code):
|
||
|
return Language.get_language(code, 'iso_639_2T')
|
||
|
|
||
|
@classmethod
|
||
|
def by_iso_639_1(cls, code):
|
||
|
return Language.get_language(code, 'iso_639_1')
|
||
|
|
||
|
|
||
|
def code_to_name(code, separator='_'):
|
||
|
"""
|
||
|
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 '{} ({})'.format(lang, country)
|
||
|
else:
|
||
|
return Language.by_iso_639_1(code[0]).translation
|