import inspect import hjson from core.decorators import instance from core.event_service import EventService from core.logger import Logger from core.setting_service import SettingService from core.setting_types import TextSettingType from core.igncore import IgnCore from core.util import Util # noinspection PyDefaultArgument @instance() class TranslationService: strings = {} translation_callbacks = {} language = None lang_codes = ["en_US", "de_DE"] LANGUAGE_SETTING = "language" def __init__(self): self.logger = Logger(__name__) def inject(self, registry): self.setting_service: SettingService = registry.get_instance("setting_service") self.event_service: EventService = registry.get_instance("event_service") self.util: Util = registry.get_instance("util") self.bot: IgnCore = registry.get_instance("bot") def pre_start(self): self.event_service.register_event_type("reload_translation") def start(self): self.setting_service.register("core.system", self.LANGUAGE_SETTING, "en_US", TextSettingType(self.lang_codes), "Language of the Bot") self.language = self.setting_service.get_value(self.LANGUAGE_SETTING) self.register_translation("global", self.load_global_msg) self.setting_service.register_change_listener(self.LANGUAGE_SETTING, self.language_setting_changed) def register_translation(self, category, callback): """ Call during start Args: category: str callback: () -> {} """ if len(inspect.signature(callback).parameters) != 0: raise Exception( "Incorrect number of arguments for handler '%s.%s()'" % (callback.__module__, callback.__name__)) if self.translation_callbacks.get(category) is None: self.translation_callbacks[category] = [] self.translation_callbacks[category].append(callback) self.update_msg(category, callback) def load_global_msg(self): with open("core/global.msg", mode="r", encoding="UTF-8") as f: return hjson.load(f) def language_setting_changed(self, name, old_value, new_value): if name == self.LANGUAGE_SETTING and new_value != old_value: self.reload_translation(new_value) # This method will load another language, defined in the param 'lang' def reload_translation(self, lang): self.event_service.fire_event("reload_translation") self.language = lang for k1 in self.strings: for callback in self.translation_callbacks.get(k1): self.update_msg(k1, callback) # updates the msgs def update_msg(self, category, callback): data = callback() for k in data: if category not in self.strings: self.strings[category] = {} self.strings[category][k] = data[k].get(self.language) or data[k].get("en_US") # # the param 'variables' accepts dictionaries ONLY. # def get_response(self, category, key, variables={}): msg = "" try: val = self.strings[category][key] if isinstance(val, list): for line in val: msg += line.format(**variables) else: msg = val.format(**variables) except KeyError as e: self.logger.error(f"translating error category '{category}' and key '{key}' with params: {variables}", e) msg = "Error translating category: {mod} key: {key}" \ " with params: {params}".format(mod=category, key=key, params=variables) finally: return msg