feat(setup): optional Hugging Face token in the library act (#303)

The unified library dropped the inline HF-token field the old
ModelStoreTab embed used to provide — so onboarding produced installs
with no token, and users hit the 'speaker diarization disabled' wall on
their first multi-speaker dub. Restored as a quiet disclosure at the
bottom of the Models & engines act: password input → POST
/system/set-env HF_TOKEN (same durable persistence Settings uses),
saved/error states, Enter-to-save. Copy names the concrete benefit
(pyannote diarization) and the local-first promise (token stays on this
machine). 6 strings × 21 locales.

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Palash Debnath
2026-06-07 22:23:55 +05:30
committed by GitHub
co-authored by Claude Opus 4.8
parent e424f46656
commit 0bb026f6f8
23 changed files with 214 additions and 21 deletions
+61
View File
@@ -69,8 +69,32 @@ export default function WizardLibrary() {
const [progress, setProgress] = useState({}); // { repo_id: { phase, files } }
const [showTail, setShowTail] = useState(false);
const [switching, setSwitching] = useState(null);
const [hfToken, setHfToken] = useState('');
const [hfState, setHfState] = useState('idle'); // idle | saving | saved | error
const esRef = useRef(null);
// Optional HF token: unlocks gated models (e.g. pyannote speaker
// diarization). Same persistence endpoint Settings uses — the backend
// writes it durably so it survives restarts.
const saveHfToken = async () => {
const value = hfToken.trim();
if (!value || hfState === 'saving') return;
setHfState('saving');
try {
const { API } = await import('../api/client');
const res = await fetch(`${API}/system/set-env`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ key: 'HF_TOKEN', value }),
});
if (!res.ok) throw new Error(String(res.status));
setHfState('saved');
setHfToken('');
} catch {
setHfState('error');
}
};
const models = useMemo(() => {
const list = modelsQuery.data;
return Array.isArray(list) ? list : (list?.models ?? []);
@@ -214,6 +238,43 @@ export default function WizardLibrary() {
{t('firstrun.resume_note', 'Interrupted downloads resume automatically — closing the app is safe.')}
</p>
)}
<details className="frs__advanced swiz-lib__hf">
<summary>
{hfState === 'saved'
? `${t('firstrun.hf_token_saved', 'Hugging Face token saved')}`
: t('firstrun.hf_token_title', 'Hugging Face token (optional)')}
</summary>
<div className="swiz-lib__hf-body">
<p className="frs__trust">
{t('firstrun.hf_token_hint', 'Unlocks gated models — e.g. speaker diarization for multi-speaker dubbing (pyannote). Free account token; stays on this machine.')}
</p>
<div className="swiz-lib__hf-row">
<input
className="frs-input"
type="password"
placeholder="hf_…"
value={hfToken}
autoComplete="off"
onChange={(e) => { setHfToken(e.target.value); if (hfState !== 'idle') setHfState('idle'); }}
onKeyDown={(e) => { if (e.key === 'Enter') saveHfToken(); }}
aria-label={t('firstrun.hf_token_title', 'Hugging Face token (optional)')}
/>
<button
type="button"
className="frs-btn frs-btn--quiet"
disabled={!hfToken.trim() || hfState === 'saving'}
onClick={saveHfToken}
>
{hfState === 'saving'
? t('firstrun.hf_token_saving', 'saving…')
: t('firstrun.hf_token_save', 'Save')}
</button>
</div>
{hfState === 'error' && (
<p className="frs__blocker">{t('firstrun.hf_token_error', 'Could not save the token — try again or set it later in Settings → Credentials.')}</p>
)}
</div>
</details>
</div>
);
}
+7 -1
View File
@@ -1663,6 +1663,12 @@
"resume_note": "تُستأنف التنزيلات المتقطعة تلقائيًا — إغلاق التطبيق آمن.",
"eta_left": "متبقٍ ~{{eta}}",
"first_sound_text": "مرحبًا بك في الاستوديو الخاص بك. كل كلمة تسمعها وُلِّدت على هذا الجهاز للتو.",
"first_sound_done": "ذلك الصوت؟ وُلِّد قبل ثوانٍ، محليًا. مرحبًا بك."
"first_sound_done": "ذلك الصوت؟ وُلِّد قبل ثوانٍ، محليًا. مرحبًا بك.",
"hf_token_title": "رمز Hugging Face (اختياري)",
"hf_token_hint": "يفتح النماذج المقيّدة — مثل فصل المتحدثين للدبلجة متعددة الأصوات (pyannote). رمز حساب مجاني؛ يبقى على هذا الجهاز.",
"hf_token_save": "حفظ",
"hf_token_saving": "جارٍ الحفظ…",
"hf_token_saved": "تم حفظ رمز Hugging Face",
"hf_token_error": "تعذّر حفظ الرمز — أعد المحاولة أو عيّنه لاحقًا في الإعدادات → بيانات الاعتماد."
}
}
+7 -1
View File
@@ -1664,6 +1664,12 @@
"resume_note": "Unterbrochene Downloads werden automatisch fortgesetzt — die App zu schließen ist sicher.",
"eta_left": "noch ~{{eta}}",
"first_sound_text": "Willkommen in deinem Studio. Jedes Wort, das du hörst, wurde gerade eben auf diesem Rechner erzeugt.",
"first_sound_done": "Diese Stimme? Vor Sekunden lokal erzeugt. Willkommen."
"first_sound_done": "Diese Stimme? Vor Sekunden lokal erzeugt. Willkommen.",
"hf_token_title": "Hugging-Face-Token (optional)",
"hf_token_hint": "Schaltet beschränkte Modelle frei — z. B. Sprecher-Diarisierung für Mehrsprecher-Dubbing (pyannote). Kostenloses Konto-Token; bleibt auf diesem Rechner.",
"hf_token_save": "Speichern",
"hf_token_saving": "speichert…",
"hf_token_saved": "Hugging-Face-Token gespeichert",
"hf_token_error": "Token konnte nicht gespeichert werden — erneut versuchen oder später in Einstellungen → Zugangsdaten setzen."
}
}
+7 -1
View File
@@ -1658,6 +1658,12 @@
"resume_note": "Interrupted downloads resume automatically — closing the app is safe.",
"eta_left": "~{{eta}} left",
"first_sound_text": "Welcome to your studio. Every word you hear was generated on this machine, just now.",
"first_sound_done": "That voice? Generated seconds ago, locally. Welcome in."
"first_sound_done": "That voice? Generated seconds ago, locally. Welcome in.",
"hf_token_title": "Hugging Face token (optional)",
"hf_token_hint": "Unlocks gated models — e.g. speaker diarization for multi-speaker dubbing (pyannote). Free account token; stays on this machine.",
"hf_token_save": "Save",
"hf_token_saving": "saving…",
"hf_token_saved": "Hugging Face token saved",
"hf_token_error": "Could not save the token — try again or set it later in Settings → Credentials."
}
}
+7 -1
View File
@@ -1664,6 +1664,12 @@
"resume_note": "Las descargas interrumpidas se reanudan solas; cerrar la app es seguro.",
"eta_left": "quedan ~{{eta}}",
"first_sound_text": "Bienvenido a tu estudio. Cada palabra que oyes se generó en esta máquina, ahora mismo.",
"first_sound_done": "¿Esa voz? Generada hace segundos, en local. Bienvenido."
"first_sound_done": "¿Esa voz? Generada hace segundos, en local. Bienvenido.",
"hf_token_title": "Token de Hugging Face (opcional)",
"hf_token_hint": "Desbloquea modelos restringidos — p. ej. diarización de hablantes para doblaje multivoz (pyannote). Token de cuenta gratuita; se queda en esta máquina.",
"hf_token_save": "Guardar",
"hf_token_saving": "guardando…",
"hf_token_saved": "Token de Hugging Face guardado",
"hf_token_error": "No se pudo guardar el token — reintenta o configúralo luego en Ajustes → Credenciales."
}
}
+7 -1
View File
@@ -1664,6 +1664,12 @@
"resume_note": "Les téléchargements interrompus reprennent automatiquement — fermer lapplication est sans risque.",
"eta_left": "~{{eta}} restantes",
"first_sound_text": "Bienvenue dans votre studio. Chaque mot que vous entendez vient d’être généré sur cette machine.",
"first_sound_done": "Cette voix ? Générée il y a quelques secondes, en local. Bienvenue."
"first_sound_done": "Cette voix ? Générée il y a quelques secondes, en local. Bienvenue.",
"hf_token_title": "Jeton Hugging Face (optionnel)",
"hf_token_hint": "Débloque les modèles restreints — p. ex. la diarisation pour le doublage multi-locuteurs (pyannote). Jeton de compte gratuit ; reste sur cette machine.",
"hf_token_save": "Enregistrer",
"hf_token_saving": "enregistrement…",
"hf_token_saved": "Jeton Hugging Face enregistré",
"hf_token_error": "Impossible denregistrer le jeton — réessayez ou configurez-le plus tard dans Réglages → Identifiants."
}
}
+7 -1
View File
@@ -1663,6 +1663,12 @@
"resume_note": "रुके हुए डाउनलोड अपने आप फिर शुरू हो जाते हैं — ऐप बंद करना सुरक्षित है।",
"eta_left": "~{{eta}} शेष",
"first_sound_text": "आपके स्टूडियो में स्वागत है। आप जो भी शब्द सुन रहे हैं, वह अभी-अभी इसी मशीन पर बना है।",
"first_sound_done": "वह आवाज़? कुछ सेकंड पहले, लोकली बनी। स्वागत है।"
"first_sound_done": "वह आवाज़? कुछ सेकंड पहले, लोकली बनी। स्वागत है।",
"hf_token_title": "Hugging Face टोकन (वैकल्पिक)",
"hf_token_hint": "प्रतिबंधित मॉडल खोलता है — जैसे मल्टी-स्पीकर डबिंग के लिए स्पीकर डायराइज़ेशन (pyannote)। मुफ़्त खाते का टोकन; इसी मशीन पर रहता है।",
"hf_token_save": "सहेजें",
"hf_token_saving": "सहेजा जा रहा है…",
"hf_token_saved": "Hugging Face टोकन सहेजा गया",
"hf_token_error": "टोकन सहेजा नहीं जा सका — फिर कोशिश करें या बाद में सेटिंग्स → क्रेडेंशियल्स में सेट करें।"
}
}
+7 -1
View File
@@ -1663,6 +1663,12 @@
"resume_note": "Unduhan yang terputus dilanjutkan otomatis — menutup aplikasi aman.",
"eta_left": "sisa ~{{eta}}",
"first_sound_text": "Selamat datang di studio Anda. Setiap kata yang Anda dengar baru saja dihasilkan di mesin ini.",
"first_sound_done": "Suara tadi? Dihasilkan beberapa detik lalu, secara lokal. Selamat datang."
"first_sound_done": "Suara tadi? Dihasilkan beberapa detik lalu, secara lokal. Selamat datang.",
"hf_token_title": "Token Hugging Face (opsional)",
"hf_token_hint": "Membuka model terbatas — mis. diarisasi pembicara untuk sulih suara multi-suara (pyannote). Token akun gratis; tetap di mesin ini.",
"hf_token_save": "Simpan",
"hf_token_saving": "menyimpan…",
"hf_token_saved": "Token Hugging Face tersimpan",
"hf_token_error": "Gagal menyimpan token — coba lagi atau atur nanti di Pengaturan → Kredensial."
}
}
+7 -1
View File
@@ -1663,6 +1663,12 @@
"resume_note": "I download interrotti riprendono da soli — chiudere lapp è sicuro.",
"eta_left": "~{{eta}} rimanenti",
"first_sound_text": "Benvenuto nel tuo studio. Ogni parola che senti è stata generata su questa macchina, proprio ora.",
"first_sound_done": "Quella voce? Generata pochi secondi fa, in locale. Benvenuto."
"first_sound_done": "Quella voce? Generata pochi secondi fa, in locale. Benvenuto.",
"hf_token_title": "Token Hugging Face (opzionale)",
"hf_token_hint": "Sblocca i modelli riservati — es. diarizzazione dei parlanti per il doppiaggio multivoce (pyannote). Token di account gratuito; resta su questa macchina.",
"hf_token_save": "Salva",
"hf_token_saving": "salvataggio…",
"hf_token_saved": "Token Hugging Face salvato",
"hf_token_error": "Impossibile salvare il token — riprova o impostalo dopo in Impostazioni → Credenziali."
}
}
+7 -1
View File
@@ -1664,6 +1664,12 @@
"resume_note": "中断したダウンロードは自動的に再開されます。アプリを閉じても安全です。",
"eta_left": "残り約 {{eta}}",
"first_sound_text": "あなたのスタジオへようこそ。いま聞こえている言葉はすべて、たった今このマシンで生成されたものです。",
"first_sound_done": "この声、数秒前にローカルで生成されました。ようこそ。"
"first_sound_done": "この声、数秒前にローカルで生成されました。ようこそ。",
"hf_token_title": "Hugging Face トークン(任意)",
"hf_token_hint": "制限付きモデルを解放します。例:複数話者ダビング用の話者分離(pyannote)。無料アカウントのトークンで、このマシンにのみ保存されます。",
"hf_token_save": "保存",
"hf_token_saving": "保存中…",
"hf_token_saved": "Hugging Face トークンを保存しました",
"hf_token_error": "トークンを保存できませんでした。再試行するか、後で設定 → 認証情報から設定してください。"
}
}
+7 -1
View File
@@ -1663,6 +1663,12 @@
"resume_note": "중단된 다운로드는 자동으로 이어집니다 — 앱을 닫아도 안전합니다.",
"eta_left": "약 {{eta}} 남음",
"first_sound_text": "당신의 스튜디오에 오신 것을 환영합니다. 지금 들리는 모든 말은 방금 이 컴퓨터에서 생성되었습니다.",
"first_sound_done": "방금 그 목소리, 몇 초 전 로컬에서 생성됐습니다. 환영합니다."
"first_sound_done": "방금 그 목소리, 몇 초 전 로컬에서 생성됐습니다. 환영합니다.",
"hf_token_title": "Hugging Face 토큰(선택)",
"hf_token_hint": "제한된 모델을 사용할 수 있게 합니다 — 예: 다중 화자 더빙용 화자 분리(pyannote). 무료 계정 토큰이며 이 컴퓨터에만 저장됩니다.",
"hf_token_save": "저장",
"hf_token_saving": "저장 중…",
"hf_token_saved": "Hugging Face 토큰 저장됨",
"hf_token_error": "토큰을 저장하지 못했습니다 — 다시 시도하거나 나중에 설정 → 자격 증명에서 설정하세요."
}
}
+7 -1
View File
@@ -1663,6 +1663,12 @@
"resume_note": "Onderbroken downloads hervatten automatisch — de app sluiten is veilig.",
"eta_left": "nog ~{{eta}}",
"first_sound_text": "Welkom in je studio. Elk woord dat je hoort is zojuist op deze machine gegenereerd.",
"first_sound_done": "Die stem? Seconden geleden lokaal gegenereerd. Welkom."
"first_sound_done": "Die stem? Seconden geleden lokaal gegenereerd. Welkom.",
"hf_token_title": "Hugging Face-token (optioneel)",
"hf_token_hint": "Ontgrendelt afgeschermde modellen — bijv. sprekerdiarisatie voor dubben met meerdere stemmen (pyannote). Token van gratis account; blijft op deze machine.",
"hf_token_save": "Opslaan",
"hf_token_saving": "opslaan…",
"hf_token_saved": "Hugging Face-token opgeslagen",
"hf_token_error": "Token kon niet worden opgeslagen — probeer opnieuw of stel het later in via Instellingen → Inloggegevens."
}
}
+7 -1
View File
@@ -1663,6 +1663,12 @@
"resume_note": "Przerwane pobierania wznawiają się same — zamknięcie aplikacji jest bezpieczne.",
"eta_left": "pozostało ~{{eta}}",
"first_sound_text": "Witaj w swoim studiu. Każde słowo, które słyszysz, zostało wygenerowane na tym komputerze — przed chwilą.",
"first_sound_done": "Ten głos? Wygenerowany sekundy temu, lokalnie. Witaj."
"first_sound_done": "Ten głos? Wygenerowany sekundy temu, lokalnie. Witaj.",
"hf_token_title": "Token Hugging Face (opcjonalny)",
"hf_token_hint": "Odblokowuje modele z ograniczeniami — np. diaryzację mówców do dubbingu wielogłosowego (pyannote). Token darmowego konta; zostaje na tym komputerze.",
"hf_token_save": "Zapisz",
"hf_token_saving": "zapisywanie…",
"hf_token_saved": "Token Hugging Face zapisany",
"hf_token_error": "Nie udało się zapisać tokenu — spróbuj ponownie lub ustaw go później w Ustawieniach → Dane logowania."
}
}
+7 -1
View File
@@ -1663,6 +1663,12 @@
"resume_note": "Downloads interrompidos retomam sozinhos — fechar o app é seguro.",
"eta_left": "faltam ~{{eta}}",
"first_sound_text": "Bem-vindo ao seu estúdio. Cada palavra que você ouve foi gerada nesta máquina, agora mesmo.",
"first_sound_done": "Essa voz? Gerada há segundos, localmente. Bem-vindo."
"first_sound_done": "Essa voz? Gerada há segundos, localmente. Bem-vindo.",
"hf_token_title": "Token do Hugging Face (opcional)",
"hf_token_hint": "Desbloqueia modelos restritos — ex.: diarização de falantes para dublagem multivoz (pyannote). Token de conta gratuita; fica nesta máquina.",
"hf_token_save": "Salvar",
"hf_token_saving": "salvando…",
"hf_token_saved": "Token do Hugging Face salvo",
"hf_token_error": "Não foi possível salvar o token — tente de novo ou configure depois em Configurações → Credenciais."
}
}
+7 -1
View File
@@ -1663,6 +1663,12 @@
"resume_note": "Прерванные загрузки возобновляются автоматически — закрывать приложение безопасно.",
"eta_left": "осталось ~{{eta}}",
"first_sound_text": "Добро пожаловать в вашу студию. Каждое слово, которое вы слышите, сгенерировано на этой машине только что.",
"first_sound_done": "Этот голос? Сгенерирован секунды назад, локально. Добро пожаловать."
"first_sound_done": "Этот голос? Сгенерирован секунды назад, локально. Добро пожаловать.",
"hf_token_title": "Токен Hugging Face (необязательно)",
"hf_token_hint": "Открывает закрытые модели — например, диаризацию для многоголосого дубляжа (pyannote). Токен бесплатного аккаунта; остаётся на этой машине.",
"hf_token_save": "Сохранить",
"hf_token_saving": "сохранение…",
"hf_token_saved": "Токен Hugging Face сохранён",
"hf_token_error": "Не удалось сохранить токен — повторите или задайте позже в Настройках → Учётные данные."
}
}
+7 -1
View File
@@ -1663,6 +1663,12 @@
"resume_note": "Avbrutna nedladdningar återupptas automatiskt — det är säkert att stänga appen.",
"eta_left": "~{{eta}} kvar",
"first_sound_text": "Välkommen till din studio. Varje ord du hör genererades på den här datorn, alldeles nyss.",
"first_sound_done": "Den rösten? Genererad för några sekunder sedan, lokalt. Välkommen."
"first_sound_done": "Den rösten? Genererad för några sekunder sedan, lokalt. Välkommen.",
"hf_token_title": "Hugging Face-token (valfritt)",
"hf_token_hint": "Låser upp begränsade modeller — t.ex. talardiarisering för dubbning med flera röster (pyannote). Token från gratiskonto; stannar på den här datorn.",
"hf_token_save": "Spara",
"hf_token_saving": "sparar…",
"hf_token_saved": "Hugging Face-token sparad",
"hf_token_error": "Kunde inte spara token — försök igen eller ange den senare i Inställningar → Uppgifter."
}
}
+7 -1
View File
@@ -1663,6 +1663,12 @@
"resume_note": "การดาวน์โหลดที่ขาดตอนจะทำต่ออัตโนมัติ — ปิดแอปได้อย่างปลอดภัย",
"eta_left": "เหลืออีก ~{{eta}}",
"first_sound_text": "ยินดีต้อนรับสู่สตูดิโอของคุณ ทุกคำที่คุณได้ยินถูกสร้างขึ้นบนเครื่องนี้เมื่อครู่นี้เอง",
"first_sound_done": "เสียงเมื่อกี้? สร้างขึ้นเมื่อไม่กี่วินาทีก่อน บนเครื่องนี้ ยินดีต้อนรับ"
"first_sound_done": "เสียงเมื่อกี้? สร้างขึ้นเมื่อไม่กี่วินาทีก่อน บนเครื่องนี้ ยินดีต้อนรับ",
"hf_token_title": "โทเคน Hugging Face (ไม่บังคับ)",
"hf_token_hint": "ปลดล็อกโมเดลที่จำกัดสิทธิ์ — เช่น การแยกผู้พูดสำหรับพากย์หลายเสียง (pyannote) โทเคนบัญชีฟรี เก็บไว้บนเครื่องนี้เท่านั้น",
"hf_token_save": "บันทึก",
"hf_token_saving": "กำลังบันทึก…",
"hf_token_saved": "บันทึกโทเคน Hugging Face แล้ว",
"hf_token_error": "บันทึกโทเคนไม่สำเร็จ — ลองใหม่ หรือไปตั้งค่าภายหลังที่ การตั้งค่า → ข้อมูลรับรอง"
}
}
+7 -1
View File
@@ -1663,6 +1663,12 @@
"resume_note": "Yarıda kalan indirmeler otomatik devam eder — uygulamayı kapatmak güvenlidir.",
"eta_left": "~{{eta}} kaldı",
"first_sound_text": "Stüdyona hoş geldin. Duyduğun her kelime az önce bu makinede üretildi.",
"first_sound_done": "O ses mi? Saniyeler önce, yerelde üretildi. Hoş geldin."
"first_sound_done": "O ses mi? Saniyeler önce, yerelde üretildi. Hoş geldin.",
"hf_token_title": "Hugging Face belirteci (isteğe bağlı)",
"hf_token_hint": "Kısıtlı modellerin kilidini açar — ör. çok konuşmacılı dublaj için konuşmacı ayrıştırma (pyannote). Ücretsiz hesap belirteci; bu makinede kalır.",
"hf_token_save": "Kaydet",
"hf_token_saving": "kaydediliyor…",
"hf_token_saved": "Hugging Face belirteci kaydedildi",
"hf_token_error": "Belirteç kaydedilemedi — yeniden deneyin veya sonra Ayarlar → Kimlik bilgileri bölümünden ayarlayın."
}
}
+7 -1
View File
@@ -1663,6 +1663,12 @@
"resume_note": "Перервані завантаження відновлюються автоматично — закривати застосунок безпечно.",
"eta_left": "залишилось ~{{eta}}",
"first_sound_text": "Вітаємо у вашій студії. Кожне слово, яке ви чуєте, щойно згенеровано на цій машині.",
"first_sound_done": "Той голос? Згенерований секунди тому, локально. Вітаємо."
"first_sound_done": "Той голос? Згенерований секунди тому, локально. Вітаємо.",
"hf_token_title": "Токен Hugging Face (необов’язково)",
"hf_token_hint": "Відкриває обмежені моделі — напр., діаризацію мовців для багатоголосого дубляжу (pyannote). Токен безкоштовного акаунта; залишається на цій машині.",
"hf_token_save": "Зберегти",
"hf_token_saving": "збереження…",
"hf_token_saved": "Токен Hugging Face збережено",
"hf_token_error": "Не вдалося зберегти токен — повторіть або задайте пізніше в Налаштування → Облікові дані."
}
}
+7 -1
View File
@@ -1663,6 +1663,12 @@
"resume_note": "Tải xuống bị gián đoạn sẽ tự tiếp tục — đóng ứng dụng vẫn an toàn.",
"eta_left": "còn ~{{eta}}",
"first_sound_text": "Chào mừng đến với studio của bạn. Mỗi từ bạn đang nghe vừa được tạo trên chính máy này.",
"first_sound_done": "Giọng nói đó? Vừa được tạo vài giây trước, ngay trên máy. Chào mừng."
"first_sound_done": "Giọng nói đó? Vừa được tạo vài giây trước, ngay trên máy. Chào mừng.",
"hf_token_title": "Token Hugging Face (tùy chọn)",
"hf_token_hint": "Mở khóa các mô hình bị giới hạn — ví dụ tách người nói cho lồng tiếng nhiều giọng (pyannote). Token tài khoản miễn phí; chỉ lưu trên máy này.",
"hf_token_save": "Lưu",
"hf_token_saving": "đang lưu…",
"hf_token_saved": "Đã lưu token Hugging Face",
"hf_token_error": "Không thể lưu token — thử lại hoặc đặt sau trong Cài đặt → Thông tin xác thực."
}
}
+7 -1
View File
@@ -1663,6 +1663,12 @@
"resume_note": "下载中断后会自动续传——关闭应用也没关系。",
"eta_left": "剩余约 {{eta}}",
"first_sound_text": "欢迎来到你的工作室。你听到的每一个字,都是刚刚在这台设备上生成的。",
"first_sound_done": "刚才的声音?几秒前在本地生成。欢迎入驻。"
"first_sound_done": "刚才的声音?几秒前在本地生成。欢迎入驻。",
"hf_token_title": "Hugging Face 令牌(可选)",
"hf_token_hint": "解锁受限模型——例如多说话人配音的说话人分离(pyannote)。免费账号令牌,仅保存在本机。",
"hf_token_save": "保存",
"hf_token_saving": "保存中…",
"hf_token_saved": "Hugging Face 令牌已保存",
"hf_token_error": "令牌保存失败——请重试,或稍后在设置 → 凭据中设置。"
}
}
+7 -1
View File
@@ -1663,6 +1663,12 @@
"resume_note": "下載中斷後會自動續傳——關閉應用程式也沒關係。",
"eta_left": "剩餘約 {{eta}}",
"first_sound_text": "歡迎來到你的工作室。你聽到的每一個字,都是剛剛在這台裝置上生成的。",
"first_sound_done": "剛才的聲音?幾秒前在本機生成。歡迎加入。"
"first_sound_done": "剛才的聲音?幾秒前在本機生成。歡迎加入。",
"hf_token_title": "Hugging Face 權杖(可選)",
"hf_token_hint": "解鎖受限模型——例如多語者配音的語者分離(pyannote)。免費帳號權杖,僅保存在本機。",
"hf_token_save": "儲存",
"hf_token_saving": "儲存中…",
"hf_token_saved": "Hugging Face 權杖已儲存",
"hf_token_error": "權杖儲存失敗——請重試,或稍後在設定 → 憑證中設定。"
}
}
+6
View File
@@ -131,3 +131,9 @@
.swiz-lib__sub { display: block; min-width: 0; }
.swiz-lib__more { align-self: flex-start; }
/* Optional HF token — quiet disclosure at the bottom of the library. */
.swiz-lib__hf { margin-top: 0.3rem; }
.swiz-lib__hf-body { display: flex; flex-direction: column; gap: 0.45rem; margin-top: 0.45rem; max-width: 460px; }
.swiz-lib__hf-row { display: flex; gap: 0.45rem; }
.swiz-lib__hf-row .frs-input { flex: 1; }