From 98a6dd8a2c38511058961c4e1f7a456b73615cfe Mon Sep 17 00:00:00 2001 From: Bruno Charest Date: Sun, 21 Jun 2026 10:48:14 -0400 Subject: [PATCH] =?UTF-8?q?fix:=20i18n=20for=20dashboard=20widgets=20+=20s?= =?UTF-8?q?hortcuts=20=E2=80=94=20no=20more=20hardcoded=20French?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replaced all hardcoded French text in dashboard.js with t() calls: - 'Chargement...' → t('common.loading') - 'Erreur:' → t('dashboard.error_prefix') - Size units ('o','Ko','Mo','Go') → t('dashboard.size_*') - 'fichier(s)' → t('dashboard.count_files*') - '0 fichiers' → t('dashboard.zero_files') - 'Conflits de synchronisation' → t('dashboard.conflicts_title') - 'Garder l\'original'/'Garder le conflit' → t('dashboard.keep_*') - 'Ajouter/Retirer des bookmarks' → t('dashboard.bookmark_*') - 'à l\'instant'/'il y a X min/h/j' → t('dashboard.*_ago', {n}) - 'Afficher'/'Masquer' → t('dashboard.show/hide') - 'Erreur de chargement' → t('dashboard.load_error') Added 11 shortcut i18n keys + 22 dashboard i18n keys to en.json/fr.json. Verified: '4 files' count, English shortcuts, English empty states. --- frontend/js/dashboard.js | 38 +++++++++++++++++++------------------- frontend/locales/en.json | 34 ++++++++++++++++++++++++++++++++++ frontend/locales/fr.json | 34 ++++++++++++++++++++++++++++++++++ 3 files changed, 87 insertions(+), 19 deletions(-) diff --git a/frontend/js/dashboard.js b/frontend/js/dashboard.js index 45853a9..697a908 100644 --- a/frontend/js/dashboard.js +++ b/frontend/js/dashboard.js @@ -21,18 +21,18 @@ const DashboardStatsWidget = { async load() { const grid = document.getElementById("dashboard-stats-grid"); if (!grid) return; - grid.innerHTML = '
Chargement...
'; + grid.innerHTML = `
${t('common.loading')}
`; try { const data = await api("/api/dashboard"); this.render(data); } catch (err) { - grid.innerHTML = `
Erreur: ${escapeHtml(err.message)}
`; + grid.innerHTML = `
${t('dashboard.error_prefix')}${escapeHtml(err.message)}
`; } }, render(data) { const grid = document.getElementById("dashboard-stats-grid"); if (!grid) return; - const fmtSize = (bytes) => bytes < 1024 ? `${bytes} o` : bytes < 1048576 ? `${(bytes/1024).toFixed(1)} Ko` : bytes < 1073741824 ? `${(bytes/1048576).toFixed(1)} Mo` : `${(bytes/1073741824).toFixed(1)} Go`; + const fmtSize = (bytes) => bytes < 1024 ? `${bytes}${t('dashboard.size_bytes')}` : bytes < 1048576 ? `${(bytes/1024).toFixed(1)}${t('dashboard.size_kb')}` : bytes < 1073741824 ? `${(bytes/1048576).toFixed(1)}${t('dashboard.size_mb')}` : `${(bytes/1073741824).toFixed(1)}${t('dashboard.size_gb')}`; const items = [ { icon: "files", label: t('dashboard.stats_files'), value: data.total_files.toLocaleString() }, { icon: "tags", label: t('dashboard.stats_tags'), value: data.total_tags.toLocaleString() }, @@ -120,7 +120,7 @@ const DashboardConflictsWidget = {
-

Conflits de synchronisation

+

${t('dashboard.conflicts_title')}

${conflicts.length}
@@ -130,11 +130,11 @@ const DashboardConflictsWidget = {
${escapeHtml(c.vault)} ${escapeHtml(c.conflict_path.split("/").pop())} - Conflit du ${c.conflict_date.replace(/(\d{4})(\d{2})(\d{2})-(\d{2})(\d{2})/, "$3/$2/$1 $4:$5")} + ${t('dashboard.conflict_date')}${c.conflict_date.replace(/(\d{4})(\d{2})(\d{2})-(\d{2})(\d{2})/, "$3/$2/$1 $4:$5")}
- - + +
`).join("")} @@ -149,7 +149,7 @@ const DashboardConflictsWidget = { await api("/api/conflicts/resolve", { method: "POST", body: JSON.stringify({ vault: d.vault, conflict_path: d.conflict, original_path: d.original, action }) }); showToast(t("dashboard.conflict_resolved"), "success"); this.load(); - } catch (err) { showToast("Erreur: " + err.message, "error"); } + } catch (err) { showToast(t('dashboard.error_prefix') + err.message, "error"); } } }; @@ -234,7 +234,7 @@ const DashboardRecentWidget = { } if (empty) empty.classList.add("hidden"); - if (count) count.textContent = `${this._cache.length} fichier${this._cache.length > 1 ? "s" : ""}`; + if (count) count.textContent = `${this._cache.length} ${this._cache.length > 1 ? t('dashboard.count_files_plural') : t('dashboard.count_files')}`; if (!grid) return; grid.innerHTML = ""; @@ -275,7 +275,7 @@ const DashboardRecentWidget = { const bookmarkBtn = document.createElement("button"); bookmarkBtn.className = `dashboard-card-bookmark-btn ${file.bookmarked ? "active" : ""}`; - bookmarkBtn.title = file.bookmarked ? "Retirer des bookmarks" : "Ajouter aux bookmarks"; + bookmarkBtn.title = file.bookmarked ? t('dashboard.bookmark_remove') : t('dashboard.bookmark_add'); bookmarkBtn.innerHTML = ``; bookmarkBtn.addEventListener("click", (e) => { @@ -347,7 +347,7 @@ const DashboardRecentWidget = { if (grid) grid.innerHTML = ""; if (loading) loading.classList.remove("active"); if (empty) empty.classList.remove("hidden"); - if (count) count.textContent = "0 fichiers"; + if (count) count.textContent = t('dashboard.zero_files'); safeCreateIcons(); }, @@ -356,17 +356,17 @@ const DashboardRecentWidget = { const empty = document.getElementById("dashboard-recent-empty"); if (empty) { const msg = empty.querySelector("span"); - if (msg) msg.textContent = "Erreur de chargement"; + if (msg) msg.textContent = t('dashboard.load_error'); } }, _humanizeDelta(mtime) { const delta = Date.now() / 1000 - mtime; - if (delta < 60) return "à l'instant"; - if (delta < 3600) return `il y a ${Math.floor(delta / 60)} min`; - if (delta < 86400) return `il y a ${Math.floor(delta / 3600)} h`; - if (delta < 604800) return `il y a ${Math.floor(delta / 86400)} j`; - return new Date(mtime * 1000).toLocaleDateString("fr-FR", { day: "numeric", month: "short", year: "numeric" }); + if (delta < 60) return t('dashboard.just_now'); + if (delta < 3600) return t('dashboard.min_ago', { n: Math.floor(delta / 60) }); + if (delta < 86400) return t('dashboard.hour_ago', { n: Math.floor(delta / 3600) }); + if (delta < 604800) return t('dashboard.day_ago', { n: Math.floor(delta / 86400) }); + return new Date(mtime * 1000).toLocaleDateString(getLocale() === 'fr' ? 'fr-FR' : 'en-US', { day: "numeric", month: "short", year: "numeric" }); }, populateVaultFilter() { @@ -405,12 +405,12 @@ const DashboardRecentWidget = { if (localStorage.getItem('obsigate-qh-collapsed') === '1') { qhBody.classList.add('collapsed'); qhToggle.textContent = '+'; - qhToggle.title = 'Afficher'; + qhToggle.title = t('dashboard.show'); } qhToggle.addEventListener('click', function() { var collapsed = qhBody.classList.toggle('collapsed'); qhToggle.textContent = collapsed ? '+' : '\u2212'; - qhToggle.title = collapsed ? 'Afficher' : 'Masquer'; + qhToggle.title = collapsed ? t('dashboard.show') : t('dashboard.hide'); localStorage.setItem('obsigate-qh-collapsed', collapsed ? '1' : '0'); }); } diff --git a/frontend/locales/en.json b/frontend/locales/en.json index 651e31e..2d9bb8b 100644 --- a/frontend/locales/en.json +++ b/frontend/locales/en.json @@ -447,12 +447,29 @@ "conflict.resolve_conflict": "Keep conflict version", "conflict.resolve_local": "Keep local version", "conflict.resolved": "Conflict resolved", + "dashboard.all_vaults": "All vaults", + "dashboard.bookmark_add": "Add to bookmarks", + "dashboard.bookmark_remove": "Remove from bookmarks", "dashboard.bookmarks": "Bookmarks", + "dashboard.conflict_date": "Conflict of ", "dashboard.conflict_resolved": "Conflict resolved", "dashboard.conflicts": "Conflicts", + "dashboard.conflicts_title": "Sync conflicts", "dashboard.copy_btn": "Copy", + "dashboard.count_files": "file", + "dashboard.count_files_plural": "files", "dashboard.ctrl_hover_tip": "Hover over a document with Ctrl for a quick preview. Click Forge in the toolbar for the advanced editor.", + "dashboard.day_ago": "{n} d ago", + "dashboard.error_prefix": "Error: ", "dashboard.expires": "Expires {date}", + "dashboard.hide": "Hide", + "dashboard.hour_ago": "{n} h ago", + "dashboard.just_now": "just now", + "dashboard.keep_conflict": "Keep conflict", + "dashboard.keep_original": "Keep original", + "dashboard.load_error": "Loading error", + "dashboard.loading": "Loading...", + "dashboard.min_ago": "{n} min ago", "dashboard.no_bookmarks": "No bookmarks", "dashboard.no_conflicts": "No conflicts", "dashboard.no_recent": "No recent files", @@ -465,6 +482,11 @@ "dashboard.recent_hint": "Open a file to see it appear here", "dashboard.shared_hint": "Share a document to see it appear here", "dashboard.shares": "Shares", + "dashboard.show": "Show", + "dashboard.size_bytes": " B", + "dashboard.size_gb": " GB", + "dashboard.size_kb": " KB", + "dashboard.size_mb": " MB", "dashboard.stats": "Statistics", "dashboard.stats_files": "Files", "dashboard.stats_size": "Total size", @@ -479,6 +501,7 @@ "dashboard.vaults_count": "Vaults", "dashboard.views": "{count} view(s)", "dashboard.welcome": "Welcome to ObsiGate", + "dashboard.zero_files": "0 files", "dragdrop.cross_vault_unsupported": "Cross-vault moves are not supported", "dragdrop.move_failed": "Move failed", "editor.cancel": "Cancel", @@ -1213,6 +1236,17 @@ "share.never": "Never", "share.revoke": "Revoke", "share.title": "Public share", + "shortcut.ai_completion": "AI inline completion (in editor)", + "shortcut.close_editor": "Close editor / modal", + "shortcut.command_palette": "Command palette", + "shortcut.editor_help": "Forge editor help", + "shortcut.file_palette": "File palette (quick nav)", + "shortcut.focus_search": "Focus search bar", + "shortcut.quick_insert": "Quick insert (Forge editor)", + "shortcut.quick_search": "Quick search (outside text field)", + "shortcut.save_file": "Save open file", + "shortcut.search_in_doc": "Search in document", + "shortcut.tip_preview": "Hover a document with **Ctrl** for a quick preview. Click **Forge** in the toolbar for the advanced editor.", "sidebar.all_vaults": "All vaults", "sidebar.case_sensitive": "Case sensitive", "sidebar.clear_filter": "Clear", diff --git a/frontend/locales/fr.json b/frontend/locales/fr.json index dd95e85..ccb213c 100644 --- a/frontend/locales/fr.json +++ b/frontend/locales/fr.json @@ -447,12 +447,29 @@ "conflict.resolve_conflict": "Garder version conflit", "conflict.resolve_local": "Garder version locale", "conflict.resolved": "Conflit résolu", + "dashboard.all_vaults": "Tous les vaults", + "dashboard.bookmark_add": "Ajouter aux bookmarks", + "dashboard.bookmark_remove": "Retirer des bookmarks", "dashboard.bookmarks": "Favoris", + "dashboard.conflict_date": "Conflit du ", "dashboard.conflict_resolved": "Conflit résolu", "dashboard.conflicts": "Conflits", + "dashboard.conflicts_title": "Conflits de synchronisation", "dashboard.copy_btn": "Copier", + "dashboard.count_files": "fichier", + "dashboard.count_files_plural": "fichiers", "dashboard.ctrl_hover_tip": "Survolez un document avec Ctrl pour un aperçu rapide. Cliquez sur Forge dans la barre d'outils pour l'éditeur avancé.", + "dashboard.day_ago": "il y a {n} j", + "dashboard.error_prefix": "Erreur: ", "dashboard.expires": "Expire le {date}", + "dashboard.hide": "Masquer", + "dashboard.hour_ago": "il y a {n} h", + "dashboard.just_now": "à l'instant", + "dashboard.keep_conflict": "Garder le conflit", + "dashboard.keep_original": "Garder l'original", + "dashboard.load_error": "Erreur de chargement", + "dashboard.loading": "Chargement...", + "dashboard.min_ago": "il y a {n} min", "dashboard.no_bookmarks": "Aucun favori", "dashboard.no_conflicts": "Aucun conflit", "dashboard.no_recent": "Aucun fichier récent", @@ -465,6 +482,11 @@ "dashboard.recent_hint": "Ouvrez un fichier pour le voir apparaître ici", "dashboard.shared_hint": "Partagez un document pour le voir apparaître ici", "dashboard.shares": "Partages", + "dashboard.show": "Afficher", + "dashboard.size_bytes": " o", + "dashboard.size_gb": " Go", + "dashboard.size_kb": " Ko", + "dashboard.size_mb": " Mo", "dashboard.stats": "Statistiques", "dashboard.stats_files": "Fichiers", "dashboard.stats_size": "Taille totale", @@ -479,6 +501,7 @@ "dashboard.vaults_count": "Vaults", "dashboard.views": "{count} vue(s)", "dashboard.welcome": "Bienvenue dans ObsiGate", + "dashboard.zero_files": "0 fichiers", "dragdrop.cross_vault_unsupported": "Cross-vault moves are not supported", "dragdrop.move_failed": "Move failed", "editor.cancel": "Annuler", @@ -1213,6 +1236,17 @@ "share.never": "Jamais", "share.revoke": "Révoquer", "share.title": "Partage public", + "shortcut.ai_completion": "Completion IA inline (dans l'éditeur)", + "shortcut.close_editor": "Fermer l'éditeur / modale", + "shortcut.command_palette": "Palette de commandes", + "shortcut.editor_help": "Aide de l'éditeur Forge", + "shortcut.file_palette": "Palette de fichiers (nav. rapide)", + "shortcut.focus_search": "Focus barre de recherche", + "shortcut.quick_insert": "Insertion rapide (éditeur Forge)", + "shortcut.quick_search": "Recherche rapide (hors champ texte)", + "shortcut.save_file": "Sauvegarder le fichier ouvert", + "shortcut.search_in_doc": "Rechercher dans le document", + "shortcut.tip_preview": "Survolez un document avec **Ctrl** pour un aperçu rapide. Cliquez sur **Forge** dans la barre d'outils pour l'éditeur avancé.", "sidebar.all_vaults": "Tous les vaults", "sidebar.case_sensitive": "Respecter la casse", "sidebar.clear_filter": "Effacer",