mirror of
https://github.com/house-of-vanity/OutFleet.git
synced 2025-08-21 14:37:16 +00:00
Added TG bot
This commit is contained in:
207
telegram_bot/localization.py
Normal file
207
telegram_bot/localization.py
Normal file
@@ -0,0 +1,207 @@
|
||||
"""
|
||||
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'
|
||||
},
|
||||
'buttons': {
|
||||
'access': "🌍 Get access",
|
||||
'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': 'контент'
|
||||
},
|
||||
'buttons': {
|
||||
'access': "🌍 Получить VPN",
|
||||
'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)
|
Reference in New Issue
Block a user