diff --git a/web/service/tgbot.go b/web/service/tgbot.go
index 794f5c7b..4c6a3c71 100644
--- a/web/service/tgbot.go
+++ b/web/service/tgbot.go
@@ -11,6 +11,7 @@ import (
"net/url"
"os"
"regexp"
+ "sort"
"strconv"
"strings"
"time"
@@ -397,10 +398,9 @@ func (t *Tgbot) OnReceive() {
smsg := message.Text
delete(userStates, message.Chat.ID)
- // Получаем все инбаунды
inbounds, err := t.inboundService.GetAllInbounds()
if err != nil {
- t.SendMsgToTgbot(message.Chat.ID, "Ошибка получения inbounds: "+err.Error(), tu.ReplyKeyboardRemove())
+ t.SendMsgToTgbot(message.Chat.ID, t.I18nBot("tgbot.inboundError")+err.Error(), tu.ReplyKeyboardRemove())
return
}
@@ -408,21 +408,98 @@ func (t *Tgbot) OnReceive() {
for _, inbound := range inbounds {
clients, err := t.inboundService.GetClients(inbound)
if err != nil {
- t.SendMsgToTgbot(message.Chat.ID, "Ошибка получения клиентов: "+err.Error(), tu.ReplyKeyboardRemove())
+ t.SendMsgToTgbot(message.Chat.ID, t.I18nBot("tgbot.clientError")+err.Error(), tu.ReplyKeyboardRemove())
continue
}
allClients = append(allClients, clients...)
}
- // Формируем строку для вывода (dev-версия)
- var sb strings.Builder
- sb.WriteString("Получено сообщение для рассылки: \n")
- sb.WriteString(smsg + "\n\n")
- sb.WriteString("Все пользователи (структуры):\n")
- for i, client := range allClients {
- sb.WriteString(fmt.Sprintf("%d: %+v\n", i+1, client))
+ count := 0
+ for _, client := range allClients {
+ if client.TgID != 0 {
+ t.SendMsgToTgbot(client.TgID, smsg)
+ count++
+ }
}
- t.SendMsgToTgbot(message.Chat.ID, sb.String(), tu.ReplyKeyboardRemove())
+
+ resultMsg := fmt.Sprintf(t.I18nBot("tgbot.broadcastMessageSent"), "Count=="+strconv.Itoa(count))
+ t.SendMsgToTgbot(message.Chat.ID, resultMsg, tu.ReplyKeyboardRemove())
+ case "awaiting_choose_user":
+ inboundIdStr, ok := userStates[message.Chat.ID+1000000000]
+ if !ok {
+ inbounds, err := t.inboundService.GetAllInbounds()
+ if err != nil || len(inbounds) == 0 {
+ t.SendMsgToTgbot(message.Chat.ID, t.I18nBot("tgbot.answers.getInboundsFailed"), tu.ReplyKeyboardRemove())
+ delete(userStates, message.Chat.ID)
+ return
+ }
+ var buttons []telego.InlineKeyboardButton
+ for _, inbound := range inbounds {
+ btnText := inbound.Remark
+ callback := t.encodeQuery("broadcast_choose_inbound " + strconv.Itoa(inbound.Id))
+ buttons = append(buttons, tu.InlineKeyboardButton(btnText).WithCallbackData(callback))
+ }
+ keyboard := tu.InlineKeyboardGrid(tu.InlineKeyboardCols(2, buttons...))
+ t.SendMsgToTgbot(message.Chat.ID, t.I18nBot("tgbot.answers.chooseBroadcastInbound"), keyboard)
+ return
+ }
+ email := strings.TrimSpace(message.Text)
+ inboundId, _ := strconv.Atoi(inboundIdStr)
+ inbound, err := t.inboundService.GetInbound(inboundId)
+ if err != nil {
+ t.SendMsgToTgbot(message.Chat.ID, t.I18nBot("tgbot.answers.getInboundsFailed"), tu.ReplyKeyboardRemove())
+ delete(userStates, message.Chat.ID)
+ return
+ }
+ clients, err := t.inboundService.GetClients(inbound)
+ if err != nil {
+ t.SendMsgToTgbot(message.Chat.ID, t.I18nBot("tgbot.answers.getClientsFailed"), tu.ReplyKeyboardRemove())
+ delete(userStates, message.Chat.ID)
+ return
+ }
+ var found *model.Client
+ for _, c := range clients {
+ if c.Email == email {
+ found = &c
+ break
+ }
+ }
+ if found == nil {
+ t.SendMsgToTgbot(message.Chat.ID, t.I18nBot("tgbot.answers.broadcastUserNotFound"), tu.ReplyKeyboardRemove())
+ return
+ }
+ if found.TgID == 0 {
+ t.SendMsgToTgbot(message.Chat.ID, t.I18nBot("tgbot.answers.broadcastUserNoTgId"), tu.ReplyKeyboardRemove())
+ return
+ }
+ userStates[message.Chat.ID+2000000000] = email
+ userStates[message.Chat.ID] = "awaiting_broadcast_message_user"
+ t.SendMsgToTgbot(message.Chat.ID, t.I18nBot("tgbot.answers.broadcastEnterText"), tu.ForceReply())
+ return
+ case "awaiting_broadcast_message_user":
+ email := userStates[message.Chat.ID+2000000000]
+ inboundIdStr := userStates[message.Chat.ID+1000000000]
+ inboundId, _ := strconv.Atoi(inboundIdStr)
+ inbound, _ := t.inboundService.GetInbound(inboundId)
+ clients, _ := t.inboundService.GetClients(inbound)
+ var found *model.Client
+ for _, c := range clients {
+ if c.Email == email {
+ found = &c
+ break
+ }
+ }
+ if found != nil && found.TgID != 0 {
+ t.SendMsgToTgbot(found.TgID, message.Text)
+ msg := t.I18nBot("tgbot.answers.broadcastSentToUser", "Email=="+email)
+ t.SendMsgToTgbot(message.Chat.ID, msg, tu.ReplyKeyboardRemove())
+ } else {
+ t.SendMsgToTgbot(message.Chat.ID, t.I18nBot("tgbot.answers.broadcastUserNoTgId"), tu.ReplyKeyboardRemove())
+ }
+ delete(userStates, message.Chat.ID)
+ delete(userStates, message.Chat.ID+1000000000)
+ delete(userStates, message.Chat.ID+2000000000)
+ return
}
} else {
@@ -1658,6 +1735,100 @@ func (t *Tgbot) answerCallback(callbackQuery *telego.CallbackQuery, isAdmin bool
msg := t.I18nBot("tgbot.messages.enterMessageText")
t.SendMsgToTgbot(chatId, msg, tu.ForceReply())
userStates[chatId] = "awaiting_broadcast_message"
+ case "message_send_user":
+ inbounds, err := t.inboundService.GetAllInbounds()
+ if err != nil || len(inbounds) == 0 {
+ t.SendMsgToTgbot(chatId, t.I18nBot("tgbot.answers.getInboundsFailed"), tu.ReplyKeyboardRemove())
+ return
+ }
+ var buttons []telego.InlineKeyboardButton
+ for _, inbound := range inbounds {
+ btnText := inbound.Remark
+ callback := t.encodeQuery("broadcast_choose_inbound " + strconv.Itoa(inbound.Id))
+ buttons = append(buttons, tu.InlineKeyboardButton(btnText).WithCallbackData(callback))
+ }
+ keyboard := tu.InlineKeyboardGrid(tu.InlineKeyboardCols(2, buttons...))
+ t.SendMsgToTgbot(chatId, t.I18nBot("tgbot.answers.chooseBroadcastInbound"), keyboard)
+ userStates[chatId] = "awaiting_choose_user"
+ return
+ case "broadcast_choose_inbound":
+ dataArray := strings.Split(callbackQuery.Data, " ")
+ inboundId, _ := strconv.Atoi(dataArray[1])
+ userStates[chatId+1000000000] = strconv.Itoa(inboundId)
+ inbound, err := t.inboundService.GetInbound(inboundId)
+ if err != nil {
+ t.SendMsgToTgbot(chatId, t.I18nBot("tgbot.answers.getInboundsFailed"), tu.ReplyKeyboardRemove())
+ delete(userStates, chatId)
+ return
+ }
+ clients, err := t.inboundService.GetClients(inbound)
+ if err != nil {
+ t.SendMsgToTgbot(chatId, t.I18nBot("tgbot.answers.getClientsFailed"), tu.ReplyKeyboardRemove())
+ delete(userStates, chatId)
+ return
+ }
+ topClients := make([]model.Client, 0, 9)
+ currentTgId := chatId
+ sort.Slice(clients, func(i, j int) bool {
+ return clients[i].TotalGB > clients[j].TotalGB
+ })
+ for _, c := range clients {
+ if len(topClients) >= 9 {
+ break
+ }
+ if c.TgID != 0 && c.TgID != currentTgId {
+ topClients = append(topClients, c)
+ }
+ }
+ var userButtons []telego.InlineKeyboardButton
+ for _, c := range topClients {
+ userButtons = append(userButtons, tu.InlineKeyboardButton(c.Email).WithCallbackData(t.encodeQuery("broadcast_choose_user "+c.Email)))
+ }
+ userButtons = append(userButtons, tu.InlineKeyboardButton("Ввести email").WithCallbackData(t.encodeQuery("broadcast_enter_email")))
+ keyboardUsers := tu.InlineKeyboardGrid(tu.InlineKeyboardCols(1, userButtons...))
+ t.SendMsgToTgbot(chatId, t.I18nBot("tgbot.answers.chooseBroadcastUser"), keyboardUsers)
+ userStates[chatId] = "awaiting_choose_user"
+ return
+ case "broadcast_choose_user":
+ inboundIdStr := userStates[chatId+1000000000]
+ inboundId, _ := strconv.Atoi(inboundIdStr)
+ inbound, err := t.inboundService.GetInbound(inboundId)
+ dataArray := strings.Split(callbackQuery.Data, " ")
+ if err != nil {
+ t.SendMsgToTgbot(chatId, t.I18nBot("tgbot.answers.getInboundsFailed"), tu.ReplyKeyboardRemove())
+ delete(userStates, chatId)
+ return
+ }
+ email := dataArray[1]
+ clients, err := t.inboundService.GetClients(inbound)
+ if err != nil {
+ t.SendMsgToTgbot(chatId, t.I18nBot("tgbot.answers.getClientsFailed"), tu.ReplyKeyboardRemove())
+ delete(userStates, chatId)
+ return
+ }
+ var found *model.Client
+ for _, c := range clients {
+ if c.Email == email {
+ found = &c
+ break
+ }
+ }
+ if found == nil {
+ t.SendMsgToTgbot(chatId, t.I18nBot("tgbot.answers.broadcastUserNotFound"), tu.ReplyKeyboardRemove())
+ return
+ }
+ if found.TgID == 0 {
+ t.SendMsgToTgbot(chatId, t.I18nBot("tgbot.answers.broadcastUserNoTgId"), tu.ReplyKeyboardRemove())
+ return
+ }
+ userStates[chatId+2000000000] = email
+ userStates[chatId] = "awaiting_broadcast_message_user"
+ t.SendMsgToTgbot(chatId, t.I18nBot("tgbot.answers.broadcastEnterText"), tu.ForceReply())
+ return
+ case "broadcast_enter_email":
+ userStates[chatId] = "awaiting_choose_user"
+ t.SendMsgToTgbot(chatId, t.I18nBot("tgbot.answers.chooseUser"), tu.ForceReply())
+ return
}
}
diff --git a/web/translation/translate.ar_EG.toml b/web/translation/translate.ar_EG.toml
index 5a86bc07..c80fc64f 100644
--- a/web/translation/translate.ar_EG.toml
+++ b/web/translation/translate.ar_EG.toml
@@ -736,3 +736,14 @@
"askToAddUserId" = "مافيش إعدادات ليك!\r\nاطلب من الأدمن يضيف الـ Telegram ChatID الخاص بيك في إعداداتك.\r\n\r\nالـ ChatID بتاعك: {{ .TgUserID }}
"
"chooseClient" = "اختار عميل للإدخال {{ .Inbound }}"
"chooseInbound" = "اختار الإدخال"
+
+"enterText" = "أدخل نص الرسالة المطلوب لإرساله لجميع المستخدمين"
+"inboundError" = "❌ حدث خطأ أثناء جلب بيانات الإدخال"
+"clientError" = "❌ حدث خطأ أثناء جلب المستخدمين"
+"broadcastMessageSent" = "تم إرسال الرسالة إلى {{ .Count }} مستخدمًا"
+"chooseBroadcastInbound" = "اختر الإدخال للإرسال الجماعي"
+"chooseBroadcastUser" = "اختر المستخدم للإرسال الجماعي أو أدخل البريد الإلكتروني يدويًا"
+"broadcastUserNotFound" = "❌ لم يتم العثور على مستخدم بهذا البريد الإلكتروني في الإدخال المحدد."
+"broadcastUserNoTgId" = "❌ المستخدم لا يحتوي على معرف Telegram، لا يمكن الإرسال الجماعي."
+"broadcastEnterText" = "أدخل نص الرسالة للمستخدم المحدد"
+"broadcastSentToUser" = "تم إرسال الرسالة إلى المستخدم: {{ .Email }}"
diff --git a/web/translation/translate.en_US.toml b/web/translation/translate.en_US.toml
index 977970e9..95d3bc1d 100644
--- a/web/translation/translate.en_US.toml
+++ b/web/translation/translate.en_US.toml
@@ -734,3 +734,14 @@
"askToAddUserId" = "Your configuration is not found!\r\nPlease ask your admin to use your Telegram ChatID in your configuration(s).\r\n\r\nYour ChatID: {{ .TgUserID }}
"
"chooseClient" = "Choose a Client for Inbound {{ .Inbound }}"
"chooseInbound" = "Choose an Inbound"
+
+"enterText" = "Enter the desired message text to send to all users"
+"inboundError" = "❌ Error getting inbounds"
+"clientError" = "❌ Error getting users"
+"broadcastMessageSent" = "Message sent to {{ .Count }} users"
+"chooseBroadcastInbound" = "Choose inbound for broadcast"
+"chooseBroadcastUser" = "Choose user for broadcast or enter email manually"
+"broadcastUserNotFound" = "❌ User with this email not found in the selected inbound."
+"broadcastUserNoTgId" = "❌ User does not have a Telegram ID, broadcast not possible."
+"broadcastEnterText" = "Enter the message text for the selected user"
+"broadcastSentToUser" = "Message sent to user: {{ .Email }}"
diff --git a/web/translation/translate.es_ES.toml b/web/translation/translate.es_ES.toml
index 63345022..6dc36713 100644
--- a/web/translation/translate.es_ES.toml
+++ b/web/translation/translate.es_ES.toml
@@ -738,3 +738,14 @@
"askToAddUserId" = "¡No se encuentra su configuración!\r\nPor favor, pídale a su administrador que use su ChatID de usuario de Telegram en su(s) configuración(es).\r\n\r\nSu ChatID de usuario: {{ .TgUserID }}
"
"chooseClient" = "Elige un Cliente para Inbound {{ .Inbound }}"
"chooseInbound" = "Elige un Inbound"
+
+"enterText" = "Introduce el texto del mensaje que deseas enviar a todos los usuarios"
+"inboundError" = "❌ Error al obtener los inbounds"
+"clientError" = "❌ Error al obtener los usuarios"
+"broadcastMessageSent" = "Mensaje enviado a {{ .Count }} usuarios"
+"chooseBroadcastInbound" = "Elige el inbound para el broadcast"
+"chooseBroadcastUser" = "Elige el usuario para el broadcast o introduce el correo electrónico manualmente"
+"broadcastUserNotFound" = "❌ No se encontró un usuario con este correo electrónico en el inbound seleccionado."
+"broadcastUserNoTgId" = "❌ El usuario no tiene Telegram ID, no es posible el broadcast."
+"broadcastEnterText" = "Introduce el texto del mensaje para el usuario seleccionado"
+"broadcastSentToUser" = "Mensaje enviado al usuario: {{ .Email }}"
diff --git a/web/translation/translate.fa_IR.toml b/web/translation/translate.fa_IR.toml
index 45cb3982..69c2129b 100644
--- a/web/translation/translate.fa_IR.toml
+++ b/web/translation/translate.fa_IR.toml
@@ -738,3 +738,14 @@
"askToAddUserId" = "پیکربندی شما یافت نشد!\r\nلطفاً از مدیر خود بخواهید که شناسه کاربر تلگرام خود را در پیکربندی (های) خود استفاده کند.\r\n\r\nشناسه کاربری شما: {{ .TgUserID }}
"
"chooseClient" = "یک مشتری برای ورودی {{ .Inbound }} انتخاب کنید"
"chooseInbound" = "یک ورودی انتخاب کنید"
+
+"enterText" = "متن پیام مورد نظر برای ارسال به همه کاربران را وارد کنید"
+"inboundError" = "❌ خطا در دریافت ورودیها"
+"clientError" = "❌ خطا در دریافت کاربران"
+"broadcastMessageSent" = "پیام به {{ .Count }} کاربر ارسال شد"
+"chooseBroadcastInbound" = "ورودی را برای ارسال انتخاب کنید"
+"chooseBroadcastUser" = "کاربر را برای ارسال انتخاب کنید یا ایمیل را به صورت دستی وارد کنید"
+"broadcastUserNotFound" = "❌ کاربری با این ایمیل در ورودی انتخاب شده یافت نشد."
+"broadcastUserNoTgId" = "❌ کاربر Telegram ID ندارد، ارسال پیام ممکن نیست."
+"broadcastEnterText" = "متن پیام برای کاربر انتخاب شده را وارد کنید"
+"broadcastSentToUser" = "پیام به کاربر ارسال شد: {{ .Email }}"
diff --git a/web/translation/translate.id_ID.toml b/web/translation/translate.id_ID.toml
index 149a006c..91cdc3c5 100644
--- a/web/translation/translate.id_ID.toml
+++ b/web/translation/translate.id_ID.toml
@@ -739,3 +739,14 @@
"askToAddUserId" = "Konfigurasi Anda tidak ditemukan!\r\nSilakan minta admin Anda untuk menggunakan ChatID Telegram Anda dalam konfigurasi Anda.\r\n\r\nChatID Pengguna Anda: {{ .TgUserID }}
"
"chooseClient" = "Pilih Klien untuk Inbound {{ .Inbound }}"
"chooseInbound" = "Pilih Inbound"
+
+"enterText" = "Masukkan teks pesan yang diinginkan untuk dikirim ke semua pengguna"
+"inboundError" = "❌ Terjadi kesalahan saat mengambil data inbound"
+"clientError" = "❌ Terjadi kesalahan saat mengambil pengguna"
+"broadcastMessageSent" = "Pesan telah dikirim ke {{ .Count }} pengguna"
+"chooseBroadcastInbound" = "Pilih inbound untuk siaran"
+"chooseBroadcastUser" = "Pilih pengguna untuk siaran atau masukkan email secara manual"
+"broadcastUserNotFound" = "❌ Pengguna dengan email ini tidak ditemukan di inbound yang dipilih."
+"broadcastUserNoTgId" = "❌ Pengguna tidak memiliki Telegram ID, siaran tidak dapat dilakukan."
+"broadcastEnterText" = "Masukkan teks pesan untuk pengguna yang dipilih"
+"broadcastSentToUser" = "Pesan telah dikirim ke pengguna: {{ .Email }}"
diff --git a/web/translation/translate.ja_JP.toml b/web/translation/translate.ja_JP.toml
index 98b136f8..9f3161a5 100644
--- a/web/translation/translate.ja_JP.toml
+++ b/web/translation/translate.ja_JP.toml
@@ -738,3 +738,14 @@
"askToAddUserId" = "設定が見つかりませんでした!\r\n管理者に問い合わせて、設定にTelegramユーザーのChatIDを使用してください。\r\n\r\nあなたのユーザーChatID:{{ .TgUserID }}
"
"chooseClient" = "インバウンド {{ .Inbound }} のクライアントを選択"
"chooseInbound" = "インバウンドを選択"
+
+"enterText" = "すべてのユーザーに送信するメッセージのテキストを入力してください"
+"inboundError" = "❌ インバウンドの取得中にエラーが発生しました"
+"clientError" = "❌ ユーザーの取得中にエラーが発生しました"
+"broadcastMessageSent" = "メッセージは{{ .Count }}人のユーザーに送信されました"
+"chooseBroadcastInbound" = "ブロードキャスト用のインバウンドを選択"
+"chooseBroadcastUser" = "ブロードキャスト用のユーザーを選択するか、メールアドレスを手動で入力してください"
+"broadcastUserNotFound" = "❌ 選択したインバウンドにこのメールアドレスのユーザーが見つかりません。"
+"broadcastUserNoTgId" = "❌ ユーザーにTelegram IDが設定されていないため、ブロードキャストできません。"
+"broadcastEnterText" = "選択したユーザーに送信するメッセージのテキストを入力してください"
+"broadcastSentToUser" = "メッセージはユーザーに送信されました: {{ .Email }}"
diff --git a/web/translation/translate.pt_BR.toml b/web/translation/translate.pt_BR.toml
index 71044abd..e3449ed6 100644
--- a/web/translation/translate.pt_BR.toml
+++ b/web/translation/translate.pt_BR.toml
@@ -738,3 +738,14 @@
"askToAddUserId" = "Sua configuração não foi encontrada!\r\nPeça ao seu administrador para usar seu Telegram ChatID em suas configurações.\r\n\r\nSeu ChatID: {{ .TgUserID }}
"
"chooseClient" = "Escolha um cliente para Inbound {{ .Inbound }}"
"chooseInbound" = "Escolha um Inbound"
+
+"enterText" = "Digite o texto da mensagem desejada para enviar a todos os usuários"
+"inboundError" = "❌ Erro ao obter inbounds"
+"clientError" = "❌ Erro ao obter usuários"
+"broadcastMessageSent" = "Mensagem enviada para {{ .Count }} usuários"
+"chooseBroadcastInbound" = "Escolha o inbound para broadcast"
+"chooseBroadcastUser" = "Escolha o usuário para broadcast ou insira o e-mail manualmente"
+"broadcastUserNotFound" = "❌ Usuário com este e-mail não encontrado no inbound selecionado."
+"broadcastUserNoTgId" = "❌ O usuário não possui Telegram ID, broadcast não é possível."
+"broadcastEnterText" = "Digite o texto da mensagem para o usuário selecionado"
+"broadcastSentToUser" = "Mensagem enviada para o usuário: {{ .Email }}"
diff --git a/web/translation/translate.ru_RU.toml b/web/translation/translate.ru_RU.toml
index 838c5bc8..71dab90e 100644
--- a/web/translation/translate.ru_RU.toml
+++ b/web/translation/translate.ru_RU.toml
@@ -740,4 +740,13 @@
"chooseInbound" = "Выберите инбаунд"
"chooseSend" = "Выберите способ отправки уведомления"
"chooseUser" = "Выберите пользователя или отправьте его email"
-"enterText" = "Введите желаемый текст сообщения"
\ No newline at end of file
+"enterText" = "Введите желаемый текст сообщения для отправки всем пользователям"
+"inboundError" = "❌ Ошибка получения инбаундов"
+"clientError" = "❌ Ошибка получения пользователей"
+"broadcastMessageSent" = "Сообщение отправлено {{ .Count }} пользователям"
+"chooseBroadcastInbound" = "Выберите инбаунд для рассылки"
+"chooseBroadcastUser" = "Выберите пользователя для рассылки или введите email вручную"
+"broadcastUserNotFound" = "❌ Пользователь с таким email не найден в выбранном инбаунде."
+"broadcastUserNoTgId" = " ❌ У пользователя не указан Telegram ID, рассылка невозможна."
+"broadcastEnterText" = "Введите текст сообщения для выбранного пользователя"
+"broadcastSentToUser" = "Сообщение отправлено пользователю: {{ .Email }}"
\ No newline at end of file
diff --git a/web/translation/translate.tr_TR.toml b/web/translation/translate.tr_TR.toml
index 4b3cae68..fffa8c51 100644
--- a/web/translation/translate.tr_TR.toml
+++ b/web/translation/translate.tr_TR.toml
@@ -738,3 +738,14 @@
"askToAddUserId" = "Yapılandırmanız bulunamadı!\r\nLütfen yöneticinizden yapılandırmalarınıza Telegram ChatID'nizi eklemesini isteyin.\r\n\r\nKullanıcı ChatID'niz: {{ .TgUserID }}
"
"chooseClient" = "Gelen {{ .Inbound }} için bir Müşteri Seçin"
"chooseInbound" = "Bir Gelen Seçin"
+
+"enterText" = "Tüm kullanıcılara göndermek için istenen mesaj metnini girin"
+"inboundError" = "❌ Girişler alınırken hata oluştu"
+"clientError" = "❌ Kullanıcılar alınırken hata oluştu"
+"broadcastMessageSent" = "Mesaj {{ .Count }} kullanıcıya gönderildi"
+"chooseBroadcastInbound" = "Yayın için giriş seçin"
+"chooseBroadcastUser" = "Yayın için kullanıcı seçin veya e-postayı manuel girin"
+"broadcastUserNotFound" = "❌ Seçilen girişte bu e-postaya sahip kullanıcı bulunamadı."
+"broadcastUserNoTgId" = "❌ Kullanıcının Telegram ID'si yok, yayın yapılamaz."
+"broadcastEnterText" = "Seçilen kullanıcı için mesaj metnini girin"
+"broadcastSentToUser" = "Mesaj kullanıcıya gönderildi: {{ .Email }}"
diff --git a/web/translation/translate.uk_UA.toml b/web/translation/translate.uk_UA.toml
index 06a5a334..3e4933d6 100644
--- a/web/translation/translate.uk_UA.toml
+++ b/web/translation/translate.uk_UA.toml
@@ -91,7 +91,7 @@
"invalidFormData" = "Формат вхідних даних недійсний."
"emptyUsername" = "Потрібне ім'я користувача"
"emptyPassword" = "Потрібен пароль"
-"wrongUsernameOrPassword" = "Невірне ім’я користувача, пароль або код двофакторної аутентифікації."
+"wrongUsernameOrPassword" = "Невірне ім'я користувача, пароль або код двофакторної аутентифікації."
"successLogin" = "Ви успішно увійшли до свого облікового запису."
[pages.index]
@@ -297,11 +297,11 @@
"panelPort" = "Порт прослуховування"
"panelPortDesc" = "Номер порту для веб-панелі. (має бути невикористаний порт)"
"publicKeyPath" = "Шлях відкритого ключа"
-"publicKeyPathDesc" = "Шлях до файлу відкритого ключа для веб-панелі. (починається з ‘/‘)"
+"publicKeyPathDesc" = "Шлях до файлу відкритого ключа для веб-панелі. (починається з '//')"
"privateKeyPath" = "Шлях приватного ключа"
-"privateKeyPathDesc" = "Шлях до файлу приватного ключа для веб-панелі. (починається з ‘/‘)"
+"privateKeyPathDesc" = "Шлях до файлу приватного ключа для веб-панелі. (починається з '//')"
"panelUrlPath" = "Шлях URL"
-"panelUrlPathDesc" = "Шлях URL для веб-панелі. (починається з ‘/‘ і закінчується ‘/‘)"
+"panelUrlPathDesc" = "Шлях URL для веб-панелі. (починається з '//' і закінчується '//')"
"pageSize" = "Розмір сторінки"
"pageSizeDesc" = "Визначити розмір сторінки для вхідної таблиці. (0 = вимкнено)"
"remarkModel" = "Модель зауваження та роздільний символ"
@@ -349,11 +349,11 @@
"subPort" = "Слухати порт"
"subPortDesc" = "Номер порту для служби підписки. (має бути невикористаний порт)"
"subCertPath" = "Шлях відкритого ключа"
-"subCertPathDesc" = "Шлях до файлу відкритого ключа для служби підписки. (починається з ‘/‘)"
+"subCertPathDesc" = "Шлях до файлу відкритого ключа для служби підписки. (починається з '//')"
"subKeyPath" = "Шлях приватного ключа"
-"subKeyPathDesc" = "Шлях до файлу приватного ключа для служби підписки. (починається з ‘/‘)"
+"subKeyPathDesc" = "Шлях до файлу приватного ключа для служби підписки. (починається з '//')"
"subPath" = "Шлях URI"
-"subPathDesc" = "Шлях URI для служби підписки. (починається з ‘/‘ і закінчується ‘/‘)"
+"subPathDesc" = "Шлях URI для служби підписки. (починається з '//' і закінчується '//')"
"subDomain" = "Домен прослуховування"
"subDomainDesc" = "Ім'я домену для служби підписки. (залиште порожнім, щоб слухати всі домени та IP-адреси)"
"subUpdates" = "Інтервали оновлення"
@@ -377,7 +377,7 @@
"muxDesc" = "Передавати кілька незалежних потоків даних у межах встановленого потоку даних."
"muxSett" = "Налаштування Mux"
"direct" = "Пряме підключення"
-"directDesc" = "Безпосередньо встановлює з’єднання з доменами або діапазонами IP певної країни."
+"directDesc" = "Безпосередньо встановлює з'єднання з доменами або діапазонами IP певної країни."
"notifications" = "Сповіщення"
"certs" = "Сертифікати"
"externalTraffic" = "Зовнішній трафік"
@@ -738,3 +738,14 @@
"askToAddUserId" = "Вашу конфігурацію не знайдено!\r\nБудь ласка, попросіть свого адміністратора використовувати ваш ідентифікатор Telegram у вашій конфігурації.\r\n\r\nВаш ідентифікатор користувача: {{ .TgUserID }}
"
"chooseClient" = "Виберіть клієнта для Вхідного {{ .Inbound }}"
"chooseInbound" = "Виберіть Вхідний"
+
+"enterText" = "Введіть бажаний текст повідомлення для надсилання всім користувачам"
+"inboundError" = "❌ Помилка отримання вхідних"
+"clientError" = "❌ Помилка отримання користувачів"
+"broadcastMessageSent" = "Повідомлення надіслано {{ .Count }} користувачам"
+"chooseBroadcastInbound" = "Оберіть вхідний для розсилки"
+"chooseBroadcastUser" = "Оберіть користувача для розсилки або введіть email вручну"
+"broadcastUserNotFound" = "❌ Користувача з таким email не знайдено у вибраному вхідному."
+"broadcastUserNoTgId" = "❌ У користувача не вказано Telegram ID, розсилка неможлива."
+"broadcastEnterText" = "Введіть текст повідомлення для вибраного користувача"
+"broadcastSentToUser" = "Повідомлення надіслано користувачу: {{ .Email }}"
diff --git a/web/translation/translate.vi_VN.toml b/web/translation/translate.vi_VN.toml
index 21b104ef..d67461a3 100644
--- a/web/translation/translate.vi_VN.toml
+++ b/web/translation/translate.vi_VN.toml
@@ -738,3 +738,14 @@
"askToAddUserId" = "Cấu hình của bạn không được tìm thấy!\r\nVui lòng yêu cầu Quản trị viên sử dụng ID người dùng telegram của bạn trong cấu hình của bạn.\r\n\r\nID người dùng của bạn: {{ .TgUserID }}
"
"chooseClient" = "Chọn một Khách hàng cho Inbound {{ .Inbound }}"
"chooseInbound" = "Chọn một Inbound"
+
+"enterText" = "Nhập nội dung tin nhắn muốn gửi cho tất cả người dùng"
+"inboundError" = "❌ Lỗi khi lấy dữ liệu inbound"
+"clientError" = "❌ Lỗi khi lấy người dùng"
+"broadcastMessageSent" = "Tin nhắn đã được gửi đến {{ .Count }} người dùng"
+"chooseBroadcastInbound" = "Chọn inbound để gửi broadcast"
+"chooseBroadcastUser" = "Chọn người dùng để gửi broadcast hoặc nhập email thủ công"
+"broadcastUserNotFound" = "❌ Không tìm thấy người dùng với email này trong inbound đã chọn."
+"broadcastUserNoTgId" = "❌ Người dùng không có Telegram ID, không thể gửi broadcast."
+"broadcastEnterText" = "Nhập nội dung tin nhắn cho người dùng đã chọn"
+"broadcastSentToUser" = "Tin nhắn đã được gửi đến người dùng: {{ .Email }}"
diff --git a/web/translation/translate.zh_CN.toml b/web/translation/translate.zh_CN.toml
index 673be51b..dee52e8b 100644
--- a/web/translation/translate.zh_CN.toml
+++ b/web/translation/translate.zh_CN.toml
@@ -738,3 +738,14 @@
"askToAddUserId" = "未找到您的配置!\r\n请向管理员询问,在您的配置中使用您的 Telegram 用户 ChatID。\r\n\r\n您的用户 ChatID:{{ .TgUserID }}
"
"chooseClient" = "为入站 {{ .Inbound }} 选择一个客户"
"chooseInbound" = "选择一个入站"
+
+"enterText" = "请输入要发送给所有用户的消息文本"
+"inboundError" = "❌ 获取入站信息出错"
+"clientError" = "❌ 获取用户出错"
+"broadcastMessageSent" = "消息已发送给 {{ .Count }} 位用户"
+"chooseBroadcastInbound" = "选择用于广播的入站"
+"chooseBroadcastUser" = "选择用于广播的用户或手动输入邮箱"
+"broadcastUserNotFound" = "❌ 在所选入站中未找到该邮箱的用户。"
+"broadcastUserNoTgId" = "❌ 用户未设置 Telegram ID,无法广播。"
+"broadcastEnterText" = "请输入为所选用户发送的消息文本"
+"broadcastSentToUser" = "消息已发送给用户: {{ .Email }}"
diff --git a/web/translation/translate.zh_TW.toml b/web/translation/translate.zh_TW.toml
index 4c41b1f8..0cfcf13e 100644
--- a/web/translation/translate.zh_TW.toml
+++ b/web/translation/translate.zh_TW.toml
@@ -740,3 +740,14 @@
"askToAddUserId" = "未找到您的配置!\r\n請向管理員詢問,在您的配置中使用您的 Telegram 使用者 ChatID。\r\n\r\n您的使用者 ChatID:{{ .TgUserID }}
"
"chooseClient" = "為入站 {{ .Inbound }} 選擇一個客戶"
"chooseInbound" = "選擇一個入站"
+
+"enterText" = "請輸入要發送給所有用戶的訊息內容"
+"inboundError" = "❌ 取得入站資料時發生錯誤"
+"clientError" = "❌ 取得用戶時發生錯誤"
+"broadcastMessageSent" = "訊息已發送給 {{ .Count }} 位用戶"
+"chooseBroadcastInbound" = "選擇要廣播的入站"
+"chooseBroadcastUser" = "選擇要廣播的用戶或手動輸入電子郵件"
+"broadcastUserNotFound" = "❌ 在所選入站中找不到該電子郵件的用戶。"
+"broadcastUserNoTgId" = "❌ 用戶未設置 Telegram ID,無法廣播。"
+"broadcastEnterText" = "請輸入要發送給所選用戶的訊息內容"
+"broadcastSentToUser" = "訊息已發送給用戶: {{ .Email }}"