fix: i18n for dashboard widgets + shortcuts — no more hardcoded French
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.
This commit is contained in:
+19
-19
@@ -21,18 +21,18 @@ const DashboardStatsWidget = {
|
||||
async load() {
|
||||
const grid = document.getElementById("dashboard-stats-grid");
|
||||
if (!grid) return;
|
||||
grid.innerHTML = '<div class="dashboard-stats-loading">Chargement...</div>';
|
||||
grid.innerHTML = `<div class="dashboard-stats-loading">${t('common.loading')}</div>`;
|
||||
try {
|
||||
const data = await api("/api/dashboard");
|
||||
this.render(data);
|
||||
} catch (err) {
|
||||
grid.innerHTML = `<div class="dashboard-recent-empty">Erreur: ${escapeHtml(err.message)}</div>`;
|
||||
grid.innerHTML = `<div class="dashboard-recent-empty">${t('dashboard.error_prefix')}${escapeHtml(err.message)}</div>`;
|
||||
}
|
||||
},
|
||||
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 = {
|
||||
<div class="dashboard-header">
|
||||
<div class="dashboard-title-row">
|
||||
<i data-lucide="alert-triangle" class="dashboard-icon" style="color:var(--accent-orange)"></i>
|
||||
<h2>Conflits de synchronisation</h2>
|
||||
<h2>${t('dashboard.conflicts_title')}</h2>
|
||||
<span class="dashboard-badge" style="background:var(--accent-orange)">${conflicts.length}</span>
|
||||
</div>
|
||||
</div>
|
||||
@@ -130,11 +130,11 @@ const DashboardConflictsWidget = {
|
||||
<div class="conflict-info">
|
||||
<span class="conflict-vault">${escapeHtml(c.vault)}</span>
|
||||
<span class="conflict-name">${escapeHtml(c.conflict_path.split("/").pop())}</span>
|
||||
<span class="conflict-date">Conflit du ${c.conflict_date.replace(/(\d{4})(\d{2})(\d{2})-(\d{2})(\d{2})/, "$3/$2/$1 $4:$5")}</span>
|
||||
<span class="conflict-date">${t('dashboard.conflict_date')}${c.conflict_date.replace(/(\d{4})(\d{2})(\d{2})-(\d{2})(\d{2})/, "$3/$2/$1 $4:$5")}</span>
|
||||
</div>
|
||||
<div class="conflict-actions">
|
||||
<button class="conflict-btn keep-local" data-vault="${escapeHtml(c.vault)}" data-conflict="${escapeHtml(c.conflict_path)}" data-original="${escapeHtml(c.original_path)}">Garder l'original</button>
|
||||
<button class="conflict-btn keep-conflict" data-vault="${escapeHtml(c.vault)}" data-conflict="${escapeHtml(c.conflict_path)}" data-original="${escapeHtml(c.original_path)}">Garder le conflit</button>
|
||||
<button class="conflict-btn keep-local" data-vault="${escapeHtml(c.vault)}" data-conflict="${escapeHtml(c.conflict_path)}" data-original="${escapeHtml(c.original_path)}">${t('dashboard.keep_original')}</button>
|
||||
<button class="conflict-btn keep-conflict" data-vault="${escapeHtml(c.vault)}" data-conflict="${escapeHtml(c.conflict_path)}" data-original="${escapeHtml(c.original_path)}">${t('dashboard.keep_conflict')}</button>
|
||||
</div>
|
||||
</div>
|
||||
`).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 = `<i data-lucide="${file.bookmarked ? "bookmark" : "bookmark-plus"}" style="width:14px;height:14px"></i>`;
|
||||
|
||||
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');
|
||||
});
|
||||
}
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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",
|
||||
|
||||
Reference in New Issue
Block a user