feat(i18n): convert Settings hardware section to t() (Batch E)
This commit is contained in:
1 parent
c0b7587298
commit
c98c14bbc7
1 file changed
+82
-68
@@ -752,14 +752,18 @@
|
||||
</section>
|
||||
{:else if section === "hardware"}
|
||||
<section>
|
||||
<h3>Hardware</h3>
|
||||
<h3>{t("settings.hardware.title")}</h3>
|
||||
{#if settings.hardware}
|
||||
<div class="row">
|
||||
Active backend<code>{settings.hardware.active}</code>
|
||||
<span class="muted">· model {settings.hardware.modelSize}</span>
|
||||
{t("settings.hardware.active_backend")}<code>{settings.hardware.active}</code>
|
||||
<span class="muted"
|
||||
>{t("settings.hardware.model_meta", {
|
||||
size: settings.hardware.modelSize,
|
||||
})}</span
|
||||
>
|
||||
</div>
|
||||
<label
|
||||
>Preferred backend
|
||||
>{t("settings.hardware.preferred_backend")}
|
||||
<select
|
||||
value={settings.settings.preferred_backend}
|
||||
onchange={(e) =>
|
||||
@@ -767,40 +771,34 @@
|
||||
(e.target as HTMLSelectElement).value as BackendId | "auto",
|
||||
)}
|
||||
>
|
||||
<option value="auto">Auto (best available)</option>
|
||||
<option value="auto">{t("settings.hardware.auto_backend")}</option>
|
||||
{#each settings.hardware.backends as b (b.id)}
|
||||
<option value={b.id} disabled={!b.available}>
|
||||
{b.name} ({b.id}){b.available ? "" : " — not available"}
|
||||
{b.name} ({b.id}){b.available ? "" : ` — ${t("settings.hardware.not_available")}`}
|
||||
</option>
|
||||
{/each}
|
||||
</select>
|
||||
</label>
|
||||
<p class="muted">
|
||||
Falls back automatically (NPU → NVIDIA → AMD → Intel → CPU) if the chosen backend fails
|
||||
to load.
|
||||
</p>
|
||||
<p class="muted">{t("settings.hardware.fallback_hint")}</p>
|
||||
|
||||
<h4>Audio Devices</h4>
|
||||
<h4>{t("settings.hardware.audio_devices")}</h4>
|
||||
<label
|
||||
>Recording device
|
||||
>{t("settings.hardware.recording_device")}
|
||||
<select
|
||||
value={settings.settings.audio_output_device ?? ""}
|
||||
onchange={(e) =>
|
||||
settings.setAudioOutputDevice((e.target as HTMLSelectElement).value || null)}
|
||||
>
|
||||
<option value="">Default system audio</option>
|
||||
<option value="">{t("settings.hardware.default_system_audio")}</option>
|
||||
{#each settings.audioDevices as d (d.id)}
|
||||
<option value={d.id}>{d.name}</option>
|
||||
{/each}
|
||||
</select>
|
||||
</label>
|
||||
<p class="muted">
|
||||
WhispAssist records whatever this device plays (loopback) — the other side of the call.
|
||||
Pick a specific output if you don't want it following Windows' system default.
|
||||
</p>
|
||||
<p class="muted">{t("settings.hardware.recording_device_hint")}</p>
|
||||
|
||||
<label
|
||||
>Microphone
|
||||
>{t("settings.hardware.microphone")}
|
||||
<select
|
||||
value={!settings.settings.microphone_enabled
|
||||
? "off"
|
||||
@@ -811,18 +809,14 @@
|
||||
else settings.setMicrophone(true, v || null);
|
||||
}}
|
||||
>
|
||||
<option value="off">Off — don't capture my microphone</option>
|
||||
<option value="">Default microphone</option>
|
||||
<option value="off">{t("settings.hardware.mic_off")}</option>
|
||||
<option value="">{t("settings.hardware.default_mic")}</option>
|
||||
{#each settings.inputDevices as d (d.id)}
|
||||
<option value={d.id}>{d.name}</option>
|
||||
{/each}
|
||||
</select>
|
||||
</label>
|
||||
<p class="muted">
|
||||
Adds your own voice to the live transcript so both sides of the meeting are captured.
|
||||
Stays on your device — nothing is uploaded. Choose “Off” to transcribe only the system
|
||||
audio above.
|
||||
</p>
|
||||
<p class="muted">{t("settings.hardware.mic_hint")}</p>
|
||||
|
||||
{#if settings.hardware.npu?.present}
|
||||
{@const npu = settings.hardware.npu}
|
||||
@@ -830,24 +824,27 @@
|
||||
<div class="npu-package">
|
||||
<div class="row">
|
||||
<Cpu size={14} aria-hidden="true" />
|
||||
<strong>NPU accelerator detected</strong>
|
||||
<strong>{t("settings.hardware.npu_detected")}</strong>
|
||||
{#if ready}
|
||||
<span class="badge ok"><Check size={12} aria-hidden="true" /> Ready</span>
|
||||
<span class="badge ok"
|
||||
><Check size={12} aria-hidden="true" /> {t("settings.hardware.ready")}</span
|
||||
>
|
||||
{:else if npuBusy}
|
||||
<span class="badge busy">Downloading…</span>
|
||||
<span class="badge busy">{t("settings.hardware.downloading")}</span>
|
||||
{:else}
|
||||
<span class="badge">Package needed</span>
|
||||
<span class="badge">{t("settings.hardware.package_needed")}</span>
|
||||
{/if}
|
||||
</div>
|
||||
{#if !ready}
|
||||
<p class="muted">
|
||||
Your NPU needs a one-time acceleration package (Whisper ONNX model{npu.runtimeReady
|
||||
? ""
|
||||
: " + OpenVINO runtime"}). It downloads in the background; you can also start it
|
||||
now.
|
||||
{t("settings.hardware.npu_hint", {
|
||||
extra: npu.runtimeReady ? "" : t("settings.hardware.plus_openvino"),
|
||||
})}
|
||||
</p>
|
||||
<button onclick={downloadNpuPackage} disabled={npuBusy}>
|
||||
{npuBusy ? "Downloading…" : "Download NPU package"}
|
||||
{npuBusy
|
||||
? t("settings.hardware.downloading")
|
||||
: t("settings.hardware.download_npu")}
|
||||
</button>
|
||||
{/if}
|
||||
{#if npuMsg}<p class="muted npu-status">{npuMsg}</p>{/if}
|
||||
@@ -861,29 +858,34 @@
|
||||
<div class="npu-package">
|
||||
<div class="row">
|
||||
<Cpu size={14} aria-hidden="true" />
|
||||
<strong>GPU acceleration (DirectML)</strong>
|
||||
<strong>{t("settings.hardware.dml_title")}</strong>
|
||||
{#if dmlReady}
|
||||
<span class="badge ok"><Check size={12} aria-hidden="true" /> Ready</span>
|
||||
<span class="badge ok"
|
||||
><Check size={12} aria-hidden="true" /> {t("settings.hardware.ready")}</span
|
||||
>
|
||||
{:else if dmlBusy}
|
||||
<span class="badge busy">Downloading…</span>
|
||||
<span class="badge busy">{t("settings.hardware.downloading")}</span>
|
||||
{:else}
|
||||
<span class="badge">Package needed</span>
|
||||
<span class="badge">{t("settings.hardware.package_needed")}</span>
|
||||
{/if}
|
||||
</div>
|
||||
{#if !dmlReady}
|
||||
<p class="muted">
|
||||
Your GPU can be accelerated without Vulkan via DirectML — a one-time package
|
||||
(Whisper ONNX model{dml.runtimeReady ? "" : " + DirectML runtime"}).
|
||||
{t("settings.hardware.dml_hint", {
|
||||
extra: dml.runtimeReady ? "" : t("settings.hardware.plus_directml"),
|
||||
})}
|
||||
</p>
|
||||
<button onclick={downloadDirectmlPackage} disabled={dmlBusy}>
|
||||
{dmlBusy ? "Downloading…" : "Download DirectML package"}
|
||||
{dmlBusy
|
||||
? t("settings.hardware.downloading")
|
||||
: t("settings.hardware.download_dml")}
|
||||
</button>
|
||||
{/if}
|
||||
{#if dmlMsg}<p class="muted npu-status">{dmlMsg}</p>{/if}
|
||||
</div>
|
||||
{/if}
|
||||
{:else}
|
||||
<p class="muted">Hardware detection unavailable.</p>
|
||||
<p class="muted">{t("settings.hardware.detection_unavailable")}</p>
|
||||
{/if}
|
||||
|
||||
<label class="row">
|
||||
@@ -893,11 +895,12 @@
|
||||
onchange={(e) => settings.setLowOverhead((e.target as HTMLInputElement).checked)}
|
||||
/>
|
||||
<span
|
||||
>Low overhead preset <em>(CPU + smallest model, for battery/background use)</em></span
|
||||
>{t("settings.hardware.low_overhead")}
|
||||
<em>({t("settings.hardware.low_overhead_note")})</em></span
|
||||
>
|
||||
</label>
|
||||
|
||||
<h4>Models</h4>
|
||||
<h4>{t("settings.hardware.models")}</h4>
|
||||
<ul class="models">
|
||||
{#each settings.models as m (m.id)}
|
||||
{@const downloading = m.id in settings.downloadProgress}
|
||||
@@ -908,16 +911,19 @@
|
||||
<span class="meta">
|
||||
{fmtBytes(m.size_mb)}
|
||||
{#if m.active}
|
||||
<span class="badge ok"><Check size={11} aria-hidden="true" /> Active</span>
|
||||
<span class="badge ok"
|
||||
><Check size={11} aria-hidden="true" />
|
||||
{t("settings.hardware.active_badge")}</span
|
||||
>
|
||||
{:else if m.installed}
|
||||
<span class="badge">Installed</span>
|
||||
<span class="badge">{t("settings.hardware.installed")}</span>
|
||||
{/if}
|
||||
</span>
|
||||
{#if downloading}
|
||||
<div
|
||||
class="progress"
|
||||
role="progressbar"
|
||||
aria-label="Downloading {m.label}"
|
||||
aria-label={t("settings.hardware.downloading_model", { name: m.label })}
|
||||
aria-valuenow={pct ?? undefined}
|
||||
aria-valuemin={0}
|
||||
aria-valuemax={100}
|
||||
@@ -929,7 +935,7 @@
|
||||
></div>
|
||||
</div>
|
||||
<span class="muted progress-label"
|
||||
>Downloading… {pct !== null ? `${pct}%` : ""}</span
|
||||
>{t("settings.hardware.downloading")} {pct !== null ? `${pct}%` : ""}</span
|
||||
>
|
||||
{/if}
|
||||
</div>
|
||||
@@ -942,19 +948,24 @@
|
||||
disabled={m.active}
|
||||
onclick={() => settings.setActiveModel(m.id)}
|
||||
>
|
||||
<Check size={13} aria-hidden="true" /> Use
|
||||
<Check size={13} aria-hidden="true" />
|
||||
{t("settings.hardware.use")}
|
||||
</button>
|
||||
<button
|
||||
class="icon-btn danger"
|
||||
disabled={m.active}
|
||||
title={m.active ? "Can't remove the active model" : "Remove"}
|
||||
title={m.active
|
||||
? t("settings.hardware.cant_remove_active")
|
||||
: t("settings.hardware.remove")}
|
||||
onclick={() => settings.removeModel(m.id)}
|
||||
>
|
||||
<Trash2 size={13} aria-hidden="true" /> Remove
|
||||
<Trash2 size={13} aria-hidden="true" />
|
||||
{t("settings.hardware.remove")}
|
||||
</button>
|
||||
{:else}
|
||||
<button class="icon-btn" onclick={() => settings.downloadModel(m.id)}>
|
||||
<Download size={13} aria-hidden="true" /> Download
|
||||
<Download size={13} aria-hidden="true" />
|
||||
{t("settings.hardware.download")}
|
||||
</button>
|
||||
{/if}
|
||||
</div>
|
||||
@@ -962,12 +973,8 @@
|
||||
{/each}
|
||||
</ul>
|
||||
|
||||
<h4>Speaker diarization</h4>
|
||||
<p class="muted">
|
||||
Install both models to have finished recordings separated by speaker (Speaker 1, Speaker
|
||||
2, …) instead of one running transcript. Runs fully offline, once per meeting after it
|
||||
stops. Without them, every line is attributed to a single speaker.
|
||||
</p>
|
||||
<h4>{t("settings.hardware.diarization")}</h4>
|
||||
<p class="muted">{t("settings.hardware.diarization_hint")}</p>
|
||||
<ul class="models">
|
||||
{#each settings.diarizationModels as m (m.id)}
|
||||
{@const downloading = m.id in settings.downloadProgress}
|
||||
@@ -978,14 +985,17 @@
|
||||
<span class="meta">
|
||||
{fmtBytes(m.size_mb)}
|
||||
{#if m.installed}
|
||||
<span class="badge ok"><Check size={11} aria-hidden="true" /> Installed</span>
|
||||
<span class="badge ok"
|
||||
><Check size={11} aria-hidden="true" />
|
||||
{t("settings.hardware.installed")}</span
|
||||
>
|
||||
{/if}
|
||||
</span>
|
||||
{#if downloading}
|
||||
<div
|
||||
class="progress"
|
||||
role="progressbar"
|
||||
aria-label="Downloading {m.label}"
|
||||
aria-label={t("settings.hardware.downloading_model", { name: m.label })}
|
||||
aria-valuenow={pct ?? undefined}
|
||||
aria-valuemin={0}
|
||||
aria-valuemax={100}
|
||||
@@ -997,7 +1007,7 @@
|
||||
></div>
|
||||
</div>
|
||||
<span class="muted progress-label"
|
||||
>Downloading… {pct !== null ? `${pct}%` : ""}</span
|
||||
>{t("settings.hardware.downloading")} {pct !== null ? `${pct}%` : ""}</span
|
||||
>
|
||||
{/if}
|
||||
</div>
|
||||
@@ -1007,14 +1017,16 @@
|
||||
{:else if m.installed}
|
||||
<button
|
||||
class="icon-btn danger"
|
||||
title="Remove"
|
||||
title={t("settings.hardware.remove")}
|
||||
onclick={() => settings.removeDiarizationModel(m.id)}
|
||||
>
|
||||
<Trash2 size={13} aria-hidden="true" /> Remove
|
||||
<Trash2 size={13} aria-hidden="true" />
|
||||
{t("settings.hardware.remove")}
|
||||
</button>
|
||||
{:else}
|
||||
<button class="icon-btn" onclick={() => settings.downloadDiarizationModel(m.id)}>
|
||||
<Download size={13} aria-hidden="true" /> Download
|
||||
<Download size={13} aria-hidden="true" />
|
||||
{t("settings.hardware.download")}
|
||||
</button>
|
||||
{/if}
|
||||
</div>
|
||||
@@ -1042,14 +1054,16 @@
|
||||
<p class="muted">{t("settings.transcription.applies_hint")}</p>
|
||||
{:else}
|
||||
<label
|
||||
>Language
|
||||
>{t("settings.transcription.label")}
|
||||
<select disabled aria-describedby="language-disabled-hint">
|
||||
<option>English only</option>
|
||||
<option>{t("settings.transcription.english_only")}</option>
|
||||
</select>
|
||||
</label>
|
||||
<p class="muted" id="language-disabled-hint">
|
||||
{activeModel ? `"${activeModel.label}" is English-only.` : "No model selected."} Switch to
|
||||
a multilingual model above to choose a language.
|
||||
{activeModel
|
||||
? t("settings.transcription.model_english_only", { model: activeModel.label })
|
||||
: t("settings.transcription.no_model")}
|
||||
{t("settings.transcription.switch_multilingual")}
|
||||
</p>
|
||||
{/if}
|
||||
</section>
|
||||
|
||||
Reference in new issue
Block a user