428th-exchange-bot/bot/i18n.py
Artemii Peretiachenko 7588d74ceb Show the wait-ack only on a client's first relayed message.
Stops repeating the ack on every client message so the private chat is not cluttered after the first contact.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-29 19:00:21 +02:00

176 lines
7.9 KiB
Python
Raw 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.

from __future__ import annotations
from html import escape
from typing import Dict, Optional
from aiogram.types import InlineKeyboardButton, InlineKeyboardMarkup
DEFAULT_LANGUAGE = "ru"
SUPPORTED_LANGUAGES = ("ru", "uk")
Language = str
SERVICES_RU = (
"<b>🌐 1. Покупка/продажа криптовалюты за наличные</b> — лучшие условия "
"во всех странах и крупных городах.\n\n"
"<b>💸 2. Перестановка наличных</b> — выдача день в день.\n\n"
"<b>💳 3. Оплата на карты</b>\n\n"
"• Покупка/продажа криптовалюты.\n\n"
"• Оплата на карты EUR, TRY, KZT, PLN, THB.\n\n"
"• Оплата физ.лиц (со счетов в ЕС): USD, EUR, GBP через Wise, Paysera, Revolut, ZEN.\n\n"
"• Прием/оплата UAH: ТОВ, ФОП, физлица.\n\n"
"• Оплата по ссылкам: Visa, Mastercard, American Express.\n\n"
"• Оплата Инвойсов (USD, EUR): товар, логистика, маркетинг, IT, Консалтинг, "
"тур. услуги, авто (Copart, IAAI), оплата авто в ЕС.\n\n"
"<b>🔒 4. Электронные деньги и платежные системы</b>\n\n"
"• Payeer, Capitalist, Perfect Money, Skrill, AdvCash, Payoneer.\n\n"
"• Оплата Юань на карты: AliPay, WeChat Pay."
)
SERVICES_UK = (
"<b>🌐 1. Купівля/продаж криптовалюти за готівку</b> — найкращі умови "
"в усіх країнах і великих містах.\n\n"
"<b>💸 2. Перестановка готівки</b> — видача в той же день.\n\n"
"<b>💳 3. Оплата на картки</b>\n\n"
"• Купівля/продаж криптовалюти.\n\n"
"• Оплата на картки EUR, TRY, KZT, PLN, THB.\n\n"
"• Оплата фіз.осіб (з рахунків в ЄС): USD, EUR, GBP через Wise, Paysera, Revolut, ZEN.\n\n"
"• Прийом/оплата UAH: ТОВ, ФОП, фізособи.\n\n"
"• Оплата за посиланнями: Visa, Mastercard, American Express.\n\n"
"• Оплата інвойсів (USD, EUR): товар, логістика, маркетинг, IT, консалтинг, "
"тур. послуги, авто (Copart, IAAI), оплата авто в ЄС.\n\n"
"<b>🔒 4. Електронні гроші та платіжні системи</b>\n\n"
"• Payeer, Capitalist, Perfect Money, Skrill, AdvCash, Payoneer.\n\n"
"• Оплата юаня на картки: AliPay, WeChat Pay."
)
TEXTS: Dict[str, Dict[str, str]] = {
"ru": {
"welcome": (
"Здравствуйте!\n\n"
"Напишите ваш запрос — менеджер ответит здесь.\n\n"
"Укажите что конкретно вам нужно сделать.\n\n"
"🔶 Все наши услуги посмотрите по кнопке ниже."
),
"ack": "Спасибо, дальше вам будет отвечать менеджер",
"cooldown": "Подождите немного, не спамьте.",
"send_failed": (
"Не удалось отправить сообщение менеджеру. Попробуйте позже."
),
"choose_language": "Выберите язык / Оберіть мову:",
"language_set": "Язык сохранён: русский.",
"prefix_bot": "Бот:",
"prefix_manager": "Менеджер:",
"lang_button": "Ru",
"services_button": "Список услуг",
"services": SERVICES_RU,
"client_blocked": (
"⚠️ Клиент заблокировал бота. Сообщение не доставлено."
),
"deliver_failed": "⚠️ Не удалось доставить сообщение клиенту.",
"edit_failed": "⚠️ Не удалось обновить сообщение у клиента.",
"deleted_notice": "🗑 Сообщение удалено.",
},
"uk": {
"welcome": (
"Вітаємо!\n\n"
"Напишіть ваш запит — менеджер відповість тут.\n\n"
"Вкажіть, що саме вам потрібно зробити.\n\n"
"🔶 Всі наші послуги подивіться по кнопці нижче."
),
"ack": "Дякуємо, далі вам буде відповідати менеджер.",
"cooldown": "Зачекайте трохи, не спамте.",
"send_failed": (
"Не вдалося надіслати повідомлення менеджеру. Спробуйте пізніше."
),
"choose_language": "Оберіть мову / Выберите язык:",
"language_set": "Мову збережено: українська.",
"prefix_bot": "Бот:",
"prefix_manager": "Менеджер:",
"lang_button": "Ukr",
"services_button": "Список послуг",
"services": SERVICES_UK,
"client_blocked": (
"⚠️ Клієнт заблокував бота. Повідомлення не доставлено."
),
"deliver_failed": "⚠️ Не вдалося доставити повідомлення клієнту.",
"edit_failed": "⚠️ Не вдалося оновити повідомлення у клієнта.",
"deleted_notice": "🗑 Повідомлення видалено.",
},
}
def normalize_language(language: Optional[str]) -> Optional[str]:
if language is None:
return None
code = language.strip().lower()
if code in SUPPORTED_LANGUAGES:
return code
return None
def resolve_language(language: Optional[str]) -> str:
return normalize_language(language) or DEFAULT_LANGUAGE
def t(language: Optional[str], key: str) -> str:
lang = resolve_language(language)
return TEXTS[lang][key]
def format_prefix(language: Optional[str], key: str) -> str:
return f"<b>{escape(t(language, key))}</b>"
def format_labeled_message(label: str, text: str) -> str:
"""Label + plain text body (body is escaped)."""
return f"<b>{escape(label)}</b>\n\n{escape(text)}"
def format_labeled_html(label: str, html_body: str) -> str:
"""Label + pre-formatted HTML body (body is not escaped)."""
return f"<b>{escape(label)}</b>\n\n{html_body}"
def format_bot_message(language: Optional[str], text: str) -> str:
return format_labeled_message(t(language, "prefix_bot"), text)
def format_bot_html(language: Optional[str], html_body: str) -> str:
"""Bot prefix + pre-formatted HTML body (not escaped)."""
return f"{format_prefix(language, 'prefix_bot')}\n\n{html_body}"
def format_manager_message(language: Optional[str], text: str) -> str:
return format_labeled_message(t(language, "prefix_manager"), text)
def format_manager_html(language: Optional[str], html_body: str) -> str:
return format_labeled_html(t(language, "prefix_manager"), html_body)
def language_keyboard() -> InlineKeyboardMarkup:
return InlineKeyboardMarkup(
inline_keyboard=[
[
InlineKeyboardButton(
text=TEXTS[code]["lang_button"],
callback_data=f"lang:{code}",
)
]
for code in SUPPORTED_LANGUAGES
]
)
def services_keyboard(language: Optional[str]) -> InlineKeyboardMarkup:
return InlineKeyboardMarkup(
inline_keyboard=[
[
InlineKeyboardButton(
text=t(language, "services_button"),
callback_data="services",
)
]
]
)