diff --git a/src/components/VoiceDownloadAll.astro b/src/components/VoiceDownloadAll.astro
index 3d806ff..c36a2a2 100644
--- a/src/components/VoiceDownloadAll.astro
+++ b/src/components/VoiceDownloadAll.astro
@@ -24,6 +24,11 @@ const ui = t(lang);
// the SmartScreen walkthrough is a section further down it.
const unsignedHref = `${localizedPath('/voice/download/', lang)}#windows`;
+// The changelog is where the version number leads: a reader who wants to
+// know what they are about to install wants the release notes, not the
+// number on its own.
+const changelogHref = localizedPath('/voice/changelog/', lang);
+
const [mac, linuxX64, linuxArm, winX64, winArm] = await Promise.all([
getDownload('mac'),
getDownload('linux-x64'),
@@ -39,6 +44,33 @@ const groups = buildGroups(
);
---
+{/* The version, once, above the whole grid — the page states five
+ targets and this states the release they all come from.
+
+ Keyed to `mac` and to nothing else, deliberately. The printed value and
+ the browser-side correction have to name the SAME target or they can
+ disagree the first time a release skips one, and `mac` is the target
+ that has never been null: it is in the offline FALLBACK table, and the
+ App Store build is cut from every release. So the SSR value, the
+ `data-dl-version` the refresh writes into, and the `data-dl-row` that
+ withdraws the whole line if the platform ever reports mac unpublished
+ are one key. No new script and no second fetch — `VoiceDownloadScripts`
+ below already does both for the rows.
+
+ The store rows are the reason this is a page-level line rather than a
+ per-row one: Apple and Microsoft resolve their own builds and report no
+ version back here, so half the grid could never carry one. */}
+
diff --git a/src/lib/i18n.ts b/src/lib/i18n.ts
index 7e38d21..44714f4 100644
--- a/src/lib/i18n.ts
+++ b/src/lib/i18n.ts
@@ -261,6 +261,19 @@ export interface UIStrings {
* label has to promise the whole set rather than "more platforms".
*/
dlAllDownloads: string;
+ /**
+ * Precedes the version number above the download grid, e.g. "Latest
+ * WaveKat Voice release v0.0.52". A label, not a sentence — the version
+ * and the changelog link follow it.
+ *
+ * It names the product on purpose, even though the
two lines above
+ * already does. A passage extractor lifts this
on its own, and
+ * "Latest release v0.0.52" alone states a version of nothing; with the
+ * entity in it the line is a fact that survives being quoted. The
+ * product name is never translated (CLAUDE.md), so only the words
+ * around it change per locale.
+ */
+ dlLatestRelease: string;
talkHeading: string;
talkBody: string;
talkButton: string;
@@ -334,6 +347,7 @@ const strings: Record = {
"The direct Windows downloads aren't code-signed, so Windows warns on first launch. The Microsoft Store version is signed.",
dlWindowsUnsignedLink: 'How to get past it',
dlAllDownloads: 'All downloads and installers',
+ dlLatestRelease: 'Latest WaveKat Voice release',
talkHeading: 'Talk to us',
talkBody:
'Questions, feedback, or a device you wish we supported? Email is the best way to reach us — we read every message and reply as soon as we can.',
@@ -388,6 +402,7 @@ const strings: Record = {
'直接下载的 Windows 版尚未进行代码签名,首次启动时系统会弹出提醒;Microsoft Store 版本已签名。',
dlWindowsUnsignedLink: '如何继续安装',
dlAllDownloads: '所有下载与安装程序',
+ dlLatestRelease: 'WaveKat Voice 最新版本',
talkHeading: '联系我们',
talkBody:
'有疑问、建议,或希望我们支持某种设备?邮件是联系我们的最佳方式——我们会阅读每一条消息,并尽快回复。',
diff --git a/src/lib/ui/de.ts b/src/lib/ui/de.ts
index 5e37a28..a1bfc0e 100644
--- a/src/lib/ui/de.ts
+++ b/src/lib/ui/de.ts
@@ -34,6 +34,7 @@ export const ui: UIStrings = {
'Die direkten Windows-Downloads sind nicht signiert, deshalb warnt Windows beim ersten Start. Die Version aus dem Microsoft Store ist signiert.',
dlWindowsUnsignedLink: 'So kommen Sie daran vorbei',
dlAllDownloads: 'Alle Downloads und Installer',
+ dlLatestRelease: 'Neueste Version von WaveKat Voice',
talkHeading: 'Kontakt',
talkBody:
'Fragen, Feedback oder ein Gerät, das Sie sich von uns wünschen? Am besten erreichen Sie uns per E-Mail — wir lesen jede Nachricht und antworten, so schnell wir können.',
diff --git a/src/lib/ui/es.ts b/src/lib/ui/es.ts
index 5bfd4ab..7da4254 100644
--- a/src/lib/ui/es.ts
+++ b/src/lib/ui/es.ts
@@ -34,6 +34,7 @@ export const ui: UIStrings = {
'Las descargas directas para Windows no están firmadas, así que Windows avisa al abrirlas por primera vez. La versión de Microsoft Store sí está firmada.',
dlWindowsUnsignedLink: 'Cómo continuar',
dlAllDownloads: 'Todas las descargas e instaladores',
+ dlLatestRelease: 'Última versión de WaveKat Voice',
talkHeading: 'Contacto',
talkBody:
'¿Preguntas, comentarios o un dispositivo que le gustaría que admitiéramos? El correo electrónico es la mejor forma de contactarnos: leemos cada mensaje y respondemos en cuanto podemos.',
diff --git a/src/lib/ui/fr.ts b/src/lib/ui/fr.ts
index e1c3248..8574e5c 100644
--- a/src/lib/ui/fr.ts
+++ b/src/lib/ui/fr.ts
@@ -34,6 +34,7 @@ export const ui: UIStrings = {
"Les téléchargements directs pour Windows ne sont pas signés : Windows affiche un avertissement au premier lancement. La version du Microsoft Store, elle, est signée.",
dlWindowsUnsignedLink: 'Comment passer outre',
dlAllDownloads: 'Tous les téléchargements et installateurs',
+ dlLatestRelease: 'Dernière version de WaveKat Voice',
talkHeading: 'Nous contacter',
talkBody:
'Une question, un retour, ou un appareil que vous aimeriez nous voir prendre en charge ? L’e-mail est le meilleur moyen de nous joindre — nous lisons chaque message et répondons dès que possible.',
diff --git a/src/lib/ui/it.ts b/src/lib/ui/it.ts
index e7dfb58..aec2da3 100644
--- a/src/lib/ui/it.ts
+++ b/src/lib/ui/it.ts
@@ -34,6 +34,7 @@ export const ui: UIStrings = {
'I download diretti per Windows non sono firmati, quindi Windows avvisa al primo avvio. La versione di Microsoft Store è firmata.',
dlWindowsUnsignedLink: 'Come procedere',
dlAllDownloads: 'Tutti i download e gli installer',
+ dlLatestRelease: 'Ultima versione di WaveKat Voice',
talkHeading: 'Contattaci',
talkBody:
'Domande, suggerimenti o un dispositivo che vorresti vedere supportato? L’email è il modo migliore per raggiungerci: leggiamo ogni messaggio e rispondiamo il prima possibile.',
diff --git a/src/lib/ui/ja.ts b/src/lib/ui/ja.ts
index dca7e5c..f241e31 100644
--- a/src/lib/ui/ja.ts
+++ b/src/lib/ui/ja.ts
@@ -34,6 +34,7 @@ export const ui: UIStrings = {
'直接ダウンロードした Windows 版はコード署名されていないため、初回起動時に警告が表示されます。Microsoft Store 版は署名済みです。',
dlWindowsUnsignedLink: '進める方法',
dlAllDownloads: 'すべてのダウンロードとインストーラー',
+ dlLatestRelease: 'WaveKat Voice の最新バージョン',
talkHeading: 'お問い合わせ',
talkBody:
diff --git a/src/lib/ui/ko.ts b/src/lib/ui/ko.ts
index 5951dc3..35d233f 100644
--- a/src/lib/ui/ko.ts
+++ b/src/lib/ui/ko.ts
@@ -34,6 +34,7 @@ export const ui: UIStrings = {
'직접 내려받은 Windows 빌드는 코드 서명이 되어 있지 않아 첫 실행 시 경고가 표시됩니다. Microsoft Store 버전은 서명되어 있습니다.',
dlWindowsUnsignedLink: '넘어가는 방법',
dlAllDownloads: '모든 다운로드 및 설치 파일',
+ dlLatestRelease: 'WaveKat Voice 최신 버전',
talkHeading: '문의하기',
talkBody:
'궁금한 점이나 의견이 있으신가요? 지원했으면 하는 기기가 있으신가요? 이메일이 저희에게 연락하는 가장 좋은 방법입니다. 모든 메시지를 읽고 가능한 한 빨리 답변드립니다.',
diff --git a/src/lib/ui/zh-hant.ts b/src/lib/ui/zh-hant.ts
index 993e2fb..3c3604b 100644
--- a/src/lib/ui/zh-hant.ts
+++ b/src/lib/ui/zh-hant.ts
@@ -34,6 +34,7 @@ export const ui: UIStrings = {
'直接下載的 Windows 版尚未進行程式碼簽章,首次啟動時系統會跳出提醒;Microsoft Store 版本已簽章。',
dlWindowsUnsignedLink: '如何繼續安裝',
dlAllDownloads: '所有下載與安裝程式',
+ dlLatestRelease: 'WaveKat Voice 最新版本',
talkHeading: '聯絡我們',
talkBody:
'有疑問、建議,或希望我們支援某款裝置?電子郵件是聯絡我們的最佳方式——我們會閱讀每一則訊息,並盡快回覆。',