From 6075e5513b8feacb42e8a9d712c6c9540ddc2af5 Mon Sep 17 00:00:00 2001 From: Davte Date: Fri, 19 Jul 2019 16:40:46 +0200 Subject: [PATCH] Support for multiple languages --- davtelepot/__init__.py | 2 +- davtelepot/administration_tools.py | 2 - davtelepot/bot.py | 4 +- davtelepot/languages.py | 88 ++++++++++++++++++++++++++++++ 4 files changed, 92 insertions(+), 4 deletions(-) create mode 100644 davtelepot/languages.py diff --git a/davtelepot/__init__.py b/davtelepot/__init__.py index 31bd97a..4860f36 100644 --- a/davtelepot/__init__.py +++ b/davtelepot/__init__.py @@ -14,7 +14,7 @@ __author__ = "Davide Testa" __email__ = "davide@davte.it" __credits__ = ["Marco Origlia", "Nick Lee @Nickoala"] __license__ = "GNU General Public License v3.0" -__version__ = "2.1.16" +__version__ = "2.1.17" __maintainer__ = "Davide Testa" __contact__ = "t.me/davte" diff --git a/davtelepot/administration_tools.py b/davtelepot/administration_tools.py index 508d259..3d22aab 100644 --- a/davtelepot/administration_tools.py +++ b/davtelepot/administration_tools.py @@ -491,8 +491,6 @@ async def _talk_button(update, bot): def init(bot): """Assign parsers, commands, buttons and queries to given `bot`.""" - if not hasattr(bot, 'messages'): - bot.messages = dict() bot.messages['talk'] = TALK_MESSAGES with bot.db as db: if 'talking_sessions' not in db.tables: diff --git a/davtelepot/bot.py b/davtelepot/bot.py index 0fe1912..d4ea594 100644 --- a/davtelepot/bot.py +++ b/davtelepot/bot.py @@ -47,6 +47,7 @@ from aiohttp import web # Project modules from .api import TelegramBot, TelegramError from .database import ObjectWithDatabase +from .languages import MultiLanguageObject from .utilities import ( escape_html_chars, extract, get_secure_key, make_inline_query_answer, make_lines_of_buttons, remove_html_tags @@ -56,7 +57,7 @@ from .utilities import ( logging.getLogger('aiohttp').setLevel(logging.WARNING) -class Bot(TelegramBot, ObjectWithDatabase): +class Bot(TelegramBot, ObjectWithDatabase, MultiLanguageObject): """Simple Bot object, providing methods corresponding to Telegram bot API. Multiple Bot() instances may be run together, along with a aiohttp web app. @@ -107,6 +108,7 @@ class Bot(TelegramBot, ObjectWithDatabase): # Call superclasses constructors with proper arguments TelegramBot.__init__(self, token) ObjectWithDatabase.__init__(self, database_url=database_url) + MultiLanguageObject.__init__(self) self._path = None self.preliminary_tasks = [] self.final_tasks = [] diff --git a/davtelepot/languages.py b/davtelepot/languages.py new file mode 100644 index 0000000..b292755 --- /dev/null +++ b/davtelepot/languages.py @@ -0,0 +1,88 @@ +"""Bot support for multiple languages.""" + +# Standard library modules +import logging + +# Project modules +from .utilities import extract + + +class MultiLanguageObject(object): + """Make bot inherit from this class to make it support multiple languages. + + Call MultiLanguage().get_message( + field1, field2, ..., + update, user_record, language, + format_kwarg1, format_kwarg2, ... + ) to get the corresponding message in the selected language. + """ + + def __init__(self): + """Instantiate MultiLanguage object, setting self.messages.""" + self.messages = dict() + + def get_message(self, *fields, update=dict(), user_record=dict(), + language=None, **format_kwargs): + """Given a list of strings (`fields`), return proper message. + + Language will be selected in this order: + - `language` parameter + - `user_record['selected_language_code']`: language selected by user + - `update['language_code']`: language of incoming telegram update + - Fallback to English if none of the above fits + + `format_kwargs` will be passed to format function on the result. + """ + # Choose language + if ( + language is None + and 'selected_language_code' in user_record + ): + language = user_record['selected_language_code'] + if ( + language is None + and 'from' in update + and 'language_code' in update['from'] + ): + language = update['from']['language_code'] + if language is None: + language = 'en' + # Find result for `language` + result = self.messages + for field in fields: + if field not in result: + logging.error( + "Please define self.message{f}".format( + f=''.join( + '[\'{field}\']'.format( + field=field + ) + for field in fields + ) + ) + ) + return "Invalid message!" + result = result[field] + if language not in result: + # For specific languages, try generic ones + language = extract( + language, + ender='-' + ) + if language not in result: + language = 'en' + if language not in result: + logging.error( + "Please define self.message{f}['en']".format( + f=''.join( + '[\'{field}\']'.format( + field=field + ) + for field in fields + ) + ) + ) + return "Invalid message!" + return result[language].format( + **format_kwargs + )