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 = {
@@ -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",