feat: display translated release notes in updater based on app language
Some checks failed
Release / build-windows (push) Has been cancelled
Release / build-linux (push) Has been cancelled

Use i18n translations for release notes when available, falling back to
the GitHub release body. Adds FR/EN notes for versions 0.3.8–0.3.11.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
le king fu 2026-02-22 14:14:28 -05:00
parent db337b3285
commit 0fbcbc0eca
3 changed files with 39 additions and 21 deletions

View file

@ -410,7 +410,13 @@
"installing": "Installing...", "installing": "Installing...",
"error": "Update failed", "error": "Update failed",
"retryButton": "Retry", "retryButton": "Retry",
"releaseNotes": "What's New" "releaseNotes": "What's New",
"notes": {
"0.3.11": "### Added\n- Dynamic Report: support multiple column dimensions (composite column keys)\n\n### Fixed\n- Dynamic Report: no longer affected by global page date filters — uses only its own panel filters",
"0.3.10": "### Added\n- Dynamic Report: fields can now be used in multiple zones simultaneously (rows + filters, columns + filters)\n- Dynamic Report: right-click on a filter value to exclude it (shown with strikethrough in red)\n- \"This year\" period option in reports and dashboard (Jan 1 to today)",
"0.3.9": "### Added\n- Dynamic Report (pivot table): compose custom reports by assigning dimensions to rows, columns, filters and measures to values\n- Delete keywords from the \"All Keywords\" view",
"0.3.8": "### Added\n- Custom date range picker for reports and dashboard\n- Toggle to position subtotals above or below detail rows\n- Display release notes from CHANGELOG in GitHub releases and in-app updater"
}
}, },
"dataManagement": { "dataManagement": {
"title": "Data Management", "title": "Data Management",

View file

@ -410,7 +410,13 @@
"installing": "Installation en cours...", "installing": "Installation en cours...",
"error": "Erreur lors de la mise à jour", "error": "Erreur lors de la mise à jour",
"retryButton": "Réessayer", "retryButton": "Réessayer",
"releaseNotes": "Nouveautés" "releaseNotes": "Nouveautés",
"notes": {
"0.3.11": "### Ajouté\n- Rapport dynamique : support de plusieurs dimensions en colonnes (clés composites)\n\n### Corrigé\n- Rapport dynamique : n'est plus affecté par les filtres de date globaux — utilise uniquement ses propres filtres du panneau",
"0.3.10": "### Ajouté\n- Rapport dynamique : les champs peuvent maintenant être utilisés dans plusieurs zones simultanément (lignes + filtres, colonnes + filtres)\n- Rapport dynamique : clic-droit sur une valeur de filtre pour l'exclure (affiché barré en rouge)\n- Option de période « Cette année » dans les rapports et le tableau de bord (du 1er janvier à aujourd'hui)",
"0.3.9": "### Ajouté\n- Rapport dynamique (tableau croisé) : composez des rapports personnalisés en assignant des dimensions aux lignes, colonnes, filtres et mesures aux valeurs\n- Suppression de mots-clés depuis la vue « Tous les mots-clés »",
"0.3.8": "### Ajouté\n- Sélecteur de plage de dates personnalisée pour les rapports et le tableau de bord\n- Bascule pour positionner les sous-totaux au-dessus ou en dessous des lignes de détail\n- Affichage des notes de version du CHANGELOG dans les releases GitHub et le système de mise à jour"
}
}, },
"dataManagement": { "dataManagement": {
"title": "Gestion des données", "title": "Gestion des données",

View file

@ -125,26 +125,32 @@ export default function SettingsPage() {
<p> <p>
{t("settings.updates.available", { version: state.version })} {t("settings.updates.available", { version: state.version })}
</p> </p>
{state.body && ( {(() => {
<div className="space-y-2"> const notesKey = `settings.updates.notes.${state.version}`;
<h3 className="text-sm font-semibold text-[var(--foreground)]"> const i18nNotes = t(notesKey, { defaultValue: "" });
{t("settings.updates.releaseNotes")} const notes = i18nNotes || state.body;
</h3> if (!notes) return null;
<div className="max-h-48 overflow-y-auto rounded-lg bg-[var(--background)] border border-[var(--border)] p-3 text-sm text-[var(--muted-foreground)] space-y-1"> return (
{state.body.split("\n").map((line, i) => { <div className="space-y-2">
const trimmed = line.trim(); <h3 className="text-sm font-semibold text-[var(--foreground)]">
if (!trimmed) return <div key={i} className="h-2" />; {t("settings.updates.releaseNotes")}
if (trimmed.startsWith("### ")) </h3>
return <p key={i} className="font-semibold text-[var(--foreground)] mt-2">{trimmed.slice(4)}</p>; <div className="max-h-48 overflow-y-auto rounded-lg bg-[var(--background)] border border-[var(--border)] p-3 text-sm text-[var(--muted-foreground)] space-y-1">
if (trimmed.startsWith("## ")) {notes.split("\n").map((line, i) => {
return <p key={i} className="font-bold text-[var(--foreground)] mt-2">{trimmed.slice(3)}</p>; const trimmed = line.trim();
if (trimmed.startsWith("- ")) if (!trimmed) return <div key={i} className="h-2" />;
return <p key={i} className="pl-3">{"\u2022 "}{trimmed.slice(2).replace(/\*\*(.+?)\*\*/g, "$1")}</p>; if (trimmed.startsWith("### "))
return <p key={i}>{trimmed}</p>; return <p key={i} className="font-semibold text-[var(--foreground)] mt-2">{trimmed.slice(4)}</p>;
})} if (trimmed.startsWith("## "))
return <p key={i} className="font-bold text-[var(--foreground)] mt-2">{trimmed.slice(3)}</p>;
if (trimmed.startsWith("- "))
return <p key={i} className="pl-3">{"\u2022 "}{trimmed.slice(2).replace(/\*\*(.+?)\*\*/g, "$1")}</p>;
return <p key={i}>{trimmed}</p>;
})}
</div>
</div> </div>
</div> );
)} })()}
<button <button
onClick={downloadAndInstall} onClick={downloadAndInstall}
className="flex items-center gap-2 px-4 py-2 bg-[var(--primary)] text-white rounded-lg hover:opacity-90 transition-opacity" className="flex items-center gap-2 px-4 py-2 bg-[var(--primary)] text-white rounded-lg hover:opacity-90 transition-opacity"