Explorar el Código

i18n(panel): translate Copy/Cancel buttons, Stream/Sniffing tabs, and All-Inbounds filenames

- TextModal: route the Copy button label and the post-copy toast
  through t('copy')/t('copied') instead of hardcoded English.
- PromptModal: route cancelText through t('cancel') and default okText
  through t('confirm') so the import-inbound prompt stops showing
  "Cancel" in non-English UI.
- InboundsPage: pass the All-Inbounds and All-Inbounds-Subs download
  filenames through t(...) so each locale can localize them.
- en-US.json: add pages.inbounds.exportAllLinksFileName and
  pages.inbounds.exportAllSubsFileName.
- All 12 non-English locales: translate streamTab and sniffingTab
  (previously left as literal English) and add the two new filename
  keys with appropriate translations.

All 13 locale files now have 1541 lines.
MHSanaei hace 5 horas
padre
commit
c5b5606bf5

+ 5 - 3
frontend/src/components/PromptModal.tsx

@@ -1,6 +1,7 @@
 import { useEffect, useRef, useState } from 'react';
 import { Input, Modal } from 'antd';
 import type { InputRef } from 'antd';
+import { useTranslation } from 'react-i18next';
 
 interface PromptModalProps {
   open: boolean;
@@ -17,12 +18,13 @@ export default function PromptModal({
   open,
   onClose,
   title,
-  okText = 'OK',
+  okText,
   type = 'input',
   initialValue = '',
   loading = false,
   onConfirm,
 }: PromptModalProps) {
+  const { t } = useTranslation();
   const [value, setValue] = useState('');
   const textareaRef = useRef<HTMLTextAreaElement | null>(null);
   const inputRef = useRef<InputRef | null>(null);
@@ -53,8 +55,8 @@ export default function PromptModal({
     <Modal
       open={open}
       title={title}
-      okText={okText}
-      cancelText="Cancel"
+      okText={okText ?? t('confirm')}
+      cancelText={t('cancel')}
       mask={{ closable: false }}
       confirmLoading={loading}
       onOk={() => onConfirm(value)}

+ 4 - 2
frontend/src/components/TextModal.tsx

@@ -1,5 +1,6 @@
 import { Button, Input, Modal, message } from 'antd';
 import { CopyOutlined, DownloadOutlined } from '@ant-design/icons';
+import { useTranslation } from 'react-i18next';
 
 import { ClipboardManager, FileManager } from '@/utils';
 
@@ -12,11 +13,12 @@ interface TextModalProps {
 }
 
 export default function TextModal({ open, onClose, title, content, fileName = '' }: TextModalProps) {
+  const { t } = useTranslation();
   const [messageApi, messageContextHolder] = message.useMessage();
   async function copy() {
     const ok = await ClipboardManager.copyText(content || '');
     if (ok) {
-      messageApi.success('Copied');
+      messageApi.success(t('copied'));
       onClose();
     }
   }
@@ -39,7 +41,7 @@ export default function TextModal({ open, onClose, title, content, fileName = ''
           {fileName && (
             <Button icon={<DownloadOutlined />} onClick={download}>{fileName}</Button>
           )}
-          <Button type="primary" icon={<CopyOutlined />} onClick={copy}>Copy</Button>
+          <Button type="primary" icon={<CopyOutlined />} onClick={copy}>{t('copy')}</Button>
         </>
       )}
     >

+ 2 - 2
frontend/src/pages/inbounds/InboundsPage.tsx

@@ -294,7 +294,7 @@ export default function InboundsPage() {
         fallbackHostname: window.location.hostname,
       }));
     }
-    openText({ title: t('pages.inbounds.exportAllLinksTitle'), content: out.join('\r\n'), fileName: 'All-Inbounds' });
+    openText({ title: t('pages.inbounds.exportAllLinksTitle'), content: out.join('\r\n'), fileName: t('pages.inbounds.exportAllLinksFileName') });
   }, [dbInbounds, hydrateInbound, checkFallback, remarkModel, hostOverrideFor, openText, t]);
 
   const exportAllSubs = useCallback(async () => {
@@ -311,7 +311,7 @@ export default function InboundsPage() {
         }
       }
     }
-    openText({ title: t('pages.inbounds.exportAllSubsTitle'), content: [...new Set(out)].join('\r\n'), fileName: 'All-Inbounds-Subs' });
+    openText({ title: t('pages.inbounds.exportAllSubsTitle'), content: [...new Set(out)].join('\r\n'), fileName: t('pages.inbounds.exportAllSubsFileName') });
   }, [dbInbounds, hydrateInbound, subSettings, openText, t]);
 
   const importInbound = useCallback(() => {

+ 4 - 2
web/translation/ar-EG.json

@@ -322,6 +322,8 @@
       "exportSubsTitle": "تصدير روابط الاشتراك",
       "exportAllLinksTitle": "تصدير كل روابط الإدخالات",
       "exportAllSubsTitle": "تصدير كل روابط الاشتراكات",
+      "exportAllLinksFileName": "جميع-الواردات",
+      "exportAllSubsFileName": "جميع-الواردات-Subs",
       "inboundJsonTitle": "JSON الوارد",
       "deleteClient": "حذف العميل",
       "deleteClientContent": "متأكد إنك عايز تحذف العميل؟",
@@ -368,9 +370,9 @@
       "IPLimitlogclear": "امسح السجل",
       "setDefaultCert": "استخدم شهادة البانل",
       "setDefaultCertEmpty": "لا توجد شهادة معدّة للوحة. عينّ واحدة من الإعدادات أولاً.",
-      "streamTab": "Stream",
+      "streamTab": "تدفق",
       "securityTab": "الأمان",
-      "sniffingTab": "Sniffing",
+      "sniffingTab": "تنصت",
       "sniffingMetadataOnly": "البيانات الوصفية فقط",
       "sniffingRouteOnly": "التوجيه فقط",
       "sniffingIpsExcluded": "IP المستثناة",

+ 2 - 0
web/translation/en-US.json

@@ -322,6 +322,8 @@
       "exportSubsTitle": "Export subscription links",
       "exportAllLinksTitle": "Export all inbound links",
       "exportAllSubsTitle": "Export all subscription links",
+      "exportAllLinksFileName": "All-Inbounds",
+      "exportAllSubsFileName": "All-Inbounds-Subs",
       "inboundJsonTitle": "Inbound JSON",
       "deleteClient": "Delete Client",
       "deleteClientContent": "Are you sure you want to delete this client?",

+ 4 - 2
web/translation/es-ES.json

@@ -322,6 +322,8 @@
       "exportSubsTitle": "Exportar enlaces de suscripción",
       "exportAllLinksTitle": "Exportar todos los enlaces de inbound",
       "exportAllSubsTitle": "Exportar todos los enlaces de suscripción",
+      "exportAllLinksFileName": "Todas-las-entradas",
+      "exportAllSubsFileName": "Todas-las-entradas-Subs",
       "inboundJsonTitle": "JSON de entrada",
       "deleteClient": "Eliminar cliente",
       "deleteClientContent": "¿Está seguro de que desea eliminar el cliente?",
@@ -368,9 +370,9 @@
       "IPLimitlogclear": "Limpiar el Registro",
       "setDefaultCert": "Establecer certificado desde el panel",
       "setDefaultCertEmpty": "No hay certificado configurado para el panel. Configura uno en Ajustes primero.",
-      "streamTab": "Stream",
+      "streamTab": "Transmisión",
       "securityTab": "Seguridad",
-      "sniffingTab": "Sniffing",
+      "sniffingTab": "Inspección",
       "sniffingMetadataOnly": "Solo metadatos",
       "sniffingRouteOnly": "Solo enrutamiento",
       "sniffingIpsExcluded": "IPs excluidas",

+ 4 - 2
web/translation/fa-IR.json

@@ -322,6 +322,8 @@
       "exportSubsTitle": "خروجی لینک‌های ساب",
       "exportAllLinksTitle": "خروجی لینک‌های همه اینباندها",
       "exportAllSubsTitle": "خروجی لینک‌های ساب همه اینباندها",
+      "exportAllLinksFileName": "همه-ورودی‌ها",
+      "exportAllSubsFileName": "همه-ورودی‌ها-Subs",
       "inboundJsonTitle": "JSON ورودی",
       "deleteClient": "حذف کاربر",
       "deleteClientContent": "آیا مطمئن به حذف کاربر هستید؟",
@@ -368,9 +370,9 @@
       "IPLimitlogclear": "پاک کردن گزارش‌ها",
       "setDefaultCert": "استفاده از گواهی پنل",
       "setDefaultCertEmpty": "هیچ گواهی‌ای برای پنل پیکربندی نشده. ابتدا از تنظیمات یکی تعیین کنید.",
-      "streamTab": "Stream",
+      "streamTab": "انتقال",
       "securityTab": "امنیت",
-      "sniffingTab": "Sniffing",
+      "sniffingTab": "شنود",
       "sniffingMetadataOnly": "فقط متادیتا",
       "sniffingRouteOnly": "فقط مسیریابی",
       "sniffingIpsExcluded": "IPهای مستثنا",

+ 3 - 1
web/translation/id-ID.json

@@ -322,6 +322,8 @@
       "exportSubsTitle": "Ekspor tautan langganan",
       "exportAllLinksTitle": "Ekspor semua tautan inbound",
       "exportAllSubsTitle": "Ekspor semua tautan langganan",
+      "exportAllLinksFileName": "Semua-Inbound",
+      "exportAllSubsFileName": "Semua-Inbound-Subs",
       "inboundJsonTitle": "JSON inbound",
       "deleteClient": "Hapus Klien",
       "deleteClientContent": "Apakah Anda yakin ingin menghapus klien?",
@@ -368,7 +370,7 @@
       "IPLimitlogclear": "Hapus Log",
       "setDefaultCert": "Atur Sertifikat dari Panel",
       "setDefaultCertEmpty": "Tidak ada sertifikat yang dikonfigurasi untuk panel. Atur dulu di Pengaturan.",
-      "streamTab": "Stream",
+      "streamTab": "Aliran",
       "securityTab": "Keamanan",
       "sniffingTab": "Sniffing",
       "sniffingMetadataOnly": "Hanya metadata",

+ 4 - 2
web/translation/ja-JP.json

@@ -322,6 +322,8 @@
       "exportSubsTitle": "サブスクリプションリンクのエクスポート",
       "exportAllLinksTitle": "全インバウンドリンクのエクスポート",
       "exportAllSubsTitle": "全サブスクリプションリンクのエクスポート",
+      "exportAllLinksFileName": "全インバウンド",
+      "exportAllSubsFileName": "全インバウンド-Subs",
       "inboundJsonTitle": "インバウンド JSON",
       "deleteClient": "クライアント削除",
       "deleteClientContent": "クライアントを削除してもよろしいですか?",
@@ -368,9 +370,9 @@
       "IPLimitlogclear": "ログをクリア",
       "setDefaultCert": "パネル設定から証明書を設定",
       "setDefaultCertEmpty": "パネル用の証明書が設定されていません。先に設定から指定してください。",
-      "streamTab": "Stream",
+      "streamTab": "ストリーム",
       "securityTab": "セキュリティ",
-      "sniffingTab": "Sniffing",
+      "sniffingTab": "スニッフィング",
       "sniffingMetadataOnly": "メタデータのみ",
       "sniffingRouteOnly": "ルーティングのみ",
       "sniffingIpsExcluded": "除外する IP",

+ 4 - 2
web/translation/pt-BR.json

@@ -322,6 +322,8 @@
       "exportSubsTitle": "Exportar links de assinatura",
       "exportAllLinksTitle": "Exportar todos os links de inbound",
       "exportAllSubsTitle": "Exportar todos os links de assinatura",
+      "exportAllLinksFileName": "Todas-as-entradas",
+      "exportAllSubsFileName": "Todas-as-entradas-Subs",
       "inboundJsonTitle": "JSON da entrada",
       "deleteClient": "Excluir Cliente",
       "deleteClientContent": "Tem certeza de que deseja excluir o cliente?",
@@ -368,9 +370,9 @@
       "IPLimitlogclear": "Limpar o Log",
       "setDefaultCert": "Definir Certificado pelo Painel",
       "setDefaultCertEmpty": "Nenhum certificado configurado para o painel. Configure um em Configurações primeiro.",
-      "streamTab": "Stream",
+      "streamTab": "Transmissão",
       "securityTab": "Segurança",
-      "sniffingTab": "Sniffing",
+      "sniffingTab": "Inspeção",
       "sniffingMetadataOnly": "Apenas metadados",
       "sniffingRouteOnly": "Apenas roteamento",
       "sniffingIpsExcluded": "IPs excluídos",

+ 4 - 2
web/translation/ru-RU.json

@@ -322,6 +322,8 @@
       "exportSubsTitle": "Экспортировать ссылки подписки",
       "exportAllLinksTitle": "Экспортировать все ссылки подключений",
       "exportAllSubsTitle": "Экспортировать все ссылки подписок",
+      "exportAllLinksFileName": "Все-входящие",
+      "exportAllSubsFileName": "Все-входящие-Subs",
       "inboundJsonTitle": "JSON входящего",
       "deleteClient": "Удалить клиента",
       "deleteClientContent": "Вы уверены, что хотите удалить клиента?",
@@ -368,9 +370,9 @@
       "IPLimitlogclear": "Очистить лог",
       "setDefaultCert": "Установить сертификат панели",
       "setDefaultCertEmpty": "Для панели не настроен сертификат. Сначала установите его в Настройках.",
-      "streamTab": "Stream",
+      "streamTab": "Поток",
       "securityTab": "Безопасность",
-      "sniffingTab": "Sniffing",
+      "sniffingTab": "Сниффинг",
       "sniffingMetadataOnly": "Только метаданные",
       "sniffingRouteOnly": "Только маршрутизация",
       "sniffingIpsExcluded": "Исключённые IP",

+ 4 - 2
web/translation/tr-TR.json

@@ -322,6 +322,8 @@
       "exportSubsTitle": "Abonelik bağlantılarını dışa aktar",
       "exportAllLinksTitle": "Tüm inbound bağlantılarını dışa aktar",
       "exportAllSubsTitle": "Tüm abonelik bağlantılarını dışa aktar",
+      "exportAllLinksFileName": "Tum-Gelenler",
+      "exportAllSubsFileName": "Tum-Gelenler-Subs",
       "inboundJsonTitle": "Gelen JSON",
       "deleteClient": "Müşteriyi Sil",
       "deleteClientContent": "Müşteriyi silmek istediğinizden emin misiniz?",
@@ -368,9 +370,9 @@
       "IPLimitlogclear": "Günlüğü Temizle",
       "setDefaultCert": "Panelden Sertifikayı Ayarla",
       "setDefaultCertEmpty": "Panel için sertifika yapılandırılmamış. Önce Ayarlar'dan ayarlayın.",
-      "streamTab": "Stream",
+      "streamTab": "Akış",
       "securityTab": "Güvenlik",
-      "sniffingTab": "Sniffing",
+      "sniffingTab": "Dinleme",
       "sniffingMetadataOnly": "Yalnızca üst veri",
       "sniffingRouteOnly": "Yalnızca yönlendirme",
       "sniffingIpsExcluded": "Hariç tutulan IP'ler",

+ 4 - 2
web/translation/uk-UA.json

@@ -322,6 +322,8 @@
       "exportSubsTitle": "Експортувати посилання підписок",
       "exportAllLinksTitle": "Експортувати всі посилання вхідних",
       "exportAllSubsTitle": "Експортувати всі посилання підписок",
+      "exportAllLinksFileName": "Усі-вхідні",
+      "exportAllSubsFileName": "Усі-вхідні-Subs",
       "inboundJsonTitle": "JSON вхідного",
       "deleteClient": "Видалити клієнта",
       "deleteClientContent": "Ви впевнені, що хочете видалити клієнт?",
@@ -368,9 +370,9 @@
       "IPLimitlogclear": "Очистити журнал",
       "setDefaultCert": "Установити сертифікат з панелі",
       "setDefaultCertEmpty": "Для панелі не налаштовано сертифікат. Спочатку встановіть його в Налаштуваннях.",
-      "streamTab": "Stream",
+      "streamTab": "Потік",
       "securityTab": "Безпека",
-      "sniffingTab": "Sniffing",
+      "sniffingTab": "Сніфінг",
       "sniffingMetadataOnly": "Лише метадані",
       "sniffingRouteOnly": "Лише маршрутизація",
       "sniffingIpsExcluded": "Виключені IP",

+ 4 - 2
web/translation/vi-VN.json

@@ -322,6 +322,8 @@
       "exportSubsTitle": "Xuất liên kết đăng ký",
       "exportAllLinksTitle": "Xuất tất cả liên kết inbound",
       "exportAllSubsTitle": "Xuất tất cả liên kết đăng ký",
+      "exportAllLinksFileName": "Tat-ca-Inbound",
+      "exportAllSubsFileName": "Tat-ca-Inbound-Subs",
       "inboundJsonTitle": "JSON inbound",
       "deleteClient": "Xóa người dùng",
       "deleteClientContent": "Bạn có chắc chắn muốn xóa người dùng không?",
@@ -368,9 +370,9 @@
       "IPLimitlogclear": "Xóa Lịch sử",
       "setDefaultCert": "Đặt chứng chỉ từ bảng điều khiển",
       "setDefaultCertEmpty": "Không có chứng chỉ nào được cấu hình cho bảng điều khiển. Hãy đặt một chứng chỉ trong Cài đặt trước.",
-      "streamTab": "Stream",
+      "streamTab": "Luồng",
       "securityTab": "Bảo mật",
-      "sniffingTab": "Sniffing",
+      "sniffingTab": "Dò gói",
       "sniffingMetadataOnly": "Chỉ siêu dữ liệu",
       "sniffingRouteOnly": "Chỉ định tuyến",
       "sniffingIpsExcluded": "IP bị loại trừ",

+ 4 - 2
web/translation/zh-CN.json

@@ -322,6 +322,8 @@
       "exportSubsTitle": "导出订阅链接",
       "exportAllLinksTitle": "导出所有入站链接",
       "exportAllSubsTitle": "导出所有订阅链接",
+      "exportAllLinksFileName": "所有入站",
+      "exportAllSubsFileName": "所有入站-Subs",
       "inboundJsonTitle": "入站 JSON",
       "deleteClient": "删除客户端",
       "deleteClientContent": "确定要删除客户端吗?",
@@ -368,9 +370,9 @@
       "IPLimitlogclear": "清除日志",
       "setDefaultCert": "从面板设置证书",
       "setDefaultCertEmpty": "面板尚未配置证书。请先在“设置”中设置。",
-      "streamTab": "Stream",
+      "streamTab": "传输",
       "securityTab": "安全",
-      "sniffingTab": "Sniffing",
+      "sniffingTab": "嗅探",
       "sniffingMetadataOnly": "仅元数据",
       "sniffingRouteOnly": "仅路由",
       "sniffingIpsExcluded": "排除的 IP",

+ 4 - 2
web/translation/zh-TW.json

@@ -322,6 +322,8 @@
       "exportSubsTitle": "匯出訂閱連結",
       "exportAllLinksTitle": "匯出所有入站連結",
       "exportAllSubsTitle": "匯出所有訂閱連結",
+      "exportAllLinksFileName": "所有入站",
+      "exportAllSubsFileName": "所有入站-Subs",
       "inboundJsonTitle": "入站 JSON",
       "deleteClient": "刪除客戶端",
       "deleteClientContent": "確定要刪除客戶端嗎?",
@@ -368,9 +370,9 @@
       "IPLimitlogclear": "清除日誌",
       "setDefaultCert": "從面板設定證書",
       "setDefaultCertEmpty": "面板尚未設定憑證。請先在「設定」中設定。",
-      "streamTab": "Stream",
+      "streamTab": "傳輸",
       "securityTab": "安全",
-      "sniffingTab": "Sniffing",
+      "sniffingTab": "嗅探",
       "sniffingMetadataOnly": "僅中繼資料",
       "sniffingRouteOnly": "僅路由",
       "sniffingIpsExcluded": "排除的 IP",