From 3b93d7421a7d5c3c85f1dbe48c38a998936db3be Mon Sep 17 00:00:00 2001 From: sim Date: Thu, 10 Sep 2026 18:17:36 +0800 Subject: [PATCH] =?UTF-8?q?feat(models):=202.0=20=E6=A8=A1=E5=9E=8B?= =?UTF-8?q?=E8=AE=BE=E7=BD=AE=E9=A1=B5=E4=B8=8E=E4=BD=BF=E7=94=A8=E9=A1=B5?= =?UTF-8?q?=E2=80=94=E2=80=94=E7=9B=AE=E5=BD=95=E5=85=83=E6=95=B0=E6=8D=AE?= =?UTF-8?q?=E3=80=81=E4=BD=BF=E7=94=A8=E4=B8=AD=E6=A8=A1=E5=9E=8B=E9=80=89?= =?UTF-8?q?=E6=8B=A9=E4=B8=8E=E6=AE=8B=E7=95=99=E6=B8=85=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 模型设置页:新增 settings/models/LocalModelsSection 替换旧 LocalModelSection, 管理看板条目接入 Core 目录元数据快照(displayName / languages / sizeBytes), 基础信息展示不再依赖实时访问 HuggingFace;详情面板新增「清理未完成下载」 (local_asr_cleanup_incomplete,仅在有 staging 残留时出现)。 模型使用页:渠道编辑器本地引擎分支内嵌 LocalModelPicker——直接切换使用中的 模型(qwen/whisper 切换后预载引擎;sherpa/foundry 走各自 set 接口),显示引擎 可用性与残留清理入口;通过 ServicesTab 提供的 LocalModelsNavContext 一键跳到 「服务 → 本地模型」管理页(复用此前闲置的 localAsrManage 文案键)。 八语文案补齐(activeModelLabel / partialDownloads* / cleanupIncomplete / languagesLabel / partialBytesLabel 等 7 键)。tsc 0 错误,前端全套通过。 --- openless-all/app/src/i18n/de.ts | 9 + openless-all/app/src/i18n/en.ts | 36 ++- openless-all/app/src/i18n/es.ts | 9 + openless-all/app/src/i18n/fr.ts | 9 + openless-all/app/src/i18n/ja.ts | 38 +++- openless-all/app/src/i18n/ko.ts | 38 +++- openless-all/app/src/i18n/zh-CN.ts | 28 ++- openless-all/app/src/i18n/zh-TW.ts | 28 ++- .../app/src/pages/LocalAsr/components.tsx | 43 +++- openless-all/app/src/pages/LocalAsr/index.tsx | 36 +++ .../src/pages/settings/ProvidersSection.tsx | 12 +- .../settings/models/LocalModelPicker.tsx | 213 ++++++++++++++++++ .../LocalModelsSection.tsx} | 30 +-- .../src/pages/settings/models/modelsNav.ts | 12 + openless-all/app/src/pages/settings/tabs.tsx | 26 ++- 15 files changed, 485 insertions(+), 82 deletions(-) create mode 100644 openless-all/app/src/pages/settings/models/LocalModelPicker.tsx rename openless-all/app/src/pages/settings/{LocalModelSection.tsx => models/LocalModelsSection.tsx} (61%) create mode 100644 openless-all/app/src/pages/settings/models/modelsNav.ts diff --git a/openless-all/app/src/i18n/de.ts b/openless-all/app/src/i18n/de.ts index 9c159bf1..a47dca7c 100644 --- a/openless-all/app/src/i18n/de.ts +++ b/openless-all/app/src/i18n/de.ts @@ -2221,6 +2221,15 @@ export const de: typeof zhCN = { downloading: 'Wird heruntergeladen', startDownload: 'Download starten', downloadNewModel: 'Neues Modell herunterladen', + activeModelLabel: 'Aktives Modell', + pickerNoModelDownloaded: + 'Noch keine Modelle heruntergeladen — lade sie zuerst auf der Seite „Lokale Modelle“.', + partialDownloadsLabel: 'Unvollständige Downloads', + partialDownloadsDesc: + 'Abgebrochene Downloads haben temporäre Dateien hinterlassen; bereinige sie ohne die installierten Modelle zu beeinflussen.', + cleanupIncomplete: 'Unvollständigen Download bereinigen', + languagesLabel: 'Sprachen', + partialBytesLabel: 'Restdateien', downloadDialogTitle: 'Modell herunterladen', downloadDialogAlreadyHave: 'Die Modelldateien sind heruntergeladen. Kehre zur Modellseite zurück, um es zu laden und zu testen, oder wähle seinen Anbieter unter „ASR-Transkription“.', diff --git a/openless-all/app/src/i18n/en.ts b/openless-all/app/src/i18n/en.ts index cd366b35..6dda75f8 100644 --- a/openless-all/app/src/i18n/en.ts +++ b/openless-all/app/src/i18n/en.ts @@ -1748,17 +1748,24 @@ export const en: typeof zhCN = { regeneratePin: 'Regenerate', portInUse: 'Port {{port}} is in use, please change it', startError: 'Failed to start the remote input service: {{reason}}', - securityHint: 'Reachable only on the same LAN and requires the pairing code; turn it off when not in use.', - certHint: "Verify the root certificate fingerprint before trusting it on first use. Older versions require one-time setup; subsequent restarts and IP changes preserve trust.", + securityHint: + 'Reachable only on the same LAN and requires the pairing code; turn it off when not in use.', + certHint: + 'Verify the root certificate fingerprint before trusting it on first use. Older versions require one-time setup; subsequent restarts and IP changes preserve trust.', certFingerprintLabel: "This computer's root CA SHA-256", - certFingerprintCopy: "Copy full fingerprint", - certFingerprintCopied: "Fingerprint copied", - certFingerprintUnavailable: "The full fingerprint is unavailable. Do not install or trust a downloaded certificate.", - certVerifyHint: "Find SHA-256 in the phone's system certificate details and compare all 64 characters with this value (ignore spaces and colons) before enabling full trust. A web page, profile name or identifier cannot prove identity. If the fingerprint differs or cannot be viewed in full, stop and remove the downloaded or installed profile.", - certProfileHint: "Expect exactly one root certificate. Do not install a profile containing additional certificates, VPN or device management settings.", - certTrustWarning: "The initial certificate download cannot verify the computer's identity; a malicious device on the LAN could replace the root certificate in a man-in-the-middle attack. Install it only on a trusted home or private network, never on a public or shared network. The root CA can issue certificates and its private key stays on this computer; remove it from your phone when no longer needed.", - certSetupLink: "Copy iPhone certificate link", - waitingStart: 'The service is not running yet. Turn the switch off, then on again. Do not restart the app.', + certFingerprintCopy: 'Copy full fingerprint', + certFingerprintCopied: 'Fingerprint copied', + certFingerprintUnavailable: + 'The full fingerprint is unavailable. Do not install or trust a downloaded certificate.', + certVerifyHint: + "Find SHA-256 in the phone's system certificate details and compare all 64 characters with this value (ignore spaces and colons) before enabling full trust. A web page, profile name or identifier cannot prove identity. If the fingerprint differs or cannot be viewed in full, stop and remove the downloaded or installed profile.", + certProfileHint: + 'Expect exactly one root certificate. Do not install a profile containing additional certificates, VPN or device management settings.', + certTrustWarning: + "The initial certificate download cannot verify the computer's identity; a malicious device on the LAN could replace the root certificate in a man-in-the-middle attack. Install it only on a trusted home or private network, never on a public or shared network. The root CA can issue certificates and its private key stays on this computer; remove it from your phone when no longer needed.", + certSetupLink: 'Copy iPhone certificate link', + waitingStart: + 'The service is not running yet. Turn the switch off, then on again. Do not restart the app.', starting: 'Starting the remote input service…', urlsStale: 'These addresses come from the previous run and may be out of date.', }, @@ -2146,6 +2153,15 @@ export const en: typeof zhCN = { downloading: 'Downloading', startDownload: 'Start download', downloadNewModel: 'Download new model', + activeModelLabel: 'Model in use', + pickerNoModelDownloaded: + 'No downloaded models yet — download one on the Local models page first.', + partialDownloadsLabel: 'Incomplete downloads', + partialDownloadsDesc: + 'Interrupted downloads left staging files behind; clean them up without affecting installed models.', + cleanupIncomplete: 'Clean up incomplete download', + languagesLabel: 'Languages', + partialBytesLabel: 'Leftover files', downloadDialogTitle: 'Download Model', downloadDialogAlreadyHave: 'The model files are downloaded. Return to the model page to load and test, or choose its provider in ASR transcription.', diff --git a/openless-all/app/src/i18n/es.ts b/openless-all/app/src/i18n/es.ts index f719eec4..75caf90e 100644 --- a/openless-all/app/src/i18n/es.ts +++ b/openless-all/app/src/i18n/es.ts @@ -2202,6 +2202,15 @@ export const es: typeof zhCN = { downloading: 'Descargando', startDownload: 'Iniciar descarga', downloadNewModel: 'Descargar nuevo modelo', + activeModelLabel: 'Modelo en uso', + pickerNoModelDownloaded: + 'Aún no hay modelos descargados; descarga primero uno en la página de modelos locales.', + partialDownloadsLabel: 'Descargas incompletas', + partialDownloadsDesc: + 'Las descargas interrumpidas dejaron archivos temporales; límpialos sin afectar a los modelos instalados.', + cleanupIncomplete: 'Limpiar descarga incompleta', + languagesLabel: 'Idiomas', + partialBytesLabel: 'Archivos residuales', downloadDialogTitle: 'Descargar modelo', downloadDialogAlreadyHave: 'Los archivos del modelo ya están descargados. Vuelve a su página para cargarlo y probarlo, o elige su proveedor en Transcripción ASR.', diff --git a/openless-all/app/src/i18n/fr.ts b/openless-all/app/src/i18n/fr.ts index 8e13d997..474540dc 100644 --- a/openless-all/app/src/i18n/fr.ts +++ b/openless-all/app/src/i18n/fr.ts @@ -2231,6 +2231,15 @@ export const fr: typeof zhCN = { downloading: 'Téléchargement', startDownload: 'Démarrer le téléchargement', downloadNewModel: 'Télécharger un nouveau modèle', + activeModelLabel: 'Modèle utilisé', + pickerNoModelDownloaded: + 'Aucun modèle téléchargé pour l’instant — commencez par la page des modèles locaux.', + partialDownloadsLabel: 'Téléchargements incomplets', + partialDownloadsDesc: + 'Des téléchargements interrompus ont laissé des fichiers temporaires ; nettoyez-les sans toucher aux modèles installés.', + cleanupIncomplete: 'Nettoyer le téléchargement incomplet', + languagesLabel: 'Langues', + partialBytesLabel: 'Fichiers restants', downloadDialogTitle: 'Télécharger un modèle', downloadDialogAlreadyHave: 'Les fichiers du modèle sont téléchargés. Revenez à sa page pour le charger et le tester, ou choisissez son fournisseur dans Transcription ASR.', diff --git a/openless-all/app/src/i18n/ja.ts b/openless-all/app/src/i18n/ja.ts index 2382eed9..6294464c 100644 --- a/openless-all/app/src/i18n/ja.ts +++ b/openless-all/app/src/i18n/ja.ts @@ -1717,17 +1717,24 @@ export const ja: typeof zhCN = { regeneratePin: '再生成', portInUse: 'ポート {{port}} は使用中です。変更してください', startError: 'リモート入力サービスの起動に失敗しました:{{reason}}', - securityHint: '同一 LAN からのみアクセス可能で、ペアリングコードの入力が必要です。使わないときはオフにすることを推奨します。', - certHint: "初回接続ではルート証明書の指紋を確認してから信頼してください。旧バージョンからは一度設定が必要ですが、その後は再起動や IP 変更でも信頼が保持されます。", - certFingerprintLabel: "このコンピューターのルート CA SHA-256", - certFingerprintCopy: "指紋全体をコピー", - certFingerprintCopied: "指紋をコピーしました", - certFingerprintUnavailable: "完全な指紋を取得できません。ダウンロードした証明書をインストールしたり信頼したりしないでください。", - certVerifyHint: "スマートフォンのシステム証明書詳細にある SHA-256 の全 64 文字を、空白とコロンを除いてこの値と照合し、完全に信頼する前に確認してください。Web ページ、プロファイル名や識別子は身元の証明にはなりません。一致しない場合や全体を表示できない場合は中止し、ダウンロード済みまたはインストール済みのプロファイルを削除してください。", - certProfileHint: "プロファイルにはルート証明書が 1 枚だけ含まれるはずです。追加の証明書、VPN、デバイス管理の設定がある場合はインストールしないでください。", - certTrustWarning: "初回の証明書ダウンロードではコンピューターの身元を確認できず、LAN 上の悪意あるデバイスが中間者攻撃でルート証明書を置き換える可能性があります。信頼できる家庭内またはプライベートネットワークでのみインストールし、公共または共有ネットワークでは操作しないでください。ルート CA は証明書を発行でき、秘密鍵はこのコンピューターに保存されます。不要になったらスマートフォンから削除してください。", - certSetupLink: "iPhone 証明書リンクをコピー", - waitingStart: 'サービスはまだ起動していません。スイッチを一度オフにしてからオンにしてください。アプリを再起動しないでください。', + securityHint: + '同一 LAN からのみアクセス可能で、ペアリングコードの入力が必要です。使わないときはオフにすることを推奨します。', + certHint: + '初回接続ではルート証明書の指紋を確認してから信頼してください。旧バージョンからは一度設定が必要ですが、その後は再起動や IP 変更でも信頼が保持されます。', + certFingerprintLabel: 'このコンピューターのルート CA SHA-256', + certFingerprintCopy: '指紋全体をコピー', + certFingerprintCopied: '指紋をコピーしました', + certFingerprintUnavailable: + '完全な指紋を取得できません。ダウンロードした証明書をインストールしたり信頼したりしないでください。', + certVerifyHint: + 'スマートフォンのシステム証明書詳細にある SHA-256 の全 64 文字を、空白とコロンを除いてこの値と照合し、完全に信頼する前に確認してください。Web ページ、プロファイル名や識別子は身元の証明にはなりません。一致しない場合や全体を表示できない場合は中止し、ダウンロード済みまたはインストール済みのプロファイルを削除してください。', + certProfileHint: + 'プロファイルにはルート証明書が 1 枚だけ含まれるはずです。追加の証明書、VPN、デバイス管理の設定がある場合はインストールしないでください。', + certTrustWarning: + '初回の証明書ダウンロードではコンピューターの身元を確認できず、LAN 上の悪意あるデバイスが中間者攻撃でルート証明書を置き換える可能性があります。信頼できる家庭内またはプライベートネットワークでのみインストールし、公共または共有ネットワークでは操作しないでください。ルート CA は証明書を発行でき、秘密鍵はこのコンピューターに保存されます。不要になったらスマートフォンから削除してください。', + certSetupLink: 'iPhone 証明書リンクをコピー', + waitingStart: + 'サービスはまだ起動していません。スイッチを一度オフにしてからオンにしてください。アプリを再起動しないでください。', starting: 'リモート入力サービスを起動しています…', urlsStale: 'これらのアドレスは前回の起動時のもので、古くなっている可能性があります。', }, @@ -2115,6 +2122,15 @@ export const ja: typeof zhCN = { downloading: 'ダウンロード中', startDownload: 'ダウンロード開始', downloadNewModel: '新しいモデルをダウンロード', + activeModelLabel: '使用中のモデル', + pickerNoModelDownloaded: + 'ダウンロード済みのモデルがありません。先にローカルモデルページで取得してください。', + partialDownloadsLabel: '未完了のダウンロード', + partialDownloadsDesc: + '中断されたダウンロードの一時ファイルが残っています。インストール済みモデルに影響せず一括削除できます。', + cleanupIncomplete: '未完了ダウンロードを削除', + languagesLabel: '言語', + partialBytesLabel: '残存ファイル', downloadDialogTitle: 'モデルをダウンロード', downloadDialogAlreadyHave: 'モデルファイルはダウンロード済みです。モデルページで読み込みとテストを行うか、「ASR 音声文字起こし」で対応するプロバイダーを選択してください。', diff --git a/openless-all/app/src/i18n/ko.ts b/openless-all/app/src/i18n/ko.ts index 0488e61a..e5cd929d 100644 --- a/openless-all/app/src/i18n/ko.ts +++ b/openless-all/app/src/i18n/ko.ts @@ -1705,17 +1705,24 @@ export const ko: typeof zhCN = { regeneratePin: '재생성', portInUse: '포트 {{port}}이(가) 사용 중입니다. 변경하세요', startError: '원격 입력 서비스 시작에 실패했습니다: {{reason}}', - securityHint: '같은 LAN에서만 접속 가능하며 페어링 코드 입력이 필요합니다. 사용하지 않을 때는 끄는 것을 권장합니다.', - certHint: "처음 연결할 때 루트 인증서 지문을 확인한 후 신뢰하세요. 이전 버전에서는 한 번 설정해야 하며, 이후 재시작과 IP 변경 시 신뢰가 유지됩니다.", - certFingerprintLabel: "이 컴퓨터의 루트 CA SHA-256", - certFingerprintCopy: "전체 지문 복사", - certFingerprintCopied: "지문 복사됨", - certFingerprintUnavailable: "전체 지문을 확인할 수 없습니다. 다운로드한 인증서를 설치하거나 신뢰하지 마세요.", - certVerifyHint: "휴대폰 시스템의 인증서 상세 정보에서 SHA-256을 찾아, 완전한 신뢰를 켜기 전에 공백과 콜론을 제외한 64자 전체를 이 값과 비교하세요. 웹 페이지, 프로파일 이름이나 식별자는 신원 증명이 아닙니다. 일치하지 않거나 전체 지문을 볼 수 없으면 중단하고 다운로드했거나 설치한 프로파일을 제거하세요.", - certProfileHint: "프로파일에는 루트 인증서 한 개만 있어야 합니다. 추가 인증서, VPN 또는 기기 관리 설정이 있으면 설치하지 마세요.", - certTrustWarning: "최초 인증서 다운로드에서는 컴퓨터의 신원을 확인할 수 없으며, LAN의 악성 기기가 중간자 공격으로 루트 인증서를 바꿀 수 있습니다. 신뢰할 수 있는 가정용 또는 사설 네트워크에서만 설치하고 공용 또는 공유 네트워크에서는 진행하지 마세요. 루트 CA는 인증서를 발급할 수 있고 개인 키는 이 컴퓨터에 저장됩니다. 더 이상 사용하지 않으면 휴대폰에서 제거하세요.", - certSetupLink: "iPhone 인증서 링크 복사", - waitingStart: '서비스가 아직 시작되지 않았습니다. 스위치를 끈 다음 다시 켜세요. 앱을 다시 시작하지 마세요.', + securityHint: + '같은 LAN에서만 접속 가능하며 페어링 코드 입력이 필요합니다. 사용하지 않을 때는 끄는 것을 권장합니다.', + certHint: + '처음 연결할 때 루트 인증서 지문을 확인한 후 신뢰하세요. 이전 버전에서는 한 번 설정해야 하며, 이후 재시작과 IP 변경 시 신뢰가 유지됩니다.', + certFingerprintLabel: '이 컴퓨터의 루트 CA SHA-256', + certFingerprintCopy: '전체 지문 복사', + certFingerprintCopied: '지문 복사됨', + certFingerprintUnavailable: + '전체 지문을 확인할 수 없습니다. 다운로드한 인증서를 설치하거나 신뢰하지 마세요.', + certVerifyHint: + '휴대폰 시스템의 인증서 상세 정보에서 SHA-256을 찾아, 완전한 신뢰를 켜기 전에 공백과 콜론을 제외한 64자 전체를 이 값과 비교하세요. 웹 페이지, 프로파일 이름이나 식별자는 신원 증명이 아닙니다. 일치하지 않거나 전체 지문을 볼 수 없으면 중단하고 다운로드했거나 설치한 프로파일을 제거하세요.', + certProfileHint: + '프로파일에는 루트 인증서 한 개만 있어야 합니다. 추가 인증서, VPN 또는 기기 관리 설정이 있으면 설치하지 마세요.', + certTrustWarning: + '최초 인증서 다운로드에서는 컴퓨터의 신원을 확인할 수 없으며, LAN의 악성 기기가 중간자 공격으로 루트 인증서를 바꿀 수 있습니다. 신뢰할 수 있는 가정용 또는 사설 네트워크에서만 설치하고 공용 또는 공유 네트워크에서는 진행하지 마세요. 루트 CA는 인증서를 발급할 수 있고 개인 키는 이 컴퓨터에 저장됩니다. 더 이상 사용하지 않으면 휴대폰에서 제거하세요.', + certSetupLink: 'iPhone 인증서 링크 복사', + waitingStart: + '서비스가 아직 시작되지 않았습니다. 스위치를 끈 다음 다시 켜세요. 앱을 다시 시작하지 마세요.', starting: '원격 입력 서비스를 시작하는 중입니다…', urlsStale: '이 주소는 이전 실행에서 가져온 것으로 최신이 아닐 수 있습니다.', }, @@ -2098,6 +2105,15 @@ export const ko: typeof zhCN = { downloading: '다운로드 중', startDownload: '다운로드 시작', downloadNewModel: '새 모델 다운로드', + activeModelLabel: '사용 중인 모델', + pickerNoModelDownloaded: + '다운로드된 모델이 아직 없습니다. 로컬 모델 페이지에서 먼저 내려받으세요.', + partialDownloadsLabel: '완료되지 않은 다운로드', + partialDownloadsDesc: + '중단된 다운로드의 임시 파일이 남아 있습니다. 설치된 모델에 영향 없이 정리할 수 있습니다.', + cleanupIncomplete: '미완료 다운로드 정리', + languagesLabel: '언어', + partialBytesLabel: '남은 파일', downloadDialogTitle: '모델 다운로드', downloadDialogAlreadyHave: '모델 파일이 다운로드되었습니다. 모델 페이지에서 불러와 테스트하거나 ASR 음성 전사에서 해당 제공업체를 선택하세요.', diff --git a/openless-all/app/src/i18n/zh-CN.ts b/openless-all/app/src/i18n/zh-CN.ts index 01796900..cef80f8c 100644 --- a/openless-all/app/src/i18n/zh-CN.ts +++ b/openless-all/app/src/i18n/zh-CN.ts @@ -1651,15 +1651,18 @@ export const zhCN = { portInUse: '端口 {{port}} 被占用,请更换', startError: '远程输入服务启动失败:{{reason}}', securityHint: '仅同一局域网可访问,需输入配对码;不用时建议关闭。', - certHint: "首次连接需核对根证书指纹后再信任。升级旧版需设置一次;以后重启和换 IP 会保留信任。", - certFingerprintLabel: "本机根证书 SHA-256", - certFingerprintCopy: "复制完整指纹", - certFingerprintCopied: "指纹已复制", - certFingerprintUnavailable: "完整指纹不可用。请勿安装或信任下载的证书。", - certVerifyHint: "在手机系统的证书详情中找到 SHA-256,与这里的全部 64 个字符逐一核对(忽略空格和冒号)。必须在开启完全信任前完成。网页、描述文件名称和标识不能证明证书身份;若不一致或无法查看完整指纹,请停止并移除已下载或安装的描述文件。", - certProfileHint: "描述文件应只包含一张根证书。若有其他证书、VPN 或设备管理配置,请勿安装。", - certTrustWarning: "首次证书下载无法验证电脑身份,恶意局域网设备可能通过中间人攻击替换根证书。仅在可信的家庭或私人网络中安装,勿在公共或共享网络操作。根证书具备签发能力,私钥保存在这台电脑;不再使用时请从手机移除。", - certSetupLink: "复制 iPhone 证书链接", + certHint: + '首次连接需核对根证书指纹后再信任。升级旧版需设置一次;以后重启和换 IP 会保留信任。', + certFingerprintLabel: '本机根证书 SHA-256', + certFingerprintCopy: '复制完整指纹', + certFingerprintCopied: '指纹已复制', + certFingerprintUnavailable: '完整指纹不可用。请勿安装或信任下载的证书。', + certVerifyHint: + '在手机系统的证书详情中找到 SHA-256,与这里的全部 64 个字符逐一核对(忽略空格和冒号)。必须在开启完全信任前完成。网页、描述文件名称和标识不能证明证书身份;若不一致或无法查看完整指纹,请停止并移除已下载或安装的描述文件。', + certProfileHint: '描述文件应只包含一张根证书。若有其他证书、VPN 或设备管理配置,请勿安装。', + certTrustWarning: + '首次证书下载无法验证电脑身份,恶意局域网设备可能通过中间人攻击替换根证书。仅在可信的家庭或私人网络中安装,勿在公共或共享网络操作。根证书具备签发能力,私钥保存在这台电脑;不再使用时请从手机移除。', + certSetupLink: '复制 iPhone 证书链接', waitingStart: '服务尚未启动。请关闭开关再打开一次,不要重启软件。', starting: '正在启动远程输入服务…', urlsStale: '这些地址来自上次运行,可能已经过期。', @@ -2031,6 +2034,13 @@ export const zhCN = { downloading: '下载中', startDownload: '开始下载', downloadNewModel: '下载新模型', + activeModelLabel: '使用中的模型', + pickerNoModelDownloaded: '还没有已下载的模型,请先在本地模型页下载。', + partialDownloadsLabel: '未完成下载', + partialDownloadsDesc: '存在中断下载的临时残留,可一键清理,不影响已安装模型。', + cleanupIncomplete: '清理未完成下载', + languagesLabel: '语言', + partialBytesLabel: '残留文件', downloadDialogTitle: '下载模型', downloadDialogAlreadyHave: '模型文件已下载。可回到模型页加载并测试,或在「ASR 语音转写」中选择对应供应商。', diff --git a/openless-all/app/src/i18n/zh-TW.ts b/openless-all/app/src/i18n/zh-TW.ts index 8e984df8..c07146e6 100644 --- a/openless-all/app/src/i18n/zh-TW.ts +++ b/openless-all/app/src/i18n/zh-TW.ts @@ -1637,15 +1637,18 @@ export const zhTW: typeof zhCN = { portInUse: '連接埠 {{port}} 被佔用,請更換', startError: '遠端輸入服務啟動失敗:{{reason}}', securityHint: '僅同一區域網路可存取,需輸入配對碼;不用時建議關閉。', - certHint: "首次連線需核對根憑證指紋後再信任。升級舊版需設定一次;之後重新啟動和更換 IP 會保留信任。", - certFingerprintLabel: "本機根憑證 SHA-256", - certFingerprintCopy: "複製完整指紋", - certFingerprintCopied: "已複製指紋", - certFingerprintUnavailable: "完整指紋無法取得。請勿安裝或信任下載的憑證。", - certVerifyHint: "在手機系統的憑證詳細資訊中找到 SHA-256,與此處全部 64 個字元逐一核對(忽略空格和冒號)。必須在開啟完全信任前完成。網頁、描述檔名稱與識別碼不能證明憑證身分;若不一致或無法查看完整指紋,請停止並移除已下載或安裝的描述檔。", - certProfileHint: "描述檔應只包含一張根憑證。若有其他憑證、VPN 或裝置管理設定,請勿安裝。", - certTrustWarning: "首次憑證下載無法驗證電腦身分,惡意區域網路裝置可能透過中間人攻擊替換根憑證。僅在可信任的家庭或私人網路中安裝,請勿在公共或共享網路操作。根憑證能簽發憑證,私密金鑰保存在這台電腦;不再使用時請從手機移除。", - certSetupLink: "複製 iPhone 憑證連結", + certHint: + '首次連線需核對根憑證指紋後再信任。升級舊版需設定一次;之後重新啟動和更換 IP 會保留信任。', + certFingerprintLabel: '本機根憑證 SHA-256', + certFingerprintCopy: '複製完整指紋', + certFingerprintCopied: '已複製指紋', + certFingerprintUnavailable: '完整指紋無法取得。請勿安裝或信任下載的憑證。', + certVerifyHint: + '在手機系統的憑證詳細資訊中找到 SHA-256,與此處全部 64 個字元逐一核對(忽略空格和冒號)。必須在開啟完全信任前完成。網頁、描述檔名稱與識別碼不能證明憑證身分;若不一致或無法查看完整指紋,請停止並移除已下載或安裝的描述檔。', + certProfileHint: '描述檔應只包含一張根憑證。若有其他憑證、VPN 或裝置管理設定,請勿安裝。', + certTrustWarning: + '首次憑證下載無法驗證電腦身分,惡意區域網路裝置可能透過中間人攻擊替換根憑證。僅在可信任的家庭或私人網路中安裝,請勿在公共或共享網路操作。根憑證能簽發憑證,私密金鑰保存在這台電腦;不再使用時請從手機移除。', + certSetupLink: '複製 iPhone 憑證連結', waitingStart: '服務尚未啟動。請關閉開關再打開一次,不要重啟軟體。', starting: '正在啟動遠端輸入服務…', urlsStale: '這些地址來自上次執行,可能已經過期。', @@ -2017,6 +2020,13 @@ export const zhTW: typeof zhCN = { downloading: '下載中', startDownload: '開始下載', downloadNewModel: '下載新模型', + activeModelLabel: '使用中的模型', + pickerNoModelDownloaded: '尚無已下載的模型,請先在本機模型頁下載。', + partialDownloadsLabel: '未完成下載', + partialDownloadsDesc: '存在中斷下載的暫存殘留,可一鍵清理,不影響已安裝模型。', + cleanupIncomplete: '清理未完成下載', + languagesLabel: '語言', + partialBytesLabel: '殘留檔案', downloadDialogTitle: '下載模型', downloadDialogAlreadyHave: '模型檔案已下載。可返回模型頁載入並測試,或在「ASR 語音轉寫」中選擇對應供應商。', diff --git a/openless-all/app/src/pages/LocalAsr/components.tsx b/openless-all/app/src/pages/LocalAsr/components.tsx index 47117b7d..edeff942 100644 --- a/openless-all/app/src/pages/LocalAsr/components.tsx +++ b/openless-all/app/src/pages/LocalAsr/components.tsx @@ -474,6 +474,14 @@ export interface SidebarModelEntry { id: string; /** 展示名(如 qwen3-asr-0.6b / whisper-small)。 */ name: string; + /** 目录快照的正式展示名(Core descriptor);无则回退 name。 */ + displayName?: string; + /** 目录快照的支持语言短码(zh / en / ja…)。 */ + languages?: string[]; + /** 目录快照的远端完整尺寸;无需实时访问 HuggingFace 即可展示。 */ + sizeBytes?: number; + /** 有已下载字节但未装好 = 中断残留,可一键清理 staging 目录。 */ + partialBytes?: number; /** HF 仓库标识(Qwen3 有;sherpa/foundry 可能为空)。 */ repo?: string; /** 已下载字节数(HF 拉取的真实尺寸)。 */ @@ -532,11 +540,14 @@ function ModelChoice({ const { t } = useTranslation(); return (