diff --git a/addons/source-python/packages/source-python/commands/typed.py b/addons/source-python/packages/source-python/commands/typed.py old mode 100644 new mode 100755 index dc2cde999..d89438d32 --- a/addons/source-python/packages/source-python/commands/typed.py +++ b/addons/source-python/packages/source-python/commands/typed.py @@ -32,6 +32,8 @@ from messages import SayText2 from messages import TextMsg from messages import HudDestination +# Translations +from translations.strings import TranslationStrings # ============================================================================= @@ -82,11 +84,11 @@ # ============================================================================= # >> EXCEPTIONS # ============================================================================= -# TODO: -# We probably need to update these exceptions if we want to add translations. class ValidationError(Exception): - def __init__(self, message=''): + def __init__(self, message='', language=None, **tokens): self.message = message + self.language = language + self.tokens = tokens class ArgumentError(ValidationError): pass class ArgumentNumberMismatch(ArgumentError): pass @@ -488,13 +490,17 @@ def __init__(self, command, typed_command_cls, index=None, team_only=None): self.index = index self.team_only = team_only - def reply(self, msg): + def reply(self, msg, language=None, **tokens): """Reply to the command issuer. - :param str msg: + :param str/TranslationStrings msg: Message to send. + :param str language: + Language to be used. + :param tokens: + Translation tokens for message. """ - self.typed_command_cls.send_message(self, msg) + self.typed_command_cls.send_message(self, msg, language, **tokens) def is_private_command(self): """Return ``True`` if it's a private command. @@ -582,13 +588,12 @@ def on_command(cls, command, *args): Parse the command, clean its arguments and execute the callback. """ - # TODO: Translations! info = CommandInfo(command, cls, *args) try: command_node, args = cls.parser.parse_command(info.command) result = cls.on_clean_command(info, command_node, args) except ValidationError as e: - info.reply(e.message) + info.reply(e.message, e.language, **e.tokens) else: if result is None: return info.auto_command_return @@ -623,7 +628,7 @@ def manager(self): raise NotImplementedError('Needs to be implemented by a sub class.') @staticmethod - def send_message(command_info, message): + def send_message(command_info, message, language=None, **tokens): """Send a message.""" raise NotImplementedError('Needs to be implemented by a sub class.') @@ -643,7 +648,11 @@ class TypedServerCommand(_TypedCommand): manager = server_command_manager @staticmethod - def send_message(command_info, message): + def send_message(command_info, message, language=None, **tokens): + # Translate the message if it's a :class:`TranslationStrings` object. + if isinstance(message, TranslationStrings): + message = message.get_string(language, **tokens) + logger.log_message(message) @classmethod @@ -684,8 +693,8 @@ class TypedClientCommand(_TypedPlayerCommand): manager = client_command_manager @staticmethod - def send_message(command_info, message): - TextMsg(message, HudDestination.CONSOLE).send(command_info.index) + def send_message(command_info, message, language=None, **tokens): + TextMsg(message, HudDestination.CONSOLE).send(command_info.index, **tokens) @classmethod def get_auto_command_return(cls, info): @@ -699,8 +708,8 @@ class TypedSayCommand(_TypedPlayerCommand): manager = say_command_manager @staticmethod - def send_message(command_info, message): - SayText2(message).send(command_info.index) + def send_message(command_info, message, language=None, **tokens): + SayText2(message).send(command_info.index, **tokens) @classmethod def get_auto_command_return(cls, info): diff --git a/addons/source-python/packages/source-python/menus/base.py b/addons/source-python/packages/source-python/menus/base.py old mode 100644 new mode 100755 index 1b66fcf43..6da8e9492 --- a/addons/source-python/packages/source-python/menus/base.py +++ b/addons/source-python/packages/source-python/menus/base.py @@ -10,10 +10,12 @@ from collections import defaultdict # Math import math +# Weakref +from weakref import WeakValueDictionary # Source.Python Imports # Core -from core import AutoUnload +from core import WeakAutoUnload # Filters from filters.recipients import RecipientFilter # Listeners @@ -36,10 +38,10 @@ def __init__(self): self.options = {} -class _BaseMenu(AutoUnload, list): +class _BaseMenu(WeakAutoUnload, list): """The base menu. Every menu class should inherit from this class.""" - _instances = {} + _instances = WeakValueDictionary() def __init__(self, data=None, select_callback=None, build_callback=None, close_callback=None): """Initialize the menu. @@ -78,10 +80,12 @@ def __init__(self, data=None, select_callback=None, build_callback=None, close_c def _unload_instance(self): """Close this menu object for every player.""" # Just close all open menus, which will remove all instances from the - # queues + # queues. self.close() - # Also remove the instance from the _instances dict + # Also remove the instance from the _instances dict. + # This process is necessary because there is no guarantee that + # the instance will be destroyed when the plugin is unloaded. del self._instances[id(self)] def _unload_player(self, player_index):