mirror of
https://github.com/house-of-vanity/OutFleet.git
synced 2025-08-21 14:37:16 +00:00
227 lines
15 KiB
Python
227 lines
15 KiB
Python
"""
|
||
Message localization for Telegram bot
|
||
"""
|
||
from typing import Optional, Dict, Any
|
||
import logging
|
||
|
||
logger = logging.getLogger(__name__)
|
||
|
||
# Translation dictionaries
|
||
MESSAGES = {
|
||
'en': {
|
||
'help_text': "📋 Welcome! Use buttons below to navigate.\n\n📊 Access - View your VPN subscriptions\n\nFor support contact administrator.",
|
||
'access_request_created': "Access request created, please wait.",
|
||
'new_user_welcome': "Welcome! To get access to VPN services, please request access using the button below.",
|
||
'pending_request_msg': "Your access request is pending approval. Please wait for administrator to review it.",
|
||
'choose_subscription': "**Choose subscription option:**",
|
||
'all_in_one_desc': "🌍 **All-in-one** - Get all subscriptions in one link",
|
||
'group_desc': "**Group** - Get specific group subscription",
|
||
'select_option': "Select an option below:",
|
||
'no_subscriptions': "❌ You don't have any active Xray subscriptions.\n\nPlease contact administrator for access.",
|
||
'group_subscription': "**Group: {group_name}**",
|
||
'subscription_link': "**🔗 Subscription Link:**",
|
||
'web_portal': "**🌐 Web Portal:**",
|
||
'tap_to_copy': "_Tap the subscription link to copy it. Use it in your Xray client._",
|
||
'all_in_one_subscription': "🌍 **All-in-one Subscription**",
|
||
'your_access_includes': "**Your Access Includes:**",
|
||
'universal_subscription_link': "**🔗 Universal Subscription Link:**",
|
||
'all_subscriptions_note': "_This link includes all your active subscriptions. Tap to copy._",
|
||
'error_loading_subscriptions': "❌ Error loading subscriptions. Please try again later.",
|
||
'error_loading_group': "❌ Error loading group subscription. Please try again later.",
|
||
'received_content': "Received your {message_type}. An administrator will review it.",
|
||
'approval_notification': "✅ Access approved!",
|
||
'content_types': {
|
||
'photo': 'photo',
|
||
'document': 'document',
|
||
'voice': 'voice',
|
||
'video': 'video',
|
||
'content': 'content'
|
||
},
|
||
'guide_title': "📖 **VPN Setup Guide**",
|
||
'guide_choose_platform': "Select your device platform:",
|
||
'web_portal_description': "_Web portal shows your access list on one convenient page with some statistics._",
|
||
'servers_in_group': "🔒 **Servers in group:**",
|
||
'android_guide': "🤖 **Android Setup Guide**\n\n**Step 1: Install the app**\nDownload V2RayTUN from Google Play:\nhttps://play.google.com/store/apps/details?id=com.v2raytun.android\n\n**Step 2: Add subscription**\n• Open the app\n• Tap the **+** button in the top right corner\n• Paste your subscription link from the bot\n• The app will automatically load all VPN servers\n\n**Step 3: Connect**\n• Choose a server from the list\n• Tap **Connect**\n• All your traffic will now go through VPN\n\n**💡 Useful settings:**\n• In settings, enable direct access for banking apps and local sites\n• You can choose specific apps to use VPN while others use direct connection\n\n**🔄 If VPN stops working:**\nTap the refresh icon next to the server list to update your subscription.",
|
||
'ios_guide': " **iOS Setup Guide**\n\n**Step 1: Install the app**\nDownload V2RayTUN from App Store:\nhttps://apps.apple.com/us/app/v2raytun/id6476628951\n\n**Step 2: Add subscription**\n• Open the app\n• Tap the **+** button in the top right corner\n• Paste your subscription link from the bot\n• The app will automatically load all VPN servers\n\n**Step 3: Connect**\n• Choose a server from the list\n• Tap **Connect**\n• All your traffic will now go through VPN\n\n**⚠️ Note for iOS users:**\nCurrently, only VLESS protocol works reliably on iOS. Other protocols may have connectivity issues.\n\n**💡 Useful settings:**\n• In settings, enable direct access for banking apps and local sites to improve performance\n\n**🔄 If VPN stops working:**\nTap the refresh icon next to the server list to update your subscription.",
|
||
'buttons': {
|
||
'access': "🌍 Get access",
|
||
'guide': "📖 Guide",
|
||
'android': "🤖 Android",
|
||
'ios': " iOS",
|
||
'web_portal': "🌐 Web Portal",
|
||
'all_in_one': "🌍 All-in-one",
|
||
'back': "⬅️ Back",
|
||
'group_prefix': "Group: ",
|
||
'request_access': "🔑 Request Access"
|
||
}
|
||
},
|
||
'ru': {
|
||
'help_text': "📋 Добро пожаловать! Используйте кнопки ниже для навигации.\n\n📊 Доступ - Просмотр VPN подписок\n\nДля поддержки обратитесь к администратору.",
|
||
'access_request_created': "Запрос на доступ создан, ожидайте.",
|
||
'new_user_welcome': "Добро пожаловать! Для получения доступа к VPN сервисам, пожалуйста запросите доступ с помощью кнопки ниже.",
|
||
'pending_request_msg': "Ваш запрос на доступ ожидает одобрения. Пожалуйста, дождитесь рассмотрения администратором.",
|
||
'choose_subscription': "**Выберите вариант подписки:**",
|
||
'all_in_one_desc': "🌍 **Все в одном** - Получить все подписки в одной ссылке",
|
||
'group_desc': "**Группа** - Получить подписку на группу",
|
||
'select_option': "Выберите вариант ниже:",
|
||
'no_subscriptions': "❌ У вас нет активных Xray подписок.\n\nОбратитесь к администратору для получения доступа.",
|
||
'group_subscription': "**Группа: {group_name}**",
|
||
'subscription_link': "**🔗 **",
|
||
'web_portal': "**🌐 Веб-портал пользователя:**",
|
||
'tap_to_copy': "_Нажмите на ссылку чтобы скопировать. Используйте в вашем Xray клиенте как подписку._",
|
||
'all_in_one_subscription': "🌍 **Подписка «Все в одном»**",
|
||
'your_access_includes': "**Ваш доступ включает:**",
|
||
'universal_subscription_link': "**🔗 Универсальная ссылка на подписку:**",
|
||
'all_subscriptions_note': "_Эта ссылка включает все ваши активные подписки. Нажмите чтобы скопировать._",
|
||
'error_loading_subscriptions': "❌ Ошибка загрузки подписок. Попробуйте позже.",
|
||
'error_loading_group': "❌ Ошибка загрузки подписки группы. Попробуйте позже.",
|
||
'received_content': "Получен ваш {message_type}. Администратор его рассмотрит.",
|
||
'approval_notification': "✅ Доступ одобрен!",
|
||
'content_types': {
|
||
'photo': 'фото',
|
||
'document': 'документ',
|
||
'voice': 'голосовое сообщение',
|
||
'video': 'видео',
|
||
'content': 'контент'
|
||
},
|
||
'guide_title': "📖 **Руководство по настройке VPN**",
|
||
'guide_choose_platform': "Выберите платформу вашего устройства:",
|
||
'web_portal_description': "_Веб-портал показывает список ваших доступов на одной удобной странице с некоторой статистикой._",
|
||
'servers_in_group': "🔒 **Серверы в группе:**",
|
||
'android_guide': "🤖 **Руководство для Android**\n\n**Шаг 1: Установите приложение**\nСкачайте V2RayTUN из Google Play:\nhttps://play.google.com/store/apps/details?id=com.v2raytun.android\n\n**Шаг 2: Добавьте подписку**\n• Откройте приложение\n• Нажмите кнопку **+** в правом верхнем углу\n• Вставьте ссылку на подписку из бота\n• Приложение автоматически загрузит список VPN серверов\n\n**Шаг 3: Подключитесь**\n• Выберите сервер из списка\n• Нажмите **Подключиться**\n• Весь ваш трафик будет проходить через VPN\n\n**💡 Полезные настройки:**\n• В настройках включите прямой доступ для банковских приложений и местных сайтов\n• Вы можете выбрать конкретные приложения для использования VPN, в то время как остальные будут работать напрямую\n\n**🔄 Если VPN перестал работать:**\nНажмите иконку обновления рядом со списком серверов для обновления подписки.",
|
||
'ios_guide': " **Руководство для iOS**\n\n**Шаг 1: Установите приложение**\nСкачайте V2RayTUN из App Store:\nhttps://apps.apple.com/us/app/v2raytun/id6476628951\n\n**Шаг 2: Добавьте подписку**\n• Откройте приложение\n• Нажмите кнопку **+** в правом верхнем углу\n• Вставьте ссылку на подписку из бота\n• Приложение автоматически загрузит список VPN серверов\n\n**Шаг 3: Подключитесь**\n• Выберите сервер из списка\n• Нажмите **Подключиться**\n• Весь ваш трафик будет проходить через VPN\n\n**⚠️ Важно для пользователей iOS:**\nВ настоящее время на iOS стабильно работает только протокол VLESS. Другие протоколы могут иметь проблемы с подключением.\n\n**💡 Полезные настройки:**\n• В настройках включите прямой доступ для банковских приложений и местных сайтов для улучшения производительности\n\n**🔄 Если VPN перестал работать:**\nНажмите иконку обновления рядом со списком серверов для обновления подписки.",
|
||
'buttons': {
|
||
'access': "🌍 Получить VPN",
|
||
'guide': "📖 Гайд",
|
||
'android': "🤖 Android",
|
||
'ios': " iOS",
|
||
'web_portal': "🌐 Веб-портал",
|
||
'all_in_one': "🌍 Все в одном",
|
||
'back': "⬅️ Назад",
|
||
'group_prefix': "Группа: ",
|
||
'request_access': "🔑 Запросить доступ"
|
||
}
|
||
}
|
||
}
|
||
|
||
class MessageLocalizer:
|
||
"""Class for bot message localization"""
|
||
|
||
@staticmethod
|
||
def get_user_language(telegram_user) -> str:
|
||
"""
|
||
Determines user language from Telegram language_code
|
||
|
||
Args:
|
||
telegram_user: Telegram user object
|
||
|
||
Returns:
|
||
str: Language code ('ru' or 'en')
|
||
"""
|
||
if not telegram_user:
|
||
return 'en'
|
||
|
||
language_code = getattr(telegram_user, 'language_code', None)
|
||
|
||
if not language_code:
|
||
return 'en'
|
||
|
||
# Support Russian and English
|
||
if language_code.startswith('ru'):
|
||
return 'ru'
|
||
else:
|
||
return 'en'
|
||
|
||
@staticmethod
|
||
def get_message(key: str, language: str = 'en', **kwargs) -> str:
|
||
"""
|
||
Gets localized message
|
||
|
||
Args:
|
||
key: Message key
|
||
language: Language code
|
||
**kwargs: Formatting parameters
|
||
|
||
Returns:
|
||
str: Localized message
|
||
"""
|
||
try:
|
||
# Fallback to English if language not supported
|
||
if language not in MESSAGES:
|
||
language = 'en'
|
||
|
||
message = MESSAGES[language].get(key, MESSAGES['en'].get(key, f"Missing translation: {key}"))
|
||
|
||
# Format with parameters
|
||
if kwargs:
|
||
try:
|
||
message = message.format(**kwargs)
|
||
except (KeyError, ValueError) as e:
|
||
logger.warning(f"Error formatting message {key}: {e}")
|
||
|
||
return message
|
||
|
||
except Exception as e:
|
||
logger.error(f"Error getting message {key} for language {language}: {e}")
|
||
return f"Error: {key}"
|
||
|
||
@staticmethod
|
||
def get_button_text(button_key: str, language: str = 'en') -> str:
|
||
"""
|
||
Gets button text
|
||
|
||
Args:
|
||
button_key: Button key
|
||
language: Language code
|
||
|
||
Returns:
|
||
str: Button text
|
||
"""
|
||
try:
|
||
if language not in MESSAGES:
|
||
language = 'en'
|
||
|
||
buttons = MESSAGES[language].get('buttons', {})
|
||
return buttons.get(button_key, MESSAGES['en']['buttons'].get(button_key, button_key))
|
||
|
||
except Exception as e:
|
||
logger.error(f"Error getting button text {button_key} for language {language}: {e}")
|
||
return button_key
|
||
|
||
@staticmethod
|
||
def get_content_type_name(content_type: str, language: str = 'en') -> str:
|
||
"""
|
||
Gets localized content type name
|
||
|
||
Args:
|
||
content_type: Content type
|
||
language: Language code
|
||
|
||
Returns:
|
||
str: Localized name
|
||
"""
|
||
try:
|
||
if language not in MESSAGES:
|
||
language = 'en'
|
||
|
||
content_types = MESSAGES[language].get('content_types', {})
|
||
return content_types.get(content_type, content_type)
|
||
|
||
except Exception as e:
|
||
logger.error(f"Error getting content type {content_type} for language {language}: {e}")
|
||
return content_type
|
||
|
||
# Convenience functions for use in code
|
||
def get_localized_message(telegram_user, message_key: str, **kwargs) -> str:
|
||
"""Get localized message for user"""
|
||
language = MessageLocalizer.get_user_language(telegram_user)
|
||
return MessageLocalizer.get_message(message_key, language, **kwargs)
|
||
|
||
def get_localized_button(telegram_user, button_key: str) -> str:
|
||
"""Get localized button text for user"""
|
||
language = MessageLocalizer.get_user_language(telegram_user)
|
||
return MessageLocalizer.get_button_text(button_key, language)
|
||
|
||
def get_user_language(telegram_user) -> str:
|
||
"""Get user language"""
|
||
return MessageLocalizer.get_user_language(telegram_user) |