Перенести выбор языка в начало общего мастера #8
6 changed files with 231 additions and 73 deletions
3
.github/workflows/bash-syntax.yml
vendored
3
.github/workflows/bash-syntax.yml
vendored
|
|
@ -26,5 +26,8 @@ jobs:
|
||||||
- name: Test step 1 selections
|
- name: Test step 1 selections
|
||||||
run: bash tests/test-step1-selection.sh
|
run: bash tests/test-step1-selection.sh
|
||||||
|
|
||||||
|
- name: Test master language selection
|
||||||
|
run: bash tests/test-master-language.sh
|
||||||
|
|
||||||
- name: Test step 3 SSH configuration parsing
|
- name: Test step 3 SSH configuration parsing
|
||||||
run: bash tests/test-step3-sshd-parsing.sh
|
run: bash tests/test-step3-sshd-parsing.sh
|
||||||
|
|
|
||||||
10
README.md
10
README.md
|
|
@ -28,7 +28,7 @@ chmod 700 ./*.sh
|
||||||
sudo ./ochenstarik-server-install.sh
|
sudo ./ochenstarik-server-install.sh
|
||||||
```
|
```
|
||||||
|
|
||||||
Мастер показывает этапы 1–7 по порядку. На каждом этапе можно выбрать установку, пропуск или завершение. В первом этапе пустой ввод устанавливает все рекомендуемые наборы программ. Во время изменения SSH-порта не закрывайте текущую сессию — сначала проверьте новый вход во втором терминале.
|
Первым запросом мастер предлагает выбрать язык диалога и только затем показывает этапы 1–7 по порядку. На каждом этапе можно выбрать установку, пропуск или завершение. В первом этапе пустой ввод устанавливает все рекомендуемые наборы программ. Во время изменения SSH-порта не закрывайте текущую сессию — сначала проверьте новый вход во втором терминале.
|
||||||
|
|
||||||
Если нужен только мастер без скачивания полного архива:
|
Если нужен только мастер без скачивания полного архива:
|
||||||
|
|
||||||
|
|
@ -50,8 +50,8 @@ sudo ./ochenstarik-server-install.sh
|
||||||
|
|
||||||
| Файл | Назначение | Можно запускать отдельно |
|
| Файл | Назначение | Можно запускать отдельно |
|
||||||
| --- | --- | --- |
|
| --- | --- | --- |
|
||||||
| `ochenstarik-server-install.sh` | Единый пошаговый мастер: установить, пропустить или завершить на каждом этапе | Да; рекомендуемый способ полной настройки |
|
| `ochenstarik-server-install.sh` | Сначала выбирает язык диалога, затем последовательно предлагает установить, пропустить или завершить каждый этап | Да; рекомендуемый способ полной настройки |
|
||||||
| `ochenstarik-server-1.sh` | Предлагает выбрать язык диалога, часовой пояс, язык терминала и наборы программ, создаёт swap-файл 2 ГБ | Да |
|
| `ochenstarik-server-1.sh` | Предлагает выбрать часовой пояс, язык терминала и наборы программ, создаёт swap-файл 2 ГБ | Да |
|
||||||
| `ochenstarik-server-2.sh` | Предлагает будущий SSH-порт и IPv4/IPv6, обновляет систему, ставит обязательные пакеты и настраивает UFW | Да |
|
| `ochenstarik-server-2.sh` | Предлагает будущий SSH-порт и IPv4/IPv6, обновляет систему, ставит обязательные пакеты и настраивает UFW | Да |
|
||||||
| `ochenstarik-server-user-3.sh` | Создаёт администратора, переносит SSH на порт из этапа 2, проверяет права и включает fail2ban | После установки необходимых пакетов; проще всего сначала запустить скрипт 2 |
|
| `ochenstarik-server-user-3.sh` | Создаёт администратора, переносит SSH на порт из этапа 2, проверяет права и включает fail2ban | После установки необходимых пакетов; проще всего сначала запустить скрипт 2 |
|
||||||
| `ochenstarik-server-tg-4.sh` | Отправляет уведомления в Telegram при успешном входе по SSH | После установки OpenSSH и `curl`; обычно после скрипта 2 или 3 |
|
| `ochenstarik-server-tg-4.sh` | Отправляет уведомления в Telegram при успешном входе по SSH | После установки OpenSSH и `curl`; обычно после скрипта 2 или 3 |
|
||||||
|
|
@ -115,9 +115,9 @@ bash -n ./ИМЯ-СКРИПТА.sh
|
||||||
|
|
||||||
Файл: `ochenstarik-server-1.sh`.
|
Файл: `ochenstarik-server-1.sh`.
|
||||||
|
|
||||||
Самый первый запрос выбирает язык диалога установщика: English, Русский, Español, Deutsch, Français, Português, 中文, 日本語, العربية или हिन्दी. Начальное меню выводится на английском, а пустой ввод оставляет English. Этот выбор меняет вопросы и сообщения скрипта, но не системную локаль сервера.
|
При запуске единого мастера самый первый запрос, ещё до выбора этапа 1, задаёт язык диалога: English, Русский, Español, Deutsch, Français, Português, 中文, 日本語, العربية или हिन्दी. Начальное меню выводится на английском, а пустой ввод оставляет English. Выбор передаётся первому этапу автоматически и не меняет системную локаль сервера.
|
||||||
|
|
||||||
Затем показывается нумерованное меню популярных часовых поясов, включая `Asia/Novosibirsk`, `Europe/Moscow` и `UTC`. Нужную зону достаточно выбрать по номеру. Для остальных зон предусмотрен полный список с последовательным выбором региона и часового пояса — вводить имя вручную не требуется.
|
Первый этап начинается с нумерованного меню популярных часовых поясов, включая `Asia/Novosibirsk`, `Europe/Moscow` и `UTC`. Нужную зону достаточно выбрать по номеру. Для остальных зон предусмотрен полный список с последовательным выбором региона и часового пояса — вводить имя вручную не требуется.
|
||||||
|
|
||||||
После выбора времени скрипт показывает меню языков терминала: оставить текущий, русский, английский, немецкий, французский, испанский, итальянский, португальский, польский, украинский, турецкий, китайский, японский, корейский либо выбрать другую локаль из полного системного списка. Выбранный язык применяется к новым терминальным сессиям. Исходный `/etc/default/locale` сохраняется для последующего восстановления.
|
После выбора времени скрипт показывает меню языков терминала: оставить текущий, русский, английский, немецкий, французский, испанский, итальянский, португальский, польский, украинский, турецкий, китайский, японский, корейский либо выбрать другую локаль из полного системного списка. Выбранный язык применяется к новым терминальным сессиям. Исходный `/etc/default/locale` сохраняется для последующего восстановления.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -51,7 +51,11 @@ readonly -a PROGRAM_GROUP_PACKAGES=(
|
||||||
)
|
)
|
||||||
|
|
||||||
APT_UPDATED=no
|
APT_UPDATED=no
|
||||||
UI_LANG=en
|
UI_LANG="${OCHENSTARIK_UI_LANG:-en}"
|
||||||
|
case "$UI_LANG" in
|
||||||
|
en|ru|es|de|fr|pt|zh|ja|ar|hi) ;;
|
||||||
|
*) UI_LANG=en ;;
|
||||||
|
esac
|
||||||
|
|
||||||
declare -A UI_TEXT=()
|
declare -A UI_TEXT=()
|
||||||
|
|
||||||
|
|
@ -335,31 +339,10 @@ localize_program_catalog() {
|
||||||
esac
|
esac
|
||||||
}
|
}
|
||||||
|
|
||||||
choose_ui_language() {
|
# The unified installer passes the selected dialog language through the
|
||||||
local answer
|
# environment. A directly launched step uses English by default.
|
||||||
printf '\nSelect the installer language / Выберите язык установщика:\n'
|
|
||||||
printf '%s\n' \
|
|
||||||
' 1) English' ' 2) Русский' ' 3) Español' ' 4) Deutsch' \
|
|
||||||
' 5) Français' ' 6) Português' ' 7) 中文' ' 8) 日本語' \
|
|
||||||
' 9) العربية' ' 10) हिन्दी'
|
|
||||||
while :; do
|
|
||||||
read -rp 'Language [1 — English]: ' answer || { printf '[x] Input was interrupted\n' >&2; exit 1; }
|
|
||||||
answer="${answer:-1}"
|
|
||||||
case "$answer" in
|
|
||||||
1) UI_LANG=en ;; 2) UI_LANG=ru ;; 3) UI_LANG=es ;; 4) UI_LANG=de ;;
|
|
||||||
5) UI_LANG=fr ;; 6) UI_LANG=pt ;; 7) UI_LANG=zh ;; 8) UI_LANG=ja ;;
|
|
||||||
9) UI_LANG=ar ;; 10) UI_LANG=hi ;;
|
|
||||||
*) printf '[!] Enter a number from 1 to 10.\n' >&2; continue ;;
|
|
||||||
esac
|
|
||||||
break
|
|
||||||
done
|
|
||||||
load_ui_text
|
|
||||||
localize_program_catalog
|
|
||||||
}
|
|
||||||
|
|
||||||
# English is active until the user answers the first prompt. This also keeps
|
|
||||||
# sourced helper functions usable by the automated tests.
|
|
||||||
load_ui_text
|
load_ui_text
|
||||||
|
localize_program_catalog
|
||||||
|
|
||||||
log() { printf '[+] %s\n' "$*"; }
|
log() { printf '[+] %s\n' "$*"; }
|
||||||
warn() { printf '[!] %s\n' "$*" >&2; }
|
warn() { printf '[!] %s\n' "$*" >&2; }
|
||||||
|
|
@ -657,7 +640,6 @@ choose_timezone() {
|
||||||
}
|
}
|
||||||
|
|
||||||
[[ "$EUID" -eq 0 ]] || die "Run this script as root"
|
[[ "$EUID" -eq 0 ]] || die "Run this script as root"
|
||||||
choose_ui_language
|
|
||||||
for command_name in awk blkid fallocate grep mkswap swapon sysctl timedatectl; do
|
for command_name in awk blkid fallocate grep mkswap swapon sysctl timedatectl; do
|
||||||
command -v "$command_name" >/dev/null 2>&1 || die "$(msg required_missing "$command_name")"
|
command -v "$command_name" >/dev/null 2>&1 || die "$(msg required_missing "$command_name")"
|
||||||
done
|
done
|
||||||
|
|
|
||||||
|
|
@ -15,16 +15,180 @@ declare -a STEP_FILES=(
|
||||||
)
|
)
|
||||||
|
|
||||||
declare -a STEP_TITLES=(
|
declare -a STEP_TITLES=(
|
||||||
"Часовой пояс, язык терминала, набор программ и swap"
|
"Timezone, terminal language, programs, and swap"
|
||||||
"Базовые пакеты, будущий SSH-порт, IPv4/IPv6 и UFW"
|
"Base packages, SSH port, IPv4/IPv6, and UFW"
|
||||||
"Администратор, перенос SSH и fail2ban"
|
"Administrator, SSH migration, and fail2ban"
|
||||||
"Telegram-уведомления о входах по SSH"
|
"Telegram notifications for SSH logins"
|
||||||
"Системный VPN через Xray"
|
"System VPN through Xray"
|
||||||
"Панель 3x-ui и Cloudflare WARP"
|
"3x-ui panel and Cloudflare WARP"
|
||||||
"Первичный снимок и расписания резервного копирования"
|
"Initial snapshot and backup schedules"
|
||||||
)
|
)
|
||||||
|
|
||||||
TEMP_FILE=""
|
TEMP_FILE=""
|
||||||
|
UI_LANG=en
|
||||||
|
declare -A MASTER_TEXT=()
|
||||||
|
|
||||||
|
load_master_text() {
|
||||||
|
MASTER_TEXT=(
|
||||||
|
[intro_title]="Unified lightweight-server installer"
|
||||||
|
[intro_body]="Steps are shown in order. Each step can be installed, skipped, or used to exit the installer. Keep the current SSH session open while changing the SSH port and test the new login in another terminal."
|
||||||
|
[step]="Step %s of %s: %s"
|
||||||
|
[install]="Install / run this step"
|
||||||
|
[skip]="Skip and continue to the next step"
|
||||||
|
[finish]="Exit the installer"
|
||||||
|
[action]="Select an action: "
|
||||||
|
[invalid]="Enter 1, 2, or 3"
|
||||||
|
[interrupted]="Input was interrupted"
|
||||||
|
[failed]="The step failed."
|
||||||
|
[retry]="Run this step again"
|
||||||
|
[summary]="Installer completed."
|
||||||
|
[completed]="Steps completed successfully: %s"
|
||||||
|
[skipped]="Steps skipped: %s"
|
||||||
|
[rerun]="You can run the installer again; every step supports reconfiguration."
|
||||||
|
[reset]="For a complete reset, use ochenstarik-server-uninstall.sh."
|
||||||
|
[launch]="Running step %s: %s"
|
||||||
|
[success]="Step %s completed successfully"
|
||||||
|
[error]="Step %s returned an error"
|
||||||
|
)
|
||||||
|
|
||||||
|
case "$UI_LANG" in
|
||||||
|
ru) MASTER_TEXT+=(
|
||||||
|
[intro_title]="Единый мастер установки lightweight-server"
|
||||||
|
[intro_body]="Этапы будут показаны по порядку. Каждый можно установить, пропустить или завершить мастер. Не закрывайте текущую SSH-сессию при изменении порта и проверьте новый вход во втором терминале."
|
||||||
|
[step]="Этап %s из %s: %s" [install]="Установить / запустить этот этап"
|
||||||
|
[skip]="Пропустить и перейти к следующему" [finish]="Завершить мастер"
|
||||||
|
[action]="Выберите действие: " [invalid]="Введите 1, 2 или 3" [interrupted]="Ввод прерван"
|
||||||
|
[failed]="Этап завершился с ошибкой." [retry]="Запустить этот этап повторно"
|
||||||
|
[summary]="Мастер установки завершён." [completed]="Успешно выполнено этапов: %s"
|
||||||
|
[skipped]="Пропущено этапов: %s"
|
||||||
|
[rerun]="Мастер можно запустить повторно: каждый этап поддерживает повторную настройку."
|
||||||
|
[reset]="Для полного сброса используйте ochenstarik-server-uninstall.sh."
|
||||||
|
[launch]="Запуск этапа %s: %s" [success]="Этап %s успешно завершён" [error]="Этап %s вернул ошибку"
|
||||||
|
) ;;
|
||||||
|
es) MASTER_TEXT+=(
|
||||||
|
[intro_title]="Instalador unificado de lightweight-server"
|
||||||
|
[intro_body]="Los pasos se muestran en orden. Puede instalar, omitir o salir en cada paso. Mantenga abierta la sesión SSH actual al cambiar el puerto y pruebe el nuevo acceso en otro terminal."
|
||||||
|
[step]="Paso %s de %s: %s" [install]="Instalar / ejecutar este paso" [skip]="Omitir y continuar"
|
||||||
|
[finish]="Salir del instalador" [action]="Seleccione una acción: " [invalid]="Introduzca 1, 2 o 3"
|
||||||
|
[interrupted]="Entrada interrumpida" [failed]="El paso terminó con un error." [retry]="Ejecutar este paso de nuevo"
|
||||||
|
[summary]="Instalación finalizada." [completed]="Pasos completados: %s" [skipped]="Pasos omitidos: %s"
|
||||||
|
[rerun]="Puede ejecutar de nuevo el instalador; cada paso admite reconfiguración."
|
||||||
|
[reset]="Para un reinicio completo, use ochenstarik-server-uninstall.sh."
|
||||||
|
[launch]="Ejecutando el paso %s: %s" [success]="Paso %s completado" [error]="El paso %s devolvió un error"
|
||||||
|
) ;;
|
||||||
|
de) MASTER_TEXT+=(
|
||||||
|
[intro_title]="Einheitlicher lightweight-server-Installer"
|
||||||
|
[intro_body]="Die Schritte werden nacheinander angezeigt. Jeder Schritt kann installiert, übersprungen oder zum Beenden verwendet werden. Lassen Sie beim Ändern des SSH-Ports die aktuelle Sitzung geöffnet und testen Sie die neue Anmeldung in einem zweiten Terminal."
|
||||||
|
[step]="Schritt %s von %s: %s" [install]="Diesen Schritt installieren / ausführen" [skip]="Überspringen und fortfahren"
|
||||||
|
[finish]="Installer beenden" [action]="Aktion auswählen: " [invalid]="Geben Sie 1, 2 oder 3 ein"
|
||||||
|
[interrupted]="Eingabe unterbrochen" [failed]="Der Schritt ist fehlgeschlagen." [retry]="Diesen Schritt erneut ausführen"
|
||||||
|
[summary]="Installation abgeschlossen." [completed]="Erfolgreiche Schritte: %s" [skipped]="Übersprungene Schritte: %s"
|
||||||
|
[rerun]="Der Installer kann erneut ausgeführt werden; jeder Schritt unterstützt eine Neukonfiguration."
|
||||||
|
[reset]="Für ein vollständiges Zurücksetzen verwenden Sie ochenstarik-server-uninstall.sh."
|
||||||
|
[launch]="Schritt %s wird ausgeführt: %s" [success]="Schritt %s erfolgreich abgeschlossen" [error]="Schritt %s meldete einen Fehler"
|
||||||
|
) ;;
|
||||||
|
fr) MASTER_TEXT+=(
|
||||||
|
[intro_title]="Programme d’installation unifié lightweight-server"
|
||||||
|
[intro_body]="Les étapes sont présentées dans l’ordre. Chacune peut être installée, ignorée ou utilisée pour quitter. Gardez la session SSH actuelle ouverte pendant le changement de port et testez la nouvelle connexion dans un autre terminal."
|
||||||
|
[step]="Étape %s sur %s : %s" [install]="Installer / exécuter cette étape" [skip]="Ignorer et continuer"
|
||||||
|
[finish]="Quitter l’installation" [action]="Sélectionnez une action : " [invalid]="Saisissez 1, 2 ou 3"
|
||||||
|
[interrupted]="Saisie interrompue" [failed]="L’étape a échoué." [retry]="Relancer cette étape"
|
||||||
|
[summary]="Installation terminée." [completed]="Étapes réussies : %s" [skipped]="Étapes ignorées : %s"
|
||||||
|
[rerun]="Vous pouvez relancer l’installation ; chaque étape accepte une reconfiguration."
|
||||||
|
[reset]="Pour une réinitialisation complète, utilisez ochenstarik-server-uninstall.sh."
|
||||||
|
[launch]="Exécution de l’étape %s : %s" [success]="Étape %s réussie" [error]="L’étape %s a renvoyé une erreur"
|
||||||
|
) ;;
|
||||||
|
pt) MASTER_TEXT+=(
|
||||||
|
[intro_title]="Instalador unificado do lightweight-server"
|
||||||
|
[intro_body]="As etapas são mostradas em ordem. Cada etapa pode ser instalada, ignorada ou usada para sair. Mantenha a sessão SSH atual aberta ao alterar a porta e teste o novo acesso em outro terminal."
|
||||||
|
[step]="Etapa %s de %s: %s" [install]="Instalar / executar esta etapa" [skip]="Ignorar e continuar"
|
||||||
|
[finish]="Sair do instalador" [action]="Selecione uma ação: " [invalid]="Digite 1, 2 ou 3"
|
||||||
|
[interrupted]="Entrada interrompida" [failed]="A etapa falhou." [retry]="Executar esta etapa novamente"
|
||||||
|
[summary]="Instalação concluída." [completed]="Etapas concluídas: %s" [skipped]="Etapas ignoradas: %s"
|
||||||
|
[rerun]="O instalador pode ser executado novamente; todas as etapas aceitam reconfiguração."
|
||||||
|
[reset]="Para redefinir tudo, use ochenstarik-server-uninstall.sh."
|
||||||
|
[launch]="Executando a etapa %s: %s" [success]="Etapa %s concluída" [error]="A etapa %s retornou um erro"
|
||||||
|
) ;;
|
||||||
|
zh) MASTER_TEXT+=(
|
||||||
|
[intro_title]="lightweight-server 统一安装程序" [intro_body]="各步骤按顺序显示。每一步都可以安装、跳过或退出。更改 SSH 端口时请保持当前会话,并在另一个终端测试新连接。"
|
||||||
|
[step]="第 %s/%s 步:%s" [install]="安装 / 运行此步骤" [skip]="跳过并继续" [finish]="退出安装程序"
|
||||||
|
[action]="请选择操作:" [invalid]="请输入 1、2 或 3" [interrupted]="输入已中断"
|
||||||
|
[failed]="此步骤执行失败。" [retry]="重新运行此步骤" [summary]="安装程序已完成。"
|
||||||
|
[completed]="成功完成的步骤:%s" [skipped]="跳过的步骤:%s" [rerun]="可以再次运行安装程序;每个步骤都支持重新配置。"
|
||||||
|
[reset]="如需完全重置,请使用 ochenstarik-server-uninstall.sh。" [launch]="正在运行步骤 %s:%s"
|
||||||
|
[success]="步骤 %s 已成功完成" [error]="步骤 %s 返回错误"
|
||||||
|
) ;;
|
||||||
|
ja) MASTER_TEXT+=(
|
||||||
|
[intro_title]="lightweight-server 統合インストーラー" [intro_body]="手順は順番に表示されます。各手順は実行、スキップ、または終了できます。SSH ポートの変更中は現在のセッションを維持し、別のターミナルで新しい接続を確認してください。"
|
||||||
|
[step]="ステップ %s/%s: %s" [install]="このステップをインストール / 実行" [skip]="スキップして次へ"
|
||||||
|
[finish]="インストーラーを終了" [action]="操作を選択してください: " [invalid]="1、2、3 のいずれかを入力してください"
|
||||||
|
[interrupted]="入力が中断されました" [failed]="ステップが失敗しました。" [retry]="このステップを再実行"
|
||||||
|
[summary]="インストールが完了しました。" [completed]="成功したステップ: %s" [skipped]="スキップしたステップ: %s"
|
||||||
|
[rerun]="インストーラーは再実行でき、各ステップを再設定できます。" [reset]="完全にリセットするには ochenstarik-server-uninstall.sh を使用してください。"
|
||||||
|
[launch]="ステップ %s を実行中: %s" [success]="ステップ %s が完了しました" [error]="ステップ %s でエラーが発生しました"
|
||||||
|
) ;;
|
||||||
|
ar) MASTER_TEXT+=(
|
||||||
|
[intro_title]="مثبت lightweight-server الموحد" [intro_body]="تظهر المراحل بالترتيب. يمكن تثبيت كل مرحلة أو تخطيها أو الخروج. أبقِ جلسة SSH الحالية مفتوحة عند تغيير المنفذ واختبر الاتصال الجديد في طرفية أخرى."
|
||||||
|
[step]="المرحلة %s من %s: %s" [install]="تثبيت / تشغيل هذه المرحلة" [skip]="تخطي والمتابعة"
|
||||||
|
[finish]="إنهاء المثبت" [action]="اختر إجراءً: " [invalid]="أدخل 1 أو 2 أو 3" [interrupted]="تم إيقاف الإدخال"
|
||||||
|
[failed]="فشلت المرحلة." [retry]="تشغيل هذه المرحلة مرة أخرى" [summary]="اكتمل المثبت."
|
||||||
|
[completed]="المراحل المكتملة: %s" [skipped]="المراحل المتخطاة: %s" [rerun]="يمكن تشغيل المثبت مرة أخرى؛ كل مرحلة تدعم إعادة الإعداد."
|
||||||
|
[reset]="لإعادة الضبط الكامل استخدم ochenstarik-server-uninstall.sh." [launch]="تشغيل المرحلة %s: %s"
|
||||||
|
[success]="اكتملت المرحلة %s" [error]="أعادت المرحلة %s خطأ"
|
||||||
|
) ;;
|
||||||
|
hi) MASTER_TEXT+=(
|
||||||
|
[intro_title]="एकीकृत lightweight-server इंस्टॉलर" [intro_body]="चरण क्रम से दिखाए जाते हैं। प्रत्येक चरण को चलाया, छोड़ा या इंस्टॉलर बंद किया जा सकता है। SSH पोर्ट बदलते समय वर्तमान सत्र खुला रखें और दूसरे टर्मिनल में नया लॉगिन जाँचें।"
|
||||||
|
[step]="चरण %s/%s: %s" [install]="यह चरण इंस्टॉल / चलाएँ" [skip]="छोड़ें और आगे बढ़ें"
|
||||||
|
[finish]="इंस्टॉलर बंद करें" [action]="कार्रवाई चुनें: " [invalid]="1, 2 या 3 दर्ज करें" [interrupted]="इनपुट बाधित हुआ"
|
||||||
|
[failed]="चरण विफल हुआ।" [retry]="यह चरण फिर चलाएँ" [summary]="इंस्टॉलर पूरा हुआ।"
|
||||||
|
[completed]="सफल चरण: %s" [skipped]="छोड़े गए चरण: %s" [rerun]="इंस्टॉलर फिर चलाया जा सकता है; हर चरण पुनः कॉन्फ़िगर हो सकता है।"
|
||||||
|
[reset]="पूर्ण रीसेट के लिए ochenstarik-server-uninstall.sh का उपयोग करें।" [launch]="चरण %s चल रहा है: %s"
|
||||||
|
[success]="चरण %s सफल रहा" [error]="चरण %s में त्रुटि हुई"
|
||||||
|
) ;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
master_msg() {
|
||||||
|
local key="$1"
|
||||||
|
shift
|
||||||
|
printf "${MASTER_TEXT[$key]}" "$@"
|
||||||
|
}
|
||||||
|
|
||||||
|
localize_step_titles() {
|
||||||
|
case "$UI_LANG" in
|
||||||
|
ru) STEP_TITLES=("Часовой пояс, язык терминала, программы и swap" "Базовые пакеты, SSH-порт, IPv4/IPv6 и UFW" "Администратор, перенос SSH и fail2ban" "Telegram-уведомления о входах по SSH" "Системный VPN через Xray" "Панель 3x-ui и Cloudflare WARP" "Первичный снимок и расписания бэкапов") ;;
|
||||||
|
es) STEP_TITLES=("Zona horaria, idioma del terminal, programas y swap" "Paquetes base, puerto SSH, IPv4/IPv6 y UFW" "Administrador, migración SSH y fail2ban" "Notificaciones de Telegram para accesos SSH" "VPN del sistema mediante Xray" "Panel 3x-ui y Cloudflare WARP" "Instantánea inicial y copias programadas") ;;
|
||||||
|
de) STEP_TITLES=("Zeitzone, Terminalsprache, Programme und Swap" "Basispakete, SSH-Port, IPv4/IPv6 und UFW" "Administrator, SSH-Umstellung und fail2ban" "Telegram-Benachrichtigungen für SSH-Anmeldungen" "System-VPN über Xray" "3x-ui und Cloudflare WARP" "Erstsicherung und Sicherungspläne") ;;
|
||||||
|
fr) STEP_TITLES=("Fuseau horaire, langue du terminal, programmes et swap" "Paquets de base, port SSH, IPv4/IPv6 et UFW" "Administrateur, migration SSH et fail2ban" "Notifications Telegram des connexions SSH" "VPN système via Xray" "Panneau 3x-ui et Cloudflare WARP" "Instantané initial et sauvegardes planifiées") ;;
|
||||||
|
pt) STEP_TITLES=("Fuso horário, idioma do terminal, programas e swap" "Pacotes básicos, porta SSH, IPv4/IPv6 e UFW" "Administrador, migração SSH e fail2ban" "Notificações Telegram de logins SSH" "VPN do sistema via Xray" "Painel 3x-ui e Cloudflare WARP" "Snapshot inicial e backups agendados") ;;
|
||||||
|
zh) STEP_TITLES=("时区、终端语言、程序和交换文件" "基础软件包、SSH 端口、IPv4/IPv6 和 UFW" "管理员、SSH 迁移和 fail2ban" "SSH 登录的 Telegram 通知" "通过 Xray 的系统 VPN" "3x-ui 面板和 Cloudflare WARP" "初始快照和备份计划") ;;
|
||||||
|
ja) STEP_TITLES=("タイムゾーン、端末言語、プログラム、スワップ" "基本パッケージ、SSH ポート、IPv4/IPv6、UFW" "管理者、SSH 移行、fail2ban" "SSH ログインの Telegram 通知" "Xray によるシステム VPN" "3x-ui パネルと Cloudflare WARP" "初回スナップショットとバックアップ予定") ;;
|
||||||
|
ar) STEP_TITLES=("المنطقة الزمنية ولغة الطرفية والبرامج وswap" "الحزم الأساسية ومنفذ SSH وIPv4/IPv6 وUFW" "المسؤول ونقل SSH وfail2ban" "إشعارات Telegram لدخول SSH" "VPN للنظام عبر Xray" "لوحة 3x-ui وCloudflare WARP" "النسخة الأولية وجداول النسخ الاحتياطي") ;;
|
||||||
|
hi) STEP_TITLES=("समय क्षेत्र, टर्मिनल भाषा, प्रोग्राम और swap" "मूल पैकेज, SSH पोर्ट, IPv4/IPv6 और UFW" "प्रशासक, SSH स्थानांतरण और fail2ban" "SSH लॉगिन की Telegram सूचनाएँ" "Xray द्वारा सिस्टम VPN" "3x-ui पैनल और Cloudflare WARP" "प्रारंभिक स्नैपशॉट और बैकअप अनुसूचियाँ") ;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
choose_dialog_language() {
|
||||||
|
local answer
|
||||||
|
printf '\nSelect the installer language / Выберите язык установщика:\n'
|
||||||
|
printf '%s\n' ' 1) English' ' 2) Русский' ' 3) Español' ' 4) Deutsch' \
|
||||||
|
' 5) Français' ' 6) Português' ' 7) 中文' ' 8) 日本語' ' 9) العربية' ' 10) हिन्दी'
|
||||||
|
while :; do
|
||||||
|
read -rp 'Language [1 — English]: ' answer || die "Input was interrupted"
|
||||||
|
answer="${answer:-1}"
|
||||||
|
case "$answer" in
|
||||||
|
1) UI_LANG=en ;; 2) UI_LANG=ru ;; 3) UI_LANG=es ;; 4) UI_LANG=de ;; 5) UI_LANG=fr ;;
|
||||||
|
6) UI_LANG=pt ;; 7) UI_LANG=zh ;; 8) UI_LANG=ja ;; 9) UI_LANG=ar ;; 10) UI_LANG=hi ;;
|
||||||
|
*) warn "Enter a number from 1 to 10"; continue ;;
|
||||||
|
esac
|
||||||
|
break
|
||||||
|
done
|
||||||
|
export OCHENSTARIK_UI_LANG="$UI_LANG"
|
||||||
|
load_master_text
|
||||||
|
localize_step_titles
|
||||||
|
}
|
||||||
|
|
||||||
|
load_master_text
|
||||||
|
|
||||||
log() { printf '[+] %s\n' "$*"; }
|
log() { printf '[+] %s\n' "$*"; }
|
||||||
warn() { printf '[!] %s\n' "$*" >&2; }
|
warn() { printf '[!] %s\n' "$*" >&2; }
|
||||||
|
|
@ -71,14 +235,14 @@ choose_step_action() {
|
||||||
local step_number="$1" title="$2" result_variable="$3" answer
|
local step_number="$1" title="$2" result_variable="$3" answer
|
||||||
while :; do
|
while :; do
|
||||||
printf '\n============================================================\n'
|
printf '\n============================================================\n'
|
||||||
printf 'Этап %s из %s: %s\n' "$step_number" "${#STEP_FILES[@]}" "$title"
|
printf '%s\n' "$(master_msg step "$step_number" "${#STEP_FILES[@]}" "$title")"
|
||||||
printf ' 1) Установить / запустить этот этап\n'
|
printf ' 1) %s\n' "$(master_msg install)"
|
||||||
printf ' 2) Пропустить и перейти к следующему\n'
|
printf ' 2) %s\n' "$(master_msg skip)"
|
||||||
printf ' 3) Завершить мастер\n'
|
printf ' 3) %s\n' "$(master_msg finish)"
|
||||||
read -rp 'Выберите действие: ' answer || die "Ввод прерван"
|
read -rp "$(master_msg action)" answer || die "$(master_msg interrupted)"
|
||||||
case "$answer" in
|
case "$answer" in
|
||||||
1|2|3) printf -v "$result_variable" '%s' "$answer"; return 0 ;;
|
1|2|3) printf -v "$result_variable" '%s' "$answer"; return 0 ;;
|
||||||
*) warn "Введите 1, 2 или 3" ;;
|
*) warn "$(master_msg invalid)" ;;
|
||||||
esac
|
esac
|
||||||
done
|
done
|
||||||
}
|
}
|
||||||
|
|
@ -86,14 +250,14 @@ choose_step_action() {
|
||||||
choose_after_failure() {
|
choose_after_failure() {
|
||||||
local result_variable="$1" answer
|
local result_variable="$1" answer
|
||||||
while :; do
|
while :; do
|
||||||
printf '\nЭтап завершился с ошибкой.\n'
|
printf '\n%s\n' "$(master_msg failed)"
|
||||||
printf ' 1) Запустить этот этап повторно\n'
|
printf ' 1) %s\n' "$(master_msg retry)"
|
||||||
printf ' 2) Пропустить и перейти к следующему\n'
|
printf ' 2) %s\n' "$(master_msg skip)"
|
||||||
printf ' 3) Завершить мастер\n'
|
printf ' 3) %s\n' "$(master_msg finish)"
|
||||||
read -rp 'Выберите действие: ' answer || die "Ввод прерван"
|
read -rp "$(master_msg action)" answer || die "$(master_msg interrupted)"
|
||||||
case "$answer" in
|
case "$answer" in
|
||||||
1|2|3) printf -v "$result_variable" '%s' "$answer"; return 0 ;;
|
1|2|3) printf -v "$result_variable" '%s' "$answer"; return 0 ;;
|
||||||
*) warn "Введите 1, 2 или 3" ;;
|
*) warn "$(master_msg invalid)" ;;
|
||||||
esac
|
esac
|
||||||
done
|
done
|
||||||
}
|
}
|
||||||
|
|
@ -101,24 +265,19 @@ choose_after_failure() {
|
||||||
print_summary() {
|
print_summary() {
|
||||||
local completed="$1" skipped="$2"
|
local completed="$1" skipped="$2"
|
||||||
printf '\n============================================================\n'
|
printf '\n============================================================\n'
|
||||||
printf 'Мастер установки завершён.\n'
|
printf '%s\n' "$(master_msg summary)"
|
||||||
printf 'Успешно выполнено этапов: %s\n' "$completed"
|
printf '%s\n' "$(master_msg completed "$completed")"
|
||||||
printf 'Пропущено этапов: %s\n' "$skipped"
|
printf '%s\n' "$(master_msg skipped "$skipped")"
|
||||||
printf '\nМастер можно запустить повторно: каждый этап поддерживает повторную настройку.\n'
|
printf '\n%s\n' "$(master_msg rerun)"
|
||||||
printf 'Для полного сброса используйте ochenstarik-server-uninstall.sh.\n'
|
printf '%s\n' "$(master_msg reset)"
|
||||||
}
|
}
|
||||||
|
|
||||||
[[ "$EUID" -eq 0 ]] || die "Запустите мастер от имени root: sudo ./ochenstarik-server-install.sh"
|
[[ "$EUID" -eq 0 ]] || die "Запустите мастер от имени root: sudo ./ochenstarik-server-install.sh"
|
||||||
((${#STEP_FILES[@]} == ${#STEP_TITLES[@]})) || die "Некорректное описание этапов"
|
((${#STEP_FILES[@]} == ${#STEP_TITLES[@]})) || die "Некорректное описание этапов"
|
||||||
|
|
||||||
cat <<'INTRO'
|
choose_dialog_language
|
||||||
|
|
||||||
Единый мастер установки lightweight-server
|
printf '\n%s\n\n%s\n' "$(master_msg intro_title)" "$(master_msg intro_body)"
|
||||||
|
|
||||||
Этапы будут показаны по порядку. Каждый из них можно выполнить, пропустить
|
|
||||||
или завершить весь мастер. Не закрывайте текущую SSH-сессию во время изменения
|
|
||||||
порта SSH и проверяйте новый вход во втором терминале.
|
|
||||||
INTRO
|
|
||||||
|
|
||||||
completed=0
|
completed=0
|
||||||
skipped=0
|
skipped=0
|
||||||
|
|
@ -141,14 +300,14 @@ for index in "${!STEP_FILES[@]}"; do
|
||||||
script_path=""
|
script_path=""
|
||||||
ensure_step_script "${STEP_FILES[index]}" script_path
|
ensure_step_script "${STEP_FILES[index]}" script_path
|
||||||
while :; do
|
while :; do
|
||||||
log "Запуск этапа ${step_number}: ${STEP_TITLES[index]}"
|
log "$(master_msg launch "$step_number" "${STEP_TITLES[index]}")"
|
||||||
if bash -- "$script_path"; then
|
if bash -- "$script_path"; then
|
||||||
completed="$((completed + 1))"
|
completed="$((completed + 1))"
|
||||||
log "Этап ${step_number} успешно завершён"
|
log "$(master_msg success "$step_number")"
|
||||||
break
|
break
|
||||||
fi
|
fi
|
||||||
|
|
||||||
warn "Этап ${step_number} вернул ошибку"
|
warn "$(master_msg error "$step_number")"
|
||||||
failure_action=""
|
failure_action=""
|
||||||
choose_after_failure failure_action
|
choose_after_failure failure_action
|
||||||
case "$failure_action" in
|
case "$failure_action" in
|
||||||
|
|
|
||||||
22
tests/test-master-language.sh
Normal file
22
tests/test-master-language.sh
Normal file
|
|
@ -0,0 +1,22 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
set -Eeuo pipefail
|
||||||
|
|
||||||
|
cd -- "$(dirname -- "${BASH_SOURCE[0]}")/.."
|
||||||
|
source <(awk '/^\[\[ "\$EUID"/{exit} {print}' ochenstarik-server-install.sh)
|
||||||
|
|
||||||
|
declare -a expected=(en ru es de fr pt zh ja ar hi)
|
||||||
|
for index in "${!expected[@]}"; do
|
||||||
|
choose_dialog_language <<< "$((index + 1))" >/dev/null
|
||||||
|
[[ "$UI_LANG" == "${expected[index]}" ]]
|
||||||
|
[[ "$OCHENSTARIK_UI_LANG" == "${expected[index]}" ]]
|
||||||
|
done
|
||||||
|
|
||||||
|
choose_dialog_language <<< '' >/dev/null
|
||||||
|
[[ "$UI_LANG" == en ]]
|
||||||
|
[[ "$(master_msg install)" == 'Install / run this step' ]]
|
||||||
|
|
||||||
|
choose_dialog_language <<< '2' >/dev/null
|
||||||
|
[[ "$(master_msg install)" == 'Установить / запустить этот этап' ]]
|
||||||
|
[[ "${STEP_TITLES[0]}" == 'Часовой пояс, язык терминала, программы и swap' ]]
|
||||||
|
|
||||||
|
printf 'Master language selection tests passed.\n'
|
||||||
|
|
@ -32,14 +32,6 @@ contains_package() {
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
declare -a EXPECTED_UI_LANGUAGES=(en ru es de fr pt zh ja ar hi)
|
|
||||||
for index in "${!EXPECTED_UI_LANGUAGES[@]}"; do
|
|
||||||
choose_ui_language <<< "$((index + 1))" >/dev/null
|
|
||||||
[[ "$UI_LANG" == "${EXPECTED_UI_LANGUAGES[index]}" ]]
|
|
||||||
done
|
|
||||||
choose_ui_language <<< '' >/dev/null
|
|
||||||
[[ "$UI_LANG" == en ]]
|
|
||||||
|
|
||||||
choose_and_install_programs <<< '1 3' >/dev/null
|
choose_and_install_programs <<< '1 3' >/dev/null
|
||||||
contains_package git
|
contains_package git
|
||||||
contains_package iotop
|
contains_package iotop
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue