v2.4.0 — internationalization (EN/RU) + custom git templates

- i18n engine (lib/i18n.sh, lib/lang/en.sh, lib/lang/ru.sh)
- first-run language picker, persisted to .language + config.json
- install.sh, common.sh, backup.sh, templates_catalog.sh wired through t()/tf()
- backup.sh preserves .language marker and records language in metadata.json
- custom git template feature (first item in pro template picker)
  * validates HTTPS URLs, rejects shell metachars
  * 100MB size guard, 90s clone timeout
  * auto-detects index.html in dist/public/build/_site/site/docs/out/www
- bot v2.4.0: i18n.py + lang/{en,ru}.json, /lang command, language toggle button
- bot: custom git template via text input with waiter gating
This commit is contained in:
anten-ka
2026-04-10 11:26:02 +03:00
parent 9c084f37ec
commit 0d087831d8
13 changed files with 2489 additions and 1002 deletions

375
lib/lang/ru.sh Executable file
View File

@@ -0,0 +1,375 @@
#!/bin/bash
# GoTelegram v2.4 — Russian translations
# shellcheck disable=SC2034,SC2148
# ── Common words ────────────────────────────────────────────────────────
I18N[yes]="Да"
I18N[no]="Нет"
I18N[ok]="OK"
I18N[cancel]="Отмена"
I18N[back]="« Назад"
I18N[exit]="Выход"
I18N[skip]="Пропустить"
I18N[choose]="Выбор"
I18N[press_enter]="Нажмите Enter..."
I18N[press_enter_to_return]="Нажмите Enter для возврата в меню..."
I18N[invalid_choice]="Неверный выбор"
I18N[running]="работает"
I18N[stopped]="остановлен"
I18N[not_installed]="не установлен"
I18N[unknown]="неизвестно"
I18N[error]="Ошибка"
I18N[warning]="Внимание"
I18N[info]="Инфо"
I18N[success]="Готово"
I18N[wait]="Подождите..."
# ── Banner ──────────────────────────────────────────────────────────────
I18N[banner_title]="GoTelegram v%s"
I18N[banner_subtitle]="MTProxy на ядре telemt (Rust + Tokio)"
I18N[banner_features]="Anti-DPI • Fake TLS • TCP Splice • JA3/JA4"
I18N[credits_title]="Благодарности / Credits"
# ── Main menu (dashboard) ───────────────────────────────────────────────
I18N[dashboard_title]="Панель управления"
I18N[svc_proxy]="Прокси"
I18N[svc_nginx]="nginx"
I18N[svc_site]="Сайт"
I18N[svc_ssl]="SSL"
I18N[svc_bot]="Бот"
I18N[ssl_until]="до %s"
I18N[net_ip]="IP:"
I18N[net_port]="Порт:"
I18N[net_mode]="Режим:"
I18N[net_domain]="Домен:"
I18N[connection_link]="Ссылка для Telegram:"
I18N[proxy_not_configured]="Прокси не настроен. Выберите пункт 1."
I18N[menu_proxy]="Прокси ▸"
I18N[menu_stats]="Статистика ▸"
I18N[menu_manage]="Управление ▸"
I18N[menu_telegram_bot]="Telegram-бот ▸"
I18N[menu_about]="О программе ▸"
I18N[auto_refresh_30s]="Обновление через 30 сек"
# ── Submenu: Proxy ──────────────────────────────────────────────────────
I18N[submenu_proxy_title]="🚀 ПРОКСИ"
I18N[proxy_install_update]="Установить / Обновить"
I18N[proxy_status_detail]="Статус подробно"
I18N[proxy_copy_link]="Скопировать ссылку"
I18N[proxy_share]="Поделиться ключом"
I18N[proxy_restart]="Перезапуск"
I18N[proxy_logs]="Логи"
I18N[proxy_change_mode]="Сменить режим / шаблон"
# ── Submenu: Manage ─────────────────────────────────────────────────────
I18N[submenu_manage_title]="⚙️ УПРАВЛЕНИЕ"
I18N[manage_backup]="Бекап"
I18N[manage_restore]="Восстановить"
I18N[manage_update_telemt]="Обновить telemt"
I18N[manage_site_ssl]="Сайт / SSL"
I18N[manage_remove]="Удалить"
I18N[manage_language]="Язык / Language"
# ── Submenu: About ──────────────────────────────────────────────────────
I18N[submenu_about_title]=" О ПРОГРАММЕ"
I18N[about_version_info]="Информация о версии"
I18N[about_promo]="Промо / Донат"
I18N[version_title]="🔍 Информация"
I18N[version_label]="GoTelegram:"
I18N[version_engine]="Ядро:"
I18N[version_tech]="Технология:"
I18N[version_license]="Лицензия:"
# ── Install flow ────────────────────────────────────────────────────────
I18N[install_select_mode]="🎭 Выберите режим маскировки:"
I18N[install_lite_title]="⚡ Lite — маскировка под популярный сайт"
I18N[install_lite_desc1]="Быстро, без домена. telemt маскирует трафик"
I18N[install_lite_desc2]="под выбранный сайт (google.com и т.д.)"
I18N[install_pro_title]="🛡 Pro — свой сайт + полная маскировка"
I18N[install_pro_desc1]="nginx + SSL + HTML-шаблон + telemt."
I18N[install_pro_desc2]="DPI видит реальный сайт с реальным сертификатом."
I18N[install_pro_desc3]="Требует: домен, направленный на этот сервер."
I18N[install_mode_choice]="Выбор (1/2):"
I18N[install_bad_choice]="Неверный выбор: %s"
I18N[install_lite_step]="Установка Lite-режима"
I18N[install_pro_step]="Установка Pro-режима"
I18N[install_enter_domain]="Введите ваш домен (например, example.com):"
I18N[install_bad_domain]="Некорректный домен: %s"
I18N[install_dns_mismatch]="Домен %s указывает на %s, а не на %s"
I18N[install_continue_anyway]="Продолжить всё равно?"
I18N[install_enter_email]="Email для SSL (Enter = без email):"
I18N[install_config_title]="📋 Конфигурация:"
I18N[install_cfg_ip]="IP:"
I18N[install_cfg_port]="Порт:"
I18N[install_cfg_mask]="Маскировка:"
I18N[install_cfg_mode]="Режим:"
I18N[install_cfg_domain]="Домен:"
I18N[install_confirm_proxy]="Установить прокси?"
I18N[install_confirm_proxy_site]="Установить прокси + сайт?"
I18N[install_done]="GoTelegram v%s установлен! (%s-режим)"
I18N[install_arch_desc1]="telemt принимает весь трафик на 443 (маскировка под HTTPS)"
I18N[install_arch_desc2]="nginx обслуживает сайт на внутреннем порту %s"
I18N[install_arch_desc3]="Провайдер видит только HTTPS-трафик к %s:443"
# ── Change mode/template ────────────────────────────────────────────────
I18N[change_current_mode]="Текущий режим:"
I18N[change_template]="Сменить шаблон сайта (только pro)"
I18N[change_mode_switch]="Переключить режим (lite ↔ pro)"
I18N[change_only_pro]="Смена шаблона доступна только в pro-режиме"
I18N[change_requires_reinstall]="Переключение режима требует переустановки."
I18N[change_reinstall_confirm]="Переустановить прокси?"
# ── Logs ────────────────────────────────────────────────────────────────
I18N[logs_telemt_title]="📋 Логи telemt (последние %s строк):"
# ── Link / Share ────────────────────────────────────────────────────────
I18N[link_title]="🔗 Ссылка для подключения:"
I18N[share_title]="📤 Перешлите это сообщение:"
I18N[share_line1]="🔐 MTProxy для Telegram (GoTelegram v%s)"
I18N[share_server]="🌍 Сервер: %s"
I18N[share_port]="🔌 Порт: %s"
I18N[share_connect_cta]="👉 Подключиться одним нажатием:"
I18N[share_footer]="Просто нажмите на ссылку или настройте вручную."
# ── Website ─────────────────────────────────────────────────────────────
I18N[website_title]="🌐 Управление сайтом"
I18N[website_domain]="Домен:"
I18N[website_ssl_until]="SSL до:"
I18N[website_only_pro]="Управление сайтом доступно только в pro-режиме"
I18N[website_renew_ssl]="Обновить SSL сертификат"
I18N[website_restart_nginx]="Перезапустить nginx"
I18N[website_change_template]="Сменить шаблон"
# ── Remove ──────────────────────────────────────────────────────────────
I18N[remove_title]="🗑 Удаление GoTelegram"
I18N[remove_proxy_only]="Удалить только прокси (telemt)"
I18N[remove_bot_only]="Удалить только Telegram-бота"
I18N[remove_all]="Удалить всё (прокси + бот + настройки)"
I18N[remove_warn_proxy]="Это удалит прокси и все его настройки."
I18N[remove_confirm_proxy]="Удалить прокси?"
I18N[remove_backup_before]="Сделать бекап перед удалением?"
I18N[remove_warn_all]="Это удалит ВСЁ: прокси, бот, сайт, настройки."
I18N[remove_confirm_all]="Вы точно уверены?"
I18N[remove_proxy_done]="Прокси удалён"
I18N[remove_all_done]="GoTelegram полностью удалён (прокси + бот)"
# ── Telegram bot submenu ────────────────────────────────────────────────
I18N[bot_title]="🤖 Telegram-бот"
I18N[bot_status_running]="● Работает"
I18N[bot_status_stopped]="○ Остановлен"
I18N[bot_status_not_installed]="✗ Не установлен"
I18N[bot_menu_status]="📊 Статус бота"
I18N[bot_menu_logs]="📋 Логи бота"
I18N[bot_menu_restart]="🔄 Перезапустить бота"
I18N[bot_menu_stop]="⏹ Остановить бота"
I18N[bot_menu_start]="▶️ Запустить бота"
I18N[bot_menu_settings]="⚙️ Настройки (.env)"
I18N[bot_menu_remove]="🗑 Удалить бота"
I18N[bot_menu_install]="🔧 Установить бота"
I18N[bot_intro1]="Бот позволяет управлять прокси прямо из Telegram:"
I18N[bot_intro2]="статус, перезапуск, смена режима, бекап, QR-код."
I18N[bot_install_step]="Установка Telegram-бота"
I18N[bot_install_python]="Установка Python3..."
I18N[bot_files_not_found]="Файлы бота не найдены в %s"
I18N[bot_create_venv]="Создание виртуального окружения..."
I18N[bot_install_deps]="Установка зависимостей..."
I18N[bot_enter_token]="Введите BOT_TOKEN от @BotFather:"
I18N[bot_token_empty]="Токен не может быть пустым"
I18N[bot_token]="Token:"
I18N[bot_add_admin_how]="Как добавить администратора?"
I18N[bot_admin_auto]="Автоматически — бот определит ID при первом /start"
I18N[bot_admin_manual]="Вручную — ввести ID сейчас"
I18N[bot_admin_ids_prompt]="ID администраторов (через пробел/запятую):"
I18N[bot_env_created]=".env создан"
I18N[bot_env_exists]=".env уже существует, настройки сохранены"
I18N[bot_wait_admin_title]="Ожидание администратора"
I18N[bot_wait_admin_msg1]="Откройте бота в Telegram и отправьте"
I18N[bot_wait_admin_msg2]="Бот автоматически назначит вас администратором"
I18N[bot_wait_admin_skip]="Нажмите Ctrl+C чтобы пропустить"
I18N[bot_wait_spinner]="Ожидание... напишите /start боту (%d сек)"
I18N[bot_admin_assigned]="Администратор назначен!"
I18N[bot_wait_skipped]="Пропущено. Добавить админа позже: меню → Telegram-бот → Настройки"
I18N[bot_wait_timeout]="Таймаут (5 мин). Добавить админа: меню → Telegram-бот → Настройки"
I18N[bot_installed]="Бот установлен и запущен!"
I18N[bot_status_title]="📊 Статус Telegram-бота"
I18N[bot_token_configured]="настроен"
I18N[bot_access_open]="все пользователи"
I18N[bot_logs_title]="📋 Логи бота (последние 30 строк):"
I18N[bot_settings_title]="⚙️ Настройки бота"
I18N[bot_current_env]="Текущий .env:"
I18N[bot_change_token]="Сменить BOT_TOKEN"
I18N[bot_change_allowed]="Изменить ALLOWED_IDS"
I18N[bot_new_token]="Новый BOT_TOKEN:"
I18N[bot_token_empty_err]="Пустой токен"
I18N[bot_token_updated]="Токен обновлён, бот перезапущен"
I18N[bot_allowed_prompt]="ALLOWED_IDS (через пробел/запятую, пусто = авто):"
I18N[bot_access_updated]="Доступ обновлён, бот перезапущен"
I18N[bot_remove_warn]="Это удалит Telegram-бота и все его настройки."
I18N[bot_remove_confirm]="Удалить бота?"
I18N[bot_removed]="Бот полностью удалён"
I18N[bot_restarted]="Бот перезапущен"
I18N[bot_stopped]="Бот остановлен"
I18N[bot_started]="Бот запущен"
I18N[bot_status_colon]="Статус:"
I18N[bot_access_colon]="Доступ:"
I18N[bot_access_ids_fmt]="ID: %s"
# ── Promo / Donate ──────────────────────────────────────────────────────
I18N[promo_host1_title]="💰 ХОСТИНГ #1 — СКИДКА ДО 60%"
I18N[promo_host2_title]="💰 ХОСТИНГ #2 — СКИДКА ДО 60%"
I18N[promo_tips_title]="☕ Донат / Чаевые"
I18N[promo_link_label]="Ссылка:"
I18N[promo_off60]="60%% скидки на первый месяц"
I18N[promo_ant20]="20%% + 3%% при оплате за 3 месяца"
I18N[promo_ant6]="15%% + 5%% при оплате за 6 месяцев"
I18N[promo_qr_host1]="── QR: Хостинг #1 ──"
I18N[promo_qr_host2]="── QR: Хостинг #2 ──"
I18N[promo_qr_tips]="── QR: Чаевые / Донат ──"
I18N[promo_menu_in]="Меню через %d сек..."
# ── Stats ───────────────────────────────────────────────────────────────
I18N[stats_title]="📊 Статистика трафика"
I18N[stats_module_missing]="Модуль статистики не загружен."
I18N[stats_file_missing]="Файл lib/stats.sh не найден."
I18N[stats_toggle]="Вкл/Выкл подсчёт (сейчас: %s)"
I18N[stats_install_collector]="Установить/обновить сборщик статистики"
I18N[stats_auto_refresh]="Обновление каждые 3 сек"
I18N[stats_on]="вкл"
I18N[stats_off]="выкл"
# ── Templates catalog ───────────────────────────────────────────────────
I18N[templates_categories]="📂 Категории шаблонов сайтов:"
I18N[templates_custom_git]="📎 Свой шаблон по git URL"
I18N[templates_random]="🎲 Случайный шаблон"
I18N[templates_count_fmt]="(%d шаблонов)"
I18N[templates_list]="📋 %s — доступные шаблоны:"
I18N[templates_preview_title]="🔍 Превью шаблона:"
I18N[templates_name]="Название:"
I18N[templates_source]="Источник:"
I18N[templates_description]="Описание:"
I18N[templates_preview]="👁 Превью:"
I18N[templates_preview_hint]="Откройте ссылку в браузере для просмотра шаблона"
I18N[templates_repo]="📦 Репо:"
I18N[templates_thanks]="💜 Спасибо авторам %s за открытый код!"
I18N[templates_install_this]="Установить этот шаблон?"
I18N[templates_cat_empty]="В этой категории нет шаблонов"
I18N[templates_downloading]="Скачивание шаблона \"%s\"..."
I18N[templates_downloaded]="Шаблон \"%s\" скачан"
I18N[templates_downloaded_subfolder]="Шаблон \"%s\" скачан (из подпапки)"
I18N[templates_no_index]="Шаблон не содержит index.html"
I18N[templates_path]="Путь: %s"
I18N[templates_catalog_not_found]="Каталог шаблонов не найден: %s"
# ── Custom git template ─────────────────────────────────────────────────
I18N[custom_git_title]="📎 СВОЙ ШАБЛОН ПО GIT URL"
I18N[custom_git_help_1]="Вы можете использовать ЛЮБОЙ репозиторий со статическим HTML-сайтом"
I18N[custom_git_help_2]="в качестве шаблона. Репозиторий должен быть публичным и содержать"
I18N[custom_git_help_3]="готовый index.html (сборка через npm НЕ выполняется)."
I18N[custom_git_formats]="Поддерживаемые форматы URL:"
I18N[custom_git_fmt_github]=" • https://github.com/user/repo"
I18N[custom_git_fmt_gitlab]=" • https://gitlab.com/user/repo"
I18N[custom_git_fmt_gitext]=" • https://example.com/user/repo.git"
I18N[custom_git_fmt_branch]=" • https://github.com/user/repo@branch (ветка после @)"
I18N[custom_git_auto_detect]="Структура репозитория (авто-определение):"
I18N[custom_git_auto_1]=" 1. index.html в корне репозитория"
I18N[custom_git_auto_2]=" 2. dist/index.html (StartBootstrap, Vite, webpack)"
I18N[custom_git_auto_3]=" 3. public/ или build/ или _site/ или site/ или docs/"
I18N[custom_git_auto_4]=" 4. Fallback: поиск index.html по всему репозиторию"
I18N[custom_git_requirements]="Требования:"
I18N[custom_git_req_1]=" • Только HTTPS (ssh:// и git:// блокируются)"
I18N[custom_git_req_2]=" • Только публичные репозитории"
I18N[custom_git_req_3]=" • Размер репо не более 100 МБ"
I18N[custom_git_req_4]=" • Статический HTML (без серверного кода PHP/Python/Node)"
I18N[custom_git_examples]="Примеры проверенных репо:"
I18N[custom_git_ex_1]=" • https://github.com/html5up-collective/strata"
I18N[custom_git_ex_2]=" • https://github.com/StartBootstrap/startbootstrap-landing-page"
I18N[custom_git_enter_url]="Вставьте git URL (или Enter для отмены):"
I18N[custom_git_empty]="URL не указан, отмена"
I18N[custom_git_bad_url]="Недопустимый URL. Принимаются только https:// адреса"
I18N[custom_git_cloning]="Клонирование репозитория..."
I18N[custom_git_clone_failed]="Не удалось клонировать репозиторий: %s"
I18N[custom_git_too_big]="Репозиторий слишком большой: %s (лимит 100MB)"
I18N[custom_git_scanning]="Поиск index.html в структуре..."
I18N[custom_git_found_at]="✓ Найден index.html в: %s"
I18N[custom_git_no_index]="index.html не найден в репозитории"
I18N[custom_git_installed]="Свой шаблон установлен из %s"
I18N[custom_git_saved]="URL шаблона сохранён в конфиге (меню → Сайт → Обновить из git)"
# ── First-run language picker ───────────────────────────────────────────
I18N[lang_picker_title]="Выберите язык / Select language"
I18N[lang_english]="English"
I18N[lang_russian]="Русский"
I18N[lang_saved]="Язык сохранён: %s"
I18N[lang_change_prompt]="Выберите новый язык:"
# ── Backup ──────────────────────────────────────────────────────────────
I18N[backup_title]="💾 Бекап"
I18N[backup_creating]="Создание бекапа..."
I18N[backup_created]="Бекап создан: %s"
I18N[backup_failed]="Ошибка создания бекапа"
I18N[backup_restore_title]="↩️ Восстановление из бекапа"
I18N[backup_no_files]="Нет файлов бекапа"
I18N[backup_select]="Выберите бекап для восстановления:"
I18N[backup_restoring]="Восстановление..."
I18N[backup_restored]="Бекап восстановлен"
I18N[backup_collecting]="Собираю конфигурацию..."
I18N[backup_site_included]="Шаблон сайта включён"
I18N[backup_archive_err]="Ошибка создания архива"
I18N[backup_archive_missing]="Архив не создан"
I18N[backup_encrypt_err]="Ошибка шифрования"
I18N[backup_encrypted]="Бекап зашифрован (AES-256-CBC)"
I18N[backup_created_fmt]="Бекап создан: %s (%s)"
I18N[backup_file_not_found_fmt]="Файл не найден: %s"
I18N[backup_enter_pass]="Введите пароль от бекапа"
I18N[backup_bad_pass]="Неверный пароль или повреждённый файл"
I18N[backup_extract_err]="Ошибка распаковки архива"
I18N[backup_label]="Бекап"
I18N[backup_version_label]="Версия"
I18N[backup_mode_label]="Режим"
I18N[backup_lang_label]="Язык"
I18N[backup_date_label]="Дата"
I18N[backup_confirm_restore]="Восстановить конфигурацию? Текущие настройки будут перезаписаны."
I18N[backup_restored_telemt]="telemt конфиг восстановлен"
I18N[backup_restored_gotelegram]="GoTelegram конфиг восстановлен"
I18N[backup_restored_lang]="Язык интерфейса восстановлен"
I18N[backup_restored_nginx]="nginx конфиг восстановлен"
I18N[backup_restored_ssl]="SSL сертификаты восстановлены"
I18N[backup_restored_site]="Шаблон сайта восстановлен"
I18N[backup_restore_done]="Восстановление завершено!"
I18N[backup_none]="Бекапов нет"
I18N[backup_list_title]="Доступные бекапы"
I18N[backup_cleanup_fmt]="Удалено %s старых бекапов (оставлено %s)"
I18N[backup_create_title]="Создание бекапа"
I18N[backup_encrypt_prompt]="Зашифровать бекап паролем?"
I18N[backup_repeat_pass]="Повторите пароль"
I18N[backup_pass_mismatch]="Пароли не совпадают"
I18N[backup_pass_short]="Пароль слишком короткий (минимум 6 символов)"
I18N[backup_pick_prompt]="Номер бекапа (или путь к файлу)"
I18N[backup_not_found]="Бекап не найден"
# ── Errors / misc ───────────────────────────────────────────────────────
I18N[err_need_root]="Запустите скрипт с sudo / от root"
I18N[err_os_unknown]="Не удалось определить ОС. Требуется Linux."
I18N[err_low_disk]="Мало места на диске: %sMB (нужно %sMB+)"
I18N[err_bad_pkg_mgr]="Неизвестный пакетный менеджер"
I18N[err_unexpected]="Неожиданная ошибка"
I18N[bye]="До встречи! 👋"
I18N[auto_refresh]="Обновление через 30 сек"
# ── Deps ────────────────────────────────────────────────────────────────
I18N[deps_installing]="Установка зависимостей: %s"
# ── Migration ───────────────────────────────────────────────────────────
I18N[v1_detected]="⚠️ Обнаружена установка GoTelegram v1 (mtg)"
I18N[v1_container]="Контейнер: %s"
I18N[v1_migration_step]="Миграция с v1 (mtg) на v2 (telemt)"
I18N[v1_found_title]="Найдена установка v1 (mtg):"
I18N[v1_port]="Порт: %s"
I18N[v1_secret]="Secret: %s..."
I18N[v1_incompatible]="секрет mtg НЕ совместим с telemt напрямую."
I18N[v1_new_link]="Клиентам потребуется новая ссылка."
I18N[v1_stop_migrate]="Остановить v1 контейнер и перейти на v2? [Y/n]:"
I18N[v1_migration_cancelled]="Миграция отменена. v1 оставлен без изменений."
I18N[v1_stopping]="Остановка v1 контейнера..."
I18N[v1_config_saved]="Конфиг v1 сохранён в %s"
I18N[v1_port_freed]="v1 остановлен. Порт %s освобождён."