From c78ebcf1728119572303501a0eb70f8ceed2ecd0 Mon Sep 17 00:00:00 2001 From: Loren Eteval Date: Thu, 20 Aug 2026 21:49:52 +0800 Subject: [PATCH] Separate protocol action and editor titles Signed-off-by: Loren Eteval --- Furious/Backends/ExternalCore/Protocols.py | 22 ++++--- Furious/Backends/Hysteria1/Protocols.py | 20 ++++--- Furious/Backends/Hysteria2/Protocols.py | 14 +++-- Furious/Backends/Xray/Protocols.py | 56 ++++++++++------- Furious/Externals/GenTranslation.py | 70 +++++++++++++++++++++- Furious/Plugins/API.py | 3 +- Furious/Plugins/Registry.py | 3 + Furious/Widget/ServerTableView.py | 21 ++++--- Furious/Window/HomePage.py | 14 +++-- 9 files changed, 159 insertions(+), 64 deletions(-) diff --git a/Furious/Backends/ExternalCore/Protocols.py b/Furious/Backends/ExternalCore/Protocols.py index e35b6c6..677a3c6 100644 --- a/Furious/Backends/ExternalCore/Protocols.py +++ b/Furious/Backends/ExternalCore/Protocols.py @@ -38,24 +38,28 @@ def _placeholder(value): _ = _placeholder -_TRANSLATABLE = (_('Add External Core...'),) +_TRANSLATABLE = ( + _('Add External Core...'), + _('Add External Core'), +) class ExternalCoreProtocolHandler(ProtocolHandler): """Own local External Core mappings while declining URI import/export.""" descriptor = ProtocolDescriptor( - EXTERNAL_CORE_TYPE, - 'External Core', - 'Add External Core...', - 100, - True, - { + id=EXTERNAL_CORE_TYPE, + displayName='External Core', + addActionText='Add External Core...', + editorWindowTitle='Add External Core', + menuOrder=100, + separatorBefore=True, + configurationSchema={ 'type': 'object', 'required': ('type', 'executable', 'arguments', 'environment'), }, - True, - False, + translatable=True, + subscriptionImportable=False, ) schemes = tuple() diff --git a/Furious/Backends/Hysteria1/Protocols.py b/Furious/Backends/Hysteria1/Protocols.py index 7fd4993..3b2f427 100644 --- a/Furious/Backends/Hysteria1/Protocols.py +++ b/Furious/Backends/Hysteria1/Protocols.py @@ -42,20 +42,24 @@ def _placeholder(x): _ = _placeholder -_TRANSLATABLE = (_('Add Hysteria1 Server...'),) +_TRANSLATABLE = ( + _('Add Hysteria1 Server...'), + _('Add Hysteria1 Server'), +) class Hysteria1ProtocolHandler(ProtocolHandler): """Own Hysteria 1 URI, mapping, validation, and export behavior.""" descriptor = ProtocolDescriptor( - 'hysteria1', - 'Hysteria1', - 'Add Hysteria1 Server...', - 50, - True, - {'type': 'object', 'required': ('server',)}, - True, + id='hysteria1', + displayName='Hysteria1', + addActionText='Add Hysteria1 Server...', + editorWindowTitle='Add Hysteria1 Server', + menuOrder=50, + separatorBefore=True, + configurationSchema={'type': 'object', 'required': ('server',)}, + translatable=True, ) schemes = ('hysteria',) diff --git a/Furious/Backends/Hysteria2/Protocols.py b/Furious/Backends/Hysteria2/Protocols.py index 0289025..5e6d374 100644 --- a/Furious/Backends/Hysteria2/Protocols.py +++ b/Furious/Backends/Hysteria2/Protocols.py @@ -42,17 +42,21 @@ def _placeholder(x): _ = _placeholder -_TRANSLATABLE = (_('Add Hysteria2 Server...'),) +_TRANSLATABLE = ( + _('Add Hysteria2 Server...'), + _('Add Hysteria2 Server'), +) class Hysteria2ProtocolHandler(ProtocolHandler): """Own Hysteria 2 URI, mapping, validation, and export behavior.""" descriptor = ProtocolDescriptor( - 'hysteria2', - 'Hysteria2', - 'Add Hysteria2 Server...', - 60, + id='hysteria2', + displayName='Hysteria2', + addActionText='Add Hysteria2 Server...', + editorWindowTitle='Add Hysteria2 Server', + menuOrder=60, configurationSchema={'type': 'object', 'required': ('server', 'auth')}, translatable=True, ) diff --git a/Furious/Backends/Xray/Protocols.py b/Furious/Backends/Xray/Protocols.py index d3c98ef..3815096 100644 --- a/Furious/Backends/Xray/Protocols.py +++ b/Furious/Backends/Xray/Protocols.py @@ -172,19 +172,25 @@ _ = _placeholder _TRANSLATABLE = ( _('Add VMess Server...'), + _('Add VMess Server'), _('Add VLESS Server...'), + _('Add VLESS Server'), _('Add Shadowsocks Server...'), + _('Add Shadowsocks Server'), _('Add Trojan Server...'), + _('Add Trojan Server'), _('Add SOCKS Server...'), + _('Add SOCKS Server'), ) XRAY_PROTOCOL_HANDLERS = ( XrayProtocolHandler( ProtocolDescriptor( - 'VMess', - 'VMess', - 'Add VMess Server...', - 10, + id='VMess', + displayName='VMess', + addActionText='Add VMess Server...', + editorWindowTitle='Add VMess Server', + menuOrder=10, configurationSchema={ 'type': 'object', 'required': ('outbounds',), @@ -197,10 +203,11 @@ XRAY_PROTOCOL_HANDLERS = ( ), XrayProtocolHandler( ProtocolDescriptor( - 'VLESS', - 'VLESS', - 'Add VLESS Server...', - 20, + id='VLESS', + displayName='VLESS', + addActionText='Add VLESS Server...', + editorWindowTitle='Add VLESS Server', + menuOrder=20, configurationSchema={ 'type': 'object', 'required': ('outbounds',), @@ -213,10 +220,11 @@ XRAY_PROTOCOL_HANDLERS = ( ), XrayProtocolHandler( ProtocolDescriptor( - 'Shadowsocks', - 'Shadowsocks', - 'Add Shadowsocks Server...', - 30, + id='Shadowsocks', + displayName='Shadowsocks', + addActionText='Add Shadowsocks Server...', + editorWindowTitle='Add Shadowsocks Server', + menuOrder=30, configurationSchema={ 'type': 'object', 'required': ('outbounds',), @@ -229,10 +237,11 @@ XRAY_PROTOCOL_HANDLERS = ( ), XrayProtocolHandler( ProtocolDescriptor( - 'Trojan', - 'Trojan', - 'Add Trojan Server...', - 40, + id='Trojan', + displayName='Trojan', + addActionText='Add Trojan Server...', + editorWindowTitle='Add Trojan Server', + menuOrder=40, configurationSchema={ 'type': 'object', 'required': ('outbounds',), @@ -245,17 +254,18 @@ XRAY_PROTOCOL_HANDLERS = ( ), SocksProtocolHandler( ProtocolDescriptor( - 'SOCKS', - 'SOCKS', - 'Add SOCKS Server...', - 70, - True, - { + id='SOCKS', + displayName='SOCKS', + addActionText='Add SOCKS Server...', + editorWindowTitle='Add SOCKS Server', + menuOrder=70, + separatorBefore=True, + configurationSchema={ 'type': 'object', 'required': ('outbounds',), 'proxyProtocol': 'socks', }, - True, + translatable=True, ), SOCKS_URI_SCHEMES, 'URI2ProxyOutboundObjectSocks', diff --git a/Furious/Externals/GenTranslation.py b/Furious/Externals/GenTranslation.py index 46ec9c8..3712672 100644 --- a/Furious/Externals/GenTranslation.py +++ b/Furious/Externals/GenTranslation.py @@ -1,7 +1,7 @@ TRANSLATION = { "Delete": { "source": [ - "Furious.Backends.Xray.AssetListWidget", + "Furious.Backends.Xray.AssetWindow", "Furious.Backends.Xray.RoutingWindow", "Furious.Qt.QtWidgets", "Furious.Widget.ServerTableView", @@ -285,6 +285,7 @@ TRANSLATION = { }, "Close Window": { "source": [ + "Furious.Backends.Xray.AssetWindow", "Furious.Backends.Xray.RoutingWindow", "Furious.Window.TextEditorWindow" ], @@ -692,8 +693,7 @@ TRANSLATION = { }, "Exit": { "source": [ - "Furious.Actions.Exit", - "Furious.Backends.Xray.AssetWindow" + "Furious.Actions.Exit" ], "RU": "Выход", "ZH": "退出", @@ -3207,5 +3207,69 @@ TRANSLATION = { "RU": "Статистика трафика", "ZH": "流量统计", "isReviewed": "True" + }, + "Add External Core": { + "source": [ + "Furious.Backends.ExternalCore.Protocols" + ], + "RU": "Добавить внешнее ядро", + "ZH": "添加外部Core", + "isReviewed": "True" + }, + "Add Hysteria1 Server": { + "source": [ + "Furious.Backends.Hysteria1.Protocols" + ], + "RU": "Добавить сервер Hysteria 1", + "ZH": "添加Hysteria1服务器", + "isReviewed": "True" + }, + "Add Hysteria2 Server": { + "source": [ + "Furious.Backends.Hysteria2.Protocols" + ], + "RU": "Добавить сервер Hysteria 2", + "ZH": "添加Hysteria2服务器", + "isReviewed": "True" + }, + "Add VMess Server": { + "source": [ + "Furious.Backends.Xray.Protocols" + ], + "RU": "Добавить сервер VMess", + "ZH": "添加VMess服务器", + "isReviewed": "True" + }, + "Add VLESS Server": { + "source": [ + "Furious.Backends.Xray.Protocols" + ], + "RU": "Добавить сервер VLESS", + "ZH": "添加VLESS服务器", + "isReviewed": "True" + }, + "Add Shadowsocks Server": { + "source": [ + "Furious.Backends.Xray.Protocols" + ], + "RU": "Добавить сервер Shadowsocks", + "ZH": "添加Shadowsocks服务器", + "isReviewed": "True" + }, + "Add Trojan Server": { + "source": [ + "Furious.Backends.Xray.Protocols" + ], + "RU": "Добавить сервер Trojan", + "ZH": "添加Trojan服务器", + "isReviewed": "True" + }, + "Add SOCKS Server": { + "source": [ + "Furious.Backends.Xray.Protocols" + ], + "RU": "Добавить сервер SOCKS", + "ZH": "添加SOCKS服务器", + "isReviewed": "True" } } diff --git a/Furious/Plugins/API.py b/Furious/Plugins/API.py index 0095d86..fc3491c 100644 --- a/Furious/Plugins/API.py +++ b/Furious/Plugins/API.py @@ -201,6 +201,7 @@ class ProtocolDescriptor: id: str displayName: str addActionText: str + editorWindowTitle: str menuOrder: int = 0 separatorBefore: bool = False configurationSchema: Mapping[str, Any] = field(default_factory=dict) @@ -273,7 +274,7 @@ class ProtocolHandler(PluginCapability): """Own one protocol's validation and serialization behavior.""" capabilityKind = CapabilityKind.Protocol - descriptor = ProtocolDescriptor('', '', '') + descriptor = ProtocolDescriptor('', '', '', '') schemes = tuple() @property diff --git a/Furious/Plugins/Registry.py b/Furious/Plugins/Registry.py index cb2ba30..4468296 100644 --- a/Furious/Plugins/Registry.py +++ b/Furious/Plugins/Registry.py @@ -205,6 +205,9 @@ class PluginRegistry: if not isinstance(descriptor.addActionText, str): raise TypeError('protocol add-action text must be a string') + if not isinstance(descriptor.editorWindowTitle, str): + raise TypeError('protocol editor-window title must be a string') + if not isinstance(descriptor.configurationSchema, Mapping): raise TypeError('protocol configuration schema must be a mapping') diff --git a/Furious/Widget/ServerTableView.py b/Furious/Widget/ServerTableView.py index 296effa..347cb9a 100644 --- a/Furious/Widget/ServerTableView.py +++ b/Furious/Widget/ServerTableView.py @@ -1789,23 +1789,26 @@ class ServerTableView( """Show all, manual, or one subscription group's profiles.""" self.proxyModel.setSubscriptionFilter(unique) - def addServerViaGui( - self, - protocol, - windowTitle: str = APPLICATION_NAME, - **kwargs, - ): + def addServerViaGui(self, protocol, **kwargs): """Add server via GUI.""" factory = blankProfile(protocol) - guiEditor = self.getGuiEditorByFactory(factory, **kwargs) + windowTitle, translatable = ( + kwargs.pop('windowTitle', APPLICATION_NAME), + kwargs.pop('translatable', True), + ) + + if translatable is True: + windowTitle = _(windowTitle) + + guiEditor = self.getGuiEditorByFactory( + factory, windowTitle=windowTitle, translatable=translatable, **kwargs + ) if guiEditor is None: # Unrecognized. Do nothing return - guiEditor.setWindowTitle(windowTitle) - try: guiEditor.factoryToInput(factory) except Exception as ex: diff --git a/Furious/Window/HomePage.py b/Furious/Window/HomePage.py index c4ae006..763d38c 100644 --- a/Furious/Window/HomePage.py +++ b/Furious/Window/HomePage.py @@ -670,19 +670,21 @@ class HomePage(Mixins.QTranslatable, QMainWindow): if descriptor.separatorBefore and serverActions: serverActions.append(AppQSeparator()) - actionText = ( - _(descriptor.addActionText) - if descriptor.translatable - else descriptor.addActionText - ) + if descriptor.translatable: + actionText = _(descriptor.addActionText) + else: + actionText = descriptor.addActionText + serverActions.append( AppQAction( actionText, callback=functools.partial( self.userServersQTableWidget.addServerViaGui, descriptor.id, - actionText, + # By default, editor window title is translatable + windowTitle=_(descriptor.editorWindowTitle), ), + translatable=descriptor.translatable, ) )