This commit is contained in:
rydve 2026-05-13 00:39:26 +03:00 committed by GitHub
commit 8ad9b73d35
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
16 changed files with 7956 additions and 8449 deletions

View file

@ -6,6 +6,7 @@ import (
"github.com/mhsanaei/3x-ui/v3/util/crypto"
"github.com/mhsanaei/3x-ui/v3/web/entity"
"github.com/mhsanaei/3x-ui/v3/web/locale"
"github.com/mhsanaei/3x-ui/v3/web/service"
"github.com/mhsanaei/3x-ui/v3/web/session"
@ -77,6 +78,9 @@ func (a *SettingController) updateSetting(c *gin.Context) {
return
}
err = a.settingService.UpdateAllSetting(allSetting)
if err == nil {
locale.UpdateBotLocalizer(allSetting.TgLang)
}
jsonMsg(c, I18nWeb(c, "pages.settings.toasts.modifySettings"), err)
}

View file

@ -111,11 +111,20 @@ func initTGBotLocalizer(settingService SettingService) error {
if err != nil {
return err
}
logger.Infof("Initializing TG Bot localizer with language: %s", botLang)
LocalizerBot = i18n.NewLocalizer(i18nBundle, botLang)
return nil
}
// UpdateBotLocalizer dynamically updates the bot localizer language.
func UpdateBotLocalizer(botLang string) {
if i18nBundle != nil {
logger.Infof("Updating TG Bot localizer with language: %s", botLang)
LocalizerBot = i18n.NewLocalizer(i18nBundle, botLang)
}
}
// LocalizerMiddleware returns a Gin middleware that sets up localization for web requests.
// It determines the user's language from cookies or Accept-Language header,
// creates a localizer instance, and stores it in the Gin context for use in handlers.
@ -161,7 +170,9 @@ func loadTranslationsFromDisk(bundle *i18n.Bundle) error {
if err != nil {
return err
}
_, err = bundle.ParseMessageFileBytes(data, path)
filename := d.Name()
logger.Infof("Parsing translation file from disk: %s", filename)
_, err = bundle.ParseMessageFileBytes(data, filename)
return err
})
}
@ -183,7 +194,9 @@ func parseTranslationFiles(i18nFS embed.FS, i18nBundle *i18n.Bundle) error {
return err
}
_, err = i18nBundle.ParseMessageFileBytes(data, path)
filename := d.Name()
logger.Infof("Parsing translation file from embed: %s (path: %s)", filename, path)
_, err = i18nBundle.ParseMessageFileBytes(data, filename)
return err
})
if err != nil {

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -873,6 +873,11 @@
"exhaustedMsg": "🚨 Exhausted {{ .Type }}:\r\n",
"exhaustedCount": "🚨 Exhausted {{ .Type }} count:\r\n",
"onlinesCount": "🌐 Online Clients: {{ .Count }}\r\n",
"cpu": "CPU: {{ .Usage }}%\r\n",
"mem": "RAM: {{ .Usage }}/{{ .Total }}\r\n",
"swap": "Swap: {{ .Usage }}/{{ .Total }}\r\n",
"disk": "Disk: {{ .Usage }}/{{ .Total }}\r\n",
"uptime": "Uptime: {{ .Time }}\r\n",
"disabled": "🛑 Disabled: {{ .Disabled }}\r\n",
"depleteSoon": "🔜 Deplete Soon: {{ .Deplete }}\r\n\r\n",
"backupTime": "🗄 Backup Time: {{ .Time }}\r\n",
@ -883,9 +888,13 @@
"received_password": "🔑📥 Password updated.",
"received_email": "📧📥 Email updated.",
"received_comment": "💬📥 Comment updated.",
"received_subid": "Sub ID updated successfully!",
"client_subid": "Sub ID:",
"client_flow": "Flow:",
"id_prompt": "🔑 Default ID: {{ .ClientId }}\n\nEnter your id.",
"pass_prompt": "🔑 Default Password: {{ .ClientPassword }}\n\nEnter your password.",
"email_prompt": "📧 Default Email: {{ .ClientEmail }}\n\nEnter your email.",
"subid_prompt": "Please enter new Sub ID:\nCurrent: {{.ClientSubId}}",
"comment_prompt": "💬 Default Comment: {{ .ClientComment }}\n\nEnter your Comment.",
"inbound_client_data_id": "🔄 Inbound: {{ .InboundRemark }}\n\n🔑 ID: {{ .ClientId }}\n📧 Email: {{ .ClientEmail }}\n📊 Traffic: {{ .ClientTraffic }}\n📅 Expire Date: {{ .ClientExp }}\n🌐 IP Limit: {{ .IpLimit }}\n💬 Comment: {{ .ClientComment }}\n\nYou can add the client to inbound now!",
"inbound_client_data_pass": "🔄 Inbound: {{ .InboundRemark }}\n\n🔑 Password: {{ .ClientPass }}\n📧 Email: {{ .ClientEmail }}\n📊 Traffic: {{ .ClientTraffic }}\n📅 Expire Date: {{ .ClientExp }}\n🌐 IP Limit: {{ .IpLimit }}\n💬 Comment: {{ .ClientComment }}\n\nYou can add the client to inbound now!",
@ -893,6 +902,7 @@
"error_add_client": "⚠️ Error:\n\n {{ .error }}",
"using_default_value": "Okay, I'll stick with the default value. 😊",
"incorrect_input": "Your input is not valid.\nThe phrases should be continuous without spaces.\nCorrect example: aaaaaa\nIncorrect example: aaa aaa 🚫",
"invalid_subid": "Invalid format.\nSub ID can only contain letters, numbers, hyphens (-), and underscores (_).\nSpaces and special characters are not allowed. 🚫",
"AreYouSure": "Are you sure? 🤔",
"SuccessResetTraffic": "📧 Email: {{ .ClientEmail }}\n🏁 Result: ✅ Success",
"FailedResetTraffic": "📧 Email: {{ .ClientEmail }}\n🏁 Result: ❌ Failed \n\n🛠 Error: [ {{ .ErrorMessage }} ]",
@ -939,6 +949,11 @@
"change_password": "⚙️🔑 Password",
"change_email": "⚙️📧 Email",
"change_comment": "⚙️💬 Comment",
"change_subid": "📝 Sub ID",
"change_flow": "🌊 Flow",
"flow_none": "None",
"qrCode": "QR Code",
"selectTGUser": "Select Telegram User",
"ResetAllTraffics": "Reset All Traffics",
"SortedTrafficUsageReport": "Sorted Traffic Usage Report"
},

File diff suppressed because it is too large Load diff

View file

@ -883,9 +883,11 @@
"received_password": "🔑📥 رمز عبور به‌روزرسانی شد.",
"received_email": "📧📥 ایمیل به‌روزرسانی شد.",
"received_comment": "💬📥 نظر به‌روزرسانی شد.",
"received_subid": "Sub ID با موفقیت تغییر کرد!",
"id_prompt": "🔑 شناسه پیش‌فرض: {{ .ClientId }}\n\nشناسه خود را وارد کنید.",
"pass_prompt": "🔑 رمز عبور پیش‌فرض: {{ .ClientPassword }}\n\nرمز عبور خود را وارد کنید.",
"email_prompt": "📧 ایمیل پیش‌فرض: {{ .ClientEmail }}\n\nایمیل خود را وارد کنید.",
"subid_prompt": "لطفاً Sub ID جدید را وارد کنید:\nفعلی: {{.ClientSubId}}",
"comment_prompt": "💬 نظر پیش‌فرض: {{ .ClientComment }}\n\nنظر خود را وارد کنید.",
"inbound_client_data_id": "🔄 ورودی: {{ .InboundRemark }}\n\n🔑 شناسه: {{ .ClientId }}\n📧 ایمیل: {{ .ClientEmail }}\n📊 ترافیک: {{ .ClientTraffic }}\n📅 تاریخ انقضا: {{ .ClientExp }}\n🌐 محدودیت IP: {{ .IpLimit }}\n💬 توضیح: {{ .ClientComment }}\n\nاکنون می‌تونی مشتری را به ورودی اضافه کنی!",
"inbound_client_data_pass": "🔄 ورودی: {{ .InboundRemark }}\n\n🔑 رمز عبور: {{ .ClientPass }}\n📧 ایمیل: {{ .ClientEmail }}\n📊 ترافیک: {{ .ClientTraffic }}\n📅 تاریخ انقضا: {{ .ClientExp }}\n🌐 محدودیت IP: {{ .IpLimit }}\n💬 توضیح: {{ .ClientComment }}\n\nاکنون می‌تونی مشتری را به ورودی اضافه کنی!",
@ -893,6 +895,9 @@
"error_add_client": "⚠️ خطا:\n\n {{ .error }}",
"using_default_value": "باشه، از مقدار پیش‌فرض استفاده می‌کنم. 😊",
"incorrect_input": "ورودی شما معتبر نیست.\nعبارتها باید بدون فاصله باشند.\nمثال صحیح: aaaaaa\nمثال نادرست: aaa aaa 🚫",
"invalid_subid": "فرمت نامعتبر است.\nشناسه Sub ID فقط می‌تواند شامل حروف، اعداد، خط تیره (-) و خط زیر (_) باشد.\nاستفاده از فاصله و کاراکترهای خاص مجاز نیست. 🚫",
"client_subid": "شناسه اشتراک (Sub ID):",
"client_flow": "جریان (Flow):",
"AreYouSure": "مطمئنی؟ 🤔",
"SuccessResetTraffic": "📧 ایمیل: {{ .ClientEmail }}\n🏁 نتیجه: ✅ موفقیت‌آمیز",
"FailedResetTraffic": "📧 ایمیل: {{ .ClientEmail }}\n🏁 نتیجه: ❌ ناموفق \n\n🛠 خطا: [ {{ .ErrorMessage }} ]",
@ -939,6 +944,9 @@
"change_password": "⚙️🔑 گذرواژه",
"change_email": "⚙️📧 ایمیل",
"change_comment": "⚙️💬 نظر",
"change_subid": "📝 Sub ID",
"change_flow": "🌊 Flow",
"flow_none": "هیچ",
"ResetAllTraffics": "بازنشانی همه ترافیک‌ها",
"SortedTrafficUsageReport": "گزارش استفاده از ترافیک مرتب‌شده"
},

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -873,6 +873,11 @@
"exhaustedMsg": "🚨 Исчерпаны {{ .Type }}:\r\n",
"exhaustedCount": "🚨 Количество исчерпанных {{ .Type }}:\r\n",
"onlinesCount": "🌐 Клиентов онлайн: {{ .Count }}\r\n",
"cpu": "ЦП: {{ .Usage }}%\r\n",
"mem": "ОЗУ: {{ .Usage }}/{{ .Total }}\r\n",
"swap": "Swap: {{ .Usage }}/{{ .Total }}\r\n",
"disk": "Диск: {{ .Usage }}/{{ .Total }}\r\n",
"uptime": "Время работы: {{ .Time }}\r\n",
"disabled": "🛑 Отключено: {{ .Disabled }}\r\n",
"depleteSoon": "🔜 Клиенты, у которых скоро исчерпание: {{ .Deplete }}\r\n\r\n",
"backupTime": "🗄 Время резервного копирования: {{ .Time }}\r\n",
@ -883,9 +888,13 @@
"received_password": "🔑📥 Пароль обновлён.",
"received_email": "📧📥 Email обновлен.",
"received_comment": "💬📥 Комментарий обновлён.",
"received_subid": "Sub ID успешно обновлен!",
"client_subid": "Sub ID:",
"client_flow": "Flow:",
"id_prompt": "🔑 Стандартный ID: {{ .ClientId }}\n\nВведите ваш ID.",
"pass_prompt": "🔑 Стандартный пароль: {{ .ClientPassword }}\n\nВведите ваш пароль.",
"email_prompt": "📧 Стандартный email: {{ .ClientEmail }}\n\nВведите ваш email.",
"subid_prompt": "Пожалуйста, введите новый Sub ID:\nТекущий: {{.ClientSubId}}",
"comment_prompt": "💬 Стандартный комментарий: {{ .ClientComment }}\n\nВведите ваш комментарий.",
"inbound_client_data_id": "🔄 Входящие подключения: {{ .InboundRemark }}\n\n🔑 ID: {{ .ClientId }}\n📧 Email: {{ .ClientEmail }}\n📊 Трафик: {{ .ClientTraffic }}\n📅 Срок действия: {{ .ClientExp }}\n💬 Комментарий: {{ .ClientComment }}\n\nТеперь вы можете добавить клиента в входящее подключение!",
"inbound_client_data_pass": "🔄 Входящие подключения: {{ .InboundRemark }}\n\n🔑 Пароль: {{ .ClientPass }}\n📧 Email: {{ .ClientEmail }}\n📊 Трафик: {{ .ClientTraffic }}\n📅 Срок действия: {{ .ClientExp }}\n💬 Комментарий: {{ .ClientComment }}\n\nТеперь вы можете добавить клиента в входящее подключение!",
@ -893,6 +902,7 @@
"error_add_client": "⚠️ Ошибка:\n\n {{ .error }}",
"using_default_value": "Используется значение по умолчанию👌",
"incorrect_input": "Ваш ввод недействителен.\nФразы должны быть непрерывными без пробелов.\nПравильный пример: aaaaaa\nНеправильный пример: aaa aaa 🚫",
"invalid_subid": "Некорректный формат.\nSub ID может содержать только буквы, цифры, дефис (-) и нижнее подчеркивание (_).\nПробелы и спецсимволы не допускаются. 🚫",
"AreYouSure": "Вы уверены? 🤔",
"SuccessResetTraffic": "📧 Почта: {{ .ClientEmail }}\n🏁 Результат: ✅ Успешно",
"FailedResetTraffic": "📧 Почта: {{ .ClientEmail }}\n🏁 Результат: ❌ Неудача \n\n🛠 Ошибка: [ {{ .ErrorMessage }} ]",
@ -939,6 +949,10 @@
"change_password": "⚙️🔑 Пароль",
"change_email": "⚙️📧 Email",
"change_comment": "⚙️💬 Комментарий",
"change_subid": "📝 Sub ID",
"change_flow": "🌊 Flow",
"flow_none": "Отсутствует",
"qrCode": "QR-код",
"ResetAllTraffics": "Сбросить весь трафик",
"SortedTrafficUsageReport": "Отсортированный отчет об использовании трафика"
},

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -883,9 +883,13 @@
"received_password": "🔑📥 Mật khẩu đã được cập nhật.",
"received_email": "📧📥 Email đã được cập nhật.",
"received_comment": "💬📥 Bình luận đã được cập nhật.",
"id_prompt": "🔑 ID mặc định: {{ .ClientId }}\n\nVui lòng nhập ID của bạn.",
"received_subid": "Sub ID đã được thay đổi thành công!",
"client_subid": "Sub ID:",
"client_flow": "Flow:",
"id_prompt": "🔑 ID mặc định: {{ .ClientId }}\n\nV Vui lòng nhập ID của bạn.",
"pass_prompt": "🔑 Mật khẩu mặc định: {{ .ClientPassword }}\n\nVui lòng nhập mật khẩu của bạn.",
"email_prompt": "📧 Email mặc định: {{ .ClientEmail }}\n\nVui lòng nhập email của bạn.",
"subid_prompt": "Vui lòng nhập Sub ID mới:\nHiện tại: {{.ClientSubId}}",
"comment_prompt": "💬 Bình luận mặc định: {{ .ClientComment }}\n\nVui lòng nhập bình luận của bạn.",
"inbound_client_data_id": "🔄 Kết nối vào: {{ .InboundRemark }}\n\n🔑 ID: {{ .ClientId }}\n📧 Email: {{ .ClientEmail }}\n📊 Dung lượng: {{ .ClientTraffic }}\n📅 Ngày hết hạn: {{ .ClientExp }}\n🌐 Giới hạn IP: {{ .IpLimit }}\n💬 Ghi chú: {{ .ClientComment }}\n\nBây giờ bạn có thể thêm khách hàng vào inbound!",
"inbound_client_data_pass": "🔄 Kết nối vào: {{ .InboundRemark }}\n\n🔑 Mật khẩu: {{ .ClientPass }}\n📧 Email: {{ .ClientEmail }}\n📊 Dung lượng: {{ .ClientTraffic }}\n📅 Ngày hết hạn: {{ .ClientExp }}\n🌐 Giới hạn IP: {{ .IpLimit }}\n💬 Ghi chú: {{ .ClientComment }}\n\nBây giờ bạn có thể thêm khách hàng vào inbound!",
@ -893,6 +897,7 @@
"error_add_client": "⚠️ Lỗi:\n\n {{ .error }}",
"using_default_value": "Được rồi, tôi sẽ sử dụng giá trị mặc định. 😊",
"incorrect_input": "Dữ liệu bạn nhập không hợp lệ.\nCác chuỗi phải liền mạch và không có dấu cách.\nVí dụ đúng: aaaaaa\nVí dụ sai: aaa aaa 🚫",
"invalid_subid": "Định dạng không hợp lệ.\nSub ID chỉ có thể chứa chữ cái, số, dấu gạch ngang (-) và dấu gạch dưới (_).\nKhông cho phép khoảng trắng và các ký tự đặc biệt. 🚫",
"AreYouSure": "Bạn có chắc không? 🤔",
"SuccessResetTraffic": "📧 Email: {{ .ClientEmail }}\n🏁 Kết quả: ✅ Thành công",
"FailedResetTraffic": "📧 Email: {{ .ClientEmail }}\n🏁 Kết quả: ❌ Thất bại \n\n🛠 Lỗi: [ {{ .ErrorMessage }} ]",
@ -939,6 +944,9 @@
"change_password": "⚙️🔑 Mật Khẩu",
"change_email": "⚙️📧 Email",
"change_comment": "⚙️💬 Bình Luận",
"change_subid": "📝 Sub ID",
"change_flow": "🌊 Flow",
"flow_none": "None",
"ResetAllTraffics": "Đặt lại tất cả lưu lượng",
"SortedTrafficUsageReport": "Báo cáo sử dụng lưu lượng đã sắp xếp"
},

View file

@ -883,9 +883,13 @@
"received_password": "🔑📥 密码已更新。",
"received_email": "📧📥 邮箱已更新。",
"received_comment": "💬📥 评论已更新。",
"received_subid": "Sub ID 修改成功!",
"client_subid": "Sub ID:",
"client_flow": "Flow:",
"id_prompt": "🔑 默认 ID: {{ .ClientId }}\n\n请输入您的 ID。",
"pass_prompt": "🔑 默认密码: {{ .ClientPassword }}\n\n请输入您的密码。",
"email_prompt": "📧 默认邮箱: {{ .ClientEmail }}\n\n请输入您的邮箱。",
"subid_prompt": "请输入新的 Sub ID:\n当前: {{.ClientSubId}}",
"comment_prompt": "💬 默认评论: {{ .ClientComment }}\n\n请输入您的评论。",
"inbound_client_data_id": "🔄 入站: {{ .InboundRemark }}\n\n🔑 ID: {{ .ClientId }}\n📧 邮箱: {{ .ClientEmail }}\n📊 流量: {{ .ClientTraffic }}\n📅 到期日期: {{ .ClientExp }}\n🌐 IP 限制: {{ .IpLimit }}\n💬 备注: {{ .ClientComment }}\n\n你现在可以将客户添加到入站了",
"inbound_client_data_pass": "🔄 入站: {{ .InboundRemark }}\n\n🔑 密码: {{ .ClientPass }}\n📧 邮箱: {{ .ClientEmail }}\n📊 流量: {{ .ClientTraffic }}\n📅 到期日期: {{ .ClientExp }}\n🌐 IP 限制: {{ .IpLimit }}\n💬 备注: {{ .ClientComment }}\n\n你现在可以将客户添加到入站了",
@ -893,6 +897,7 @@
"error_add_client": "⚠️ 错误:\n\n {{ .error }}",
"using_default_value": "好的,我会使用默认值。 😊",
"incorrect_input": "您的输入无效。\n短语应连续输入不能有空格。\n正确示例: aaaaaa\n错误示例: aaa aaa 🚫",
"invalid_subid": "格式无效。\nSub ID 只能包含字母、数字、连字符 (-) 和下划线 (_)。\n不允许使用空格和特殊字符。 🚫",
"AreYouSure": "你确定吗?🤔",
"SuccessResetTraffic": "📧 邮箱: {{ .ClientEmail }}\n🏁 结果: ✅ 成功",
"FailedResetTraffic": "📧 邮箱: {{ .ClientEmail }}\n🏁 结果: ❌ 失败 \n\n🛠 错误: [ {{ .ErrorMessage }} ]",
@ -939,6 +944,9 @@
"change_password": "⚙️🔑 密码",
"change_email": "⚙️📧 邮箱",
"change_comment": "⚙️💬 评论",
"change_subid": "📝 Sub ID",
"change_flow": "🌊 Flow",
"flow_none": "无",
"ResetAllTraffics": "重置所有流量",
"SortedTrafficUsageReport": "排序的流量使用报告"
},

File diff suppressed because it is too large Load diff