""" Internationalization module for the Lichess Telegram Bot Supports English and Russian languages """ from typing import Optional # Translation dictionary (English and Russian) TRANSLATIONS = { 'en': { # Start command 'start_message': ( "🎯 The bot tracks one or more players on Lichess.\n\n" "📈 It shows ratings, daily, yesterday and weekly activity.\n\n" "🧩 When specifying a user_token (with puzzle-read permission), you can also get puzzle data.\n\n" "⏱️ The bot supports automatic checks at specified intervals\n" "📨 …and sends a report if there was activity during that time.\n\n" "Example for a week:\n" "🧩 Puzzles: 114 (✅ 81 - ❌ 33)\n\n" "🔥 Blitz — 5 games • 🔴 -10\n" "Rating: 2245\n" "✅ Wins: 1\n" "❌ Losses: 3\n" "🤝 Draws: 1\n\n" "🐇 Rapid — 19 games • 🟢 +20\n" "Rating: 2248\n" "✅ Wins: 8\n" "❌ Losses: 4\n" "🤝 Draws: 7\n\n" "📋 Available commands:\n\n" "➕ /addgamer — Add a Lichess player to track (username only)\n" "🔑 /addtoken — Add a player with a token to get puzzle data\n" "👥 /getgamers — View statistics of your players\n" "🚫 /delgamer — Remove a player from the tracked list\n\n" "📅 /today — Statistics for today\n" "📆 /yesterday — Statistics for yesterday\n" "📆 /week — Statistics for the week\n" "📈 /lastYear_or_1000games — Statistics for the last year or last 1000 rated games\n\n" "⏱️ /setperiod — Set up periodic notifications for the active player\n" " ↳ (active player changes in the /getgamers menu)\n\n" "👤 /profile — View Lichess profile links for tracked players\n" "🌍 /set_lang — Select bot language (English / Russian)\n" "💬 /support — Contact the developer for support and feedback" ), # Add gamer commands 'addgamer_prompt': "👤 Enter the Lichess username of the player to track:", 'addtoken_prompt': ( "🔑 Enter the Lichess API token to get puzzle data.\n" "The token is created in profile settings — give it only puzzle:read permission.\n" "After that, the player corresponding to this token will be added." ), 'token_added': "✅ Token added for player {username}!", 'gamer_added_with_token': "✅ Player {username} added with token!", 'gamer_added': "✅ Player {username} successfully added!\n\nTo add another player, use /addgamer", 'invalid_token': "❌ Invalid token. Please try again.", 'token_username_error': "❌ Failed to get username from token. Please try again.", 'empty_username': "❌ Username cannot be empty. Please try again.", 'user_not_found': "❌ Player {username} not found on Lichess. Check the spelling of the name.", # Get gamers 'no_gamers': "📭 No players in database. Use /addgamer to add.", 'loading_ratings': "🔄 Loading player ratings...", 'select_active_gamer': "👥 Select active player:\n\n", 'active_gamer_set': "✅ Active player: {username}", 'gamer_not_found': "❌ Player not found", # Delete gamer 'no_gamers_to_delete': "📭 You have no tracked players.", 'loading_gamers': "🔄 Loading player list...", 'select_gamer_to_delete': "🗑️ Select player to delete:\n\n", 'gamer_deleted': "✅ Player {username} removed from tracked list.", 'active_gamer_deleted': "✅ Player {username} removed from tracked list.\n\n⚠️ You deleted the active player. Use the /getgamers command to select a player for which the /today, /yesterday, /week commands will work.", 'last_gamer_deleted': "✅ Player {username} removed from tracked list.\n\n⚠️ You deleted the last player. Use the /addgamer command to add a new tracked player.", 'delete_failed': "❌ Failed to delete player", # Stats commands 'no_active_gamer': "❌ No active player. Use /getgamers to select.", 'unknown_period': "❌ Unknown period", 'no_data': "📭 No data", 'stats_title': "📊 Statistics {username} • {date_range}\n\n", 'puzzles_section': "🧩 Puzzles: {total} (✅ {solved} - ❌ {unsolved})\n\n", 'games_section': "{emoji} {game_type} — {games_count} games • {rating_change}\nRating: {rating}\n✅ Wins: {wins}\n❌ Losses: {losses}\n🤝 Draws: {draws}\n\n", # Set period 'select_gamer_for_period': "⏱️ Select player to set notification period:\n\n", 'select_period': "⏱️ Select period for player {username}:\n📱 Notifications will be sent to personal messages", 'notifications_disabled': "✅ Notifications disabled for {username}", 'period_set': "✅ Period {period} minutes set for {username}\n📱 Notifications will be sent to personal messages", 'disable_notifications': "❌ Disable notifications", 'period_minutes': "⏰ {period} minutes", # Period notification 'period_1_minute': "for 1 minute", 'period_2_3_4_minutes': "for {period} minutes", 'period_minutes_text': "for {period} minutes", 'period_notification_title': "📊 Statistics {username} • {period_text}\n\n", 'period_puzzles_section': "🧩 Puzzles: {total} (✅ {solved} - ❌ {failed})\n\n", 'period_games_section': "{emoji} {game_type} — {games_count} games • {rating_change}\nRating: {rating}\n✅ Wins: {wins}\n❌ Losses: {losses}\n🤝 Draws: {draws}\n\n", 'no_activity': "📭 No activity for this period", # Last year or 1000 games 'last_year_1000_processing': "⏳ Processing request... This may take a while as requests are very slow.", 'last_year_1000_player_processing': "🔄 Requesting data for player {username}...", # Stats commands (today/yesterday/week) 'stats_processing': "⏳ Processing request...", 'stats_player_processing': "🔄 Requesting data for player {username}...", 'stats_all_done': "✅ That's all", # Support 'support_message': ( "💬 Support & Feedback\n\n" "You can write to the service developer directly and report a problem, suggest new features, or ask a question.\n\n" "I will be happy to review every message and respond to it.\n\n" "The developer accepts messages in English and Russian languages.\n\n" "📧 Contact: @vrubelr\n\n" "📦 Bot version: {version}" ), # Common 'period_minutes_suffix': "m", # Language selection 'select_language': "🌐 Select language / Выберите язык:", 'language_set_en': "✅ Language set to English", 'language_set_ru': "✅ Язык установлен: Русский", # Profile command 'select_player_profile': "👤 Select player:", 'profile_link_sent': "✅ Profile link sent", }, 'ru': { # Start command 'start_message': ( "🎯 Бот отслеживает одного или нескольких игроков на Lichess.\n\n" "📈 Показывает рейтинги, активность за сегодня, вчера и за неделю.\n\n" "🧩 При указании user_token (с разрешением puzzle-read) можно также получать данные по пазлам.\n\n" "⏱️ Бот поддерживает автоматические проверки с заданными интервалами\n" "📨 …и отправляет отчет, если была активность за это время.\n\n" "Пример за неделю:\n" "🧩 Пазлы: 114 (✅ 81 - ❌ 33)\n\n" "🔥 Блиц — 5 игр • 🔴 -10\n" "Рейтинг: 2245\n" "✅ Побед: 1\n" "❌ Поражений: 3\n" "🤝 Ничьих: 1\n\n" "🐇 Рапид — 19 игр • 🟢 +20\n" "Рейтинг: 2248\n" "✅ Побед: 8\n" "❌ Поражений: 4\n" "🤝 Ничьих: 7\n\n" "📋 Доступные команды:\n\n" "➕ /addgamer — Добавить игрока Lichess для отслеживания (только username)\n" "🔑 /addtoken — Добавить игрока с токеном для получения данных по пазлам\n" "👥 /getgamers — Посмотрите статистику своих игроков\n" "🚫 /delgamer — Удалить игрока из списка отслеживаемых\n\n" "📅 /today — Статистика за сегодня\n" "📆 /yesterday — Статистика за вчера\n" "📆 /week — Статистика за неделю\n" "📈 /lastYear_or_1000games — Статистика за последний год или последние 1000 рейтинговых игр\n\n" "⏱️ /setperiod — Настроить периодические уведомления для активного игрока\n" " ↳ (активный игрок меняется в меню /getgamers)\n\n" "👤 /profile — Просмотр ссылок на профили Lichess отслеживаемых игроков\n" "🌍 /set_lang — Выбрать язык бота\n" "💬 /support — Связаться с разработчиком для поддержки и обратной связи" ), # Add gamer commands 'addgamer_prompt': "👤 Введите username игрока Lichess для отслеживания:", 'addtoken_prompt': ( "🔑 Введите токен API Lichess для получения данных по пазлам.\n" "Токен создается в настройках профиля — дайте ему только разрешение puzzle:read.\n" "После этого будет добавлен игрок, соответствующий этому токену." ), 'token_added': "✅ Токен добавлен для игрока {username}!", 'gamer_added_with_token': "✅ Игрок {username} добавлен с токеном!", 'gamer_added': "✅ Игрок {username} успешно добавлен!\n\nДля добавления следующего игрока воспользуйтесь /addgamer", 'invalid_token': "❌ Неверный токен. Попробуйте еще раз.", 'token_username_error': "❌ Не удалось получить username из токена. Попробуйте еще раз.", 'empty_username': "❌ Username не может быть пустым. Попробуйте еще раз.", 'user_not_found': "❌ Игрок {username} не найден на Lichess. Проверьте правильность написания имени.", # Get gamers 'no_gamers': "📭 Нет игроков в базе данных. Используйте /addgamer для добавления.", 'loading_ratings': "🔄 Загрузка рейтингов игроков...", 'select_active_gamer': "👥 Выберите активного игрока:\n\n", 'active_gamer_set': "✅ Активный игрок: {username}", 'gamer_not_found': "❌ Игрок не найден", # Delete gamer 'no_gamers_to_delete': "📭 У вас нет отслеживаемых игроков.", 'loading_gamers': "🔄 Загрузка списка игроков...", 'select_gamer_to_delete': "🗑️ Выберите игрока для удаления:\n\n", 'gamer_deleted': "✅ Игрок {username} удален из списка отслеживаемых.", 'active_gamer_deleted': "✅ Игрок {username} удален из списка отслеживаемых.\n\n⚠️ Вы удалили активного игрока. Используйте команду /getgamers для выбора игрока, для которого будут работать команды /today, /yesterday, /week.", 'last_gamer_deleted': "✅ Игрок {username} удален из списка отслеживаемых.\n\n⚠️ Вы удалили последнего игрока. Используйте команду /addgamer для добавления нового отслеживаемого игрока.", 'delete_failed': "❌ Не удалось удалить игрока", # Stats commands 'no_active_gamer': "❌ Нет активного игрока. Используйте /getgamers для выбора.", 'unknown_period': "❌ Неизвестный период", 'no_data': "📭 Нет данных", 'stats_title': "📊 Статистика {username} • {date_range}\n\n", 'puzzles_section': "🧩 Пазлы: {total} (✅ {solved} - ❌ {unsolved})\n\n", 'games_section': "{emoji} {game_type} — {games_count} игр • {rating_change}\nРейтинг: {rating}\n✅ Побед: {wins}\n❌ Поражений: {losses}\n🤝 Ничьих: {draws}\n\n", # Set period 'select_gamer_for_period': "⏱️ Выберите игрока для установки периода уведомлений:\n\n", 'select_period': "⏱️ Выберите период для игрока {username}:\n📱 Уведомления будут отправляться в личные сообщения", 'notifications_disabled': "✅ Уведомления отключены для {username}", 'period_set': "✅ Период {period} минут установлен для {username}\n📱 Уведомления будут отправляться в личные сообщения", 'disable_notifications': "❌ Отключить уведомления", 'period_minutes': "⏰ {period} минут", # Period notification 'period_1_minute': "за 1 минуту", 'period_2_3_4_minutes': "за {period} минуты", 'period_minutes_text': "за {period} минут", 'period_notification_title': "📊 Статистика {username} • {period_text}\n\n", 'period_puzzles_section': "🧩 Пазлы: {total} (✅ {solved} - ❌ {failed})\n\n", 'period_games_section': "{emoji} {game_type} — {games_count} игр • {rating_change}\nРейтинг: {rating}\n✅ Побед: {wins}\n❌ Поражений: {losses}\n🤝 Ничьих: {draws}\n\n", 'no_activity': "📭 Нет активности за этот период", # Last year or 1000 games 'last_year_1000_processing': "⏳ Обработка запроса... Это может занять некоторое время, так как запросы очень медленные.", 'last_year_1000_player_processing': "🔄 Запрос данных для игрока {username}...", # Stats commands (today/yesterday/week) 'stats_processing': "⏳ Обработка запроса...", 'stats_player_processing': "🔄 Запрос данных для игрока {username}...", 'stats_all_done': "✅ Это всё", # Support 'support_message': ( "💬 Поддержка и обратная связь\n\n" "Вы можете написать разработчику сервиса напрямую и сообщить о проблеме, предложить новые функции или задать вопрос.\n\n" "Я буду рад рассмотреть каждое сообщение и ответить на него.\n\n" "Разработчик принимает сообщения на английском и русском языках.\n\n" "📧 Контакт: @vrubelr\n\n" "📦 Версия бота: {version}" ), # Common 'period_minutes_suffix': "м", # Language selection 'select_language': "🌐 Выберите язык / Select language:", 'language_set_en': "✅ Language set to English", 'language_set_ru': "✅ Язык установлен: Русский", # Profile command 'select_player_profile': "👤 Выберите игрока:", 'profile_link_sent': "✅ Ссылка на профиль отправлена", } } def t(key: str, lang: str = 'en', **kwargs) -> str: """ Translate a key to the specified language. Args: key: Translation key lang: Language code ('en' or 'ru') **kwargs: Format arguments for the translation string Returns: Translated string with formatted arguments """ # Default to English if language not supported if lang not in TRANSLATIONS: lang = 'en' translation = TRANSLATIONS[lang].get(key) # Fallback to English if translation not found if translation is None: translation = TRANSLATIONS['en'].get(key, key) # Format the string if kwargs provided if kwargs: try: return translation.format(**kwargs) except KeyError: # If formatting fails, return the translation as-is return translation return translation