Files
OutFleet/telegram_bot/localization.py
2025-08-15 16:33:23 +03:00

267 lines
18 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""
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:**",
# Admin messages
'admin_new_request_notification': "🔔 **New Access Request**\n\n👤 **User:** {user_info}\n📱 **Telegram:** {telegram_info}\n📅 **Date:** {date}\n\n💬 **Message:** {message}",
'admin_access_requests_title': "📋 **Pending Access Requests**",
'admin_no_pending_requests': "✅ No pending access requests",
'admin_request_item': "👤 **{user_info}**\n📅 {date}\n💬 _{message_preview}_",
'admin_choose_subscription_groups': "📦 **Choose Subscription Groups for {user_info}:**\n\nSelect groups to assign to this user:",
'admin_approval_success': "✅ **Request Approved!**\n\n👤 User: {user_info}\n📦 Groups: {groups}\n\nUser has been notified and given access.",
'admin_rejection_success': "❌ **Request Rejected**\n\n👤 User: {user_info}\n\nUser has been notified.",
'admin_request_already_processed': "⚠️ This request has already been processed by another admin.",
'admin_error_processing': "❌ Error processing request: {error}",
'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",
# Admin buttons
'access_requests': "📋 Access Requests",
'approve': "✅ Approve",
'reject': "❌ Reject",
'details': "👁 Details",
'confirm_approval': "✅ Confirm Approval",
'confirm_rejection': "❌ Confirm Rejection",
'cancel': "🚫 Cancel"
}
},
'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': "🔒 **Серверы в группе:**",
# Admin messages
'admin_new_request_notification': "🔔 **Новый запрос на доступ**\n\n👤 **Пользователь:** {user_info}\n📱 **Telegram:** {telegram_info}\n📅 **Дата:** {date}\n\n💬 **Сообщение:** {message}",
'admin_access_requests_title': "📋 **Ожидающие запросы на доступ**",
'admin_no_pending_requests': "✅ Нет ожидающих запросов на доступ",
'admin_request_item': "👤 **{user_info}**\n📅 {date}\n💬 _{message_preview}_",
'admin_choose_subscription_groups': "📦 **Выберите группы подписки для {user_info}:**\n\nВыберите группы для назначения этому пользователю:",
'admin_approval_success': "✅ **Запрос одобрен!**\n\n👤 Пользователь: {user_info}\n📦 Группы: {groups}\n\nПользователь уведомлен и получил доступ.",
'admin_rejection_success': "❌ **Запрос отклонен**\n\n👤 Пользователь: {user_info}\n\nПользователь уведомлен.",
'admin_request_already_processed': "⚠️ Этот запрос уже обработан другим администратором.",
'admin_error_processing': "❌ Ошибка обработки запроса: {error}",
'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': "🔑 Запросить доступ",
# Admin buttons
'access_requests': "📋 Запросы на доступ",
'approve': "✅ Одобрить",
'reject': "❌ Отклонить",
'details': "👁 Подробности",
'confirm_approval': "✅ Подтвердить одобрение",
'confirm_rejection': "❌ Подтвердить отклонение",
'cancel': "🚫 Отмена"
}
}
}
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)