Replace hardcoded French strings with i18n calls
Initialize i18n before auth so t() works when rendering auth-dependent UI, and build the command palette lazily so translations are loaded first. Bump service worker cache version.
This commit is contained in:
+6
-4
@@ -23,12 +23,14 @@ import { initMermaid, setupFocusMode } from './mermaid-viewer.js';
|
||||
// Initialization — mirrors the original app.js init() ordering
|
||||
// =========================================================================
|
||||
async function init() {
|
||||
// 1. Init auth first — needed for server-side language preference
|
||||
const authOk = await Auth.AuthManager.initAuth();
|
||||
|
||||
// 2. Init i18n after auth so server language preference is available
|
||||
// 1. Init i18n FIRST — loads fallback (FR) + selected locale
|
||||
// Server language check may fail (no auth yet), falls to localStorage
|
||||
// LocalStorage has correct language if user set it previously
|
||||
await initI18n();
|
||||
|
||||
// 2. Init auth — now t() works inside showApp()/renderUserMenu()
|
||||
const authOk = await Auth.AuthManager.initAuth();
|
||||
|
||||
UI.initTheme();
|
||||
UI.initHeaderMenu();
|
||||
UI.initCustomDropdowns();
|
||||
|
||||
@@ -221,7 +221,7 @@ async function previewBackup(fpath) {
|
||||
var content = document.getElementById('bm-preview-content');
|
||||
var title = document.getElementById('bm-preview-title');
|
||||
panel.style.display = 'block';
|
||||
content.textContent = 'Chargement...';
|
||||
content.textContent = t("common.loading");
|
||||
|
||||
try {
|
||||
var data = await api('/api/backups/content?path=' + encodeURIComponent(fpath));
|
||||
|
||||
@@ -180,7 +180,7 @@ function renderMainView() {
|
||||
var html =
|
||||
'<div class="backup-header">' +
|
||||
'<div class="backup-header-left">' +
|
||||
'<h3>Backups</h3>' +
|
||||
'<h3>'+t('backups.title')+'</h3>' +
|
||||
'<span class="backup-file-path">' + escapeHtml(state.path) + '</span>' +
|
||||
'</div>' +
|
||||
'<div class="backup-header-right">' +
|
||||
|
||||
@@ -96,7 +96,7 @@ function renderRecentList(files) {
|
||||
|
||||
function _humanizeDelta(mtime) {
|
||||
const delta = Date.now() / 1000 - mtime;
|
||||
if (delta < 60) return "à l'instant";
|
||||
if (delta < 60) return t("config.just_now");
|
||||
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`;
|
||||
|
||||
+11
-11
@@ -88,8 +88,8 @@ export const GraphViewManager = {
|
||||
this._depth = depthSlider ? parseInt(depthSlider.value) : 1;
|
||||
this._scope = 'directory';
|
||||
|
||||
title.textContent = `Vue Graphique — ${vault}${path ? '/' + path : ''}`;
|
||||
statusEl.textContent = 'Chargement...';
|
||||
title.textContent = t('graph.title', { vault, path: path ? '/' + path : '' });
|
||||
statusEl.textContent = t('graph.loading');
|
||||
modal.classList.add('active');
|
||||
|
||||
this._canvas = canvas;
|
||||
@@ -120,8 +120,8 @@ export const GraphViewManager = {
|
||||
this._nodes = cached.nodes;
|
||||
this._edges = cached.edges;
|
||||
this._scope = cached.scope;
|
||||
const scopeLabel = this._scope === 'full' ? 'Vault complet' : 'Dossier';
|
||||
statusEl.textContent = `${this._nodes.length} nœuds, ${this._edges.length} liens · ${scopeLabel} · prof=${this._depth} (cache)`;
|
||||
const scopeLabel = this._scope === 'full' ? t('graph.scope_full') : t('graph.scope_directory');
|
||||
statusEl.textContent = `${t('graph.nodes_count', { count: this._nodes.length })}, ${t('graph.edges_count', { count: this._edges.length })} · ${scopeLabel} · ${t('graph.depth_label', { depth: this._depth })} ${t('graph.cache_label')}`;
|
||||
this._initLayout();
|
||||
this._startRender();
|
||||
return;
|
||||
@@ -149,12 +149,12 @@ export const GraphViewManager = {
|
||||
};
|
||||
this._cacheKey = cacheKey;
|
||||
|
||||
const scopeLabel = this._scope === 'full' ? 'Vault complet' : 'Dossier';
|
||||
statusEl.textContent = `${this._nodes.length} nœuds, ${this._edges.length} liens · ${scopeLabel} · prof=${this._depth}`;
|
||||
const scopeLabel = this._scope === 'full' ? t('graph.scope_full') : t('graph.scope_directory');
|
||||
statusEl.textContent = `${t('graph.nodes_count', { count: this._nodes.length })}, ${t('graph.edges_count', { count: this._edges.length })} · ${scopeLabel} · ${t('graph.depth_label', { depth: this._depth })}`;
|
||||
this._initLayout();
|
||||
this._startRender();
|
||||
} catch (err) {
|
||||
statusEl.textContent = 'Erreur de chargement';
|
||||
statusEl.textContent = t('graph.error_loading');
|
||||
console.error('Graph error:', err);
|
||||
}
|
||||
},
|
||||
@@ -173,7 +173,7 @@ export const GraphViewManager = {
|
||||
toggleScope() {
|
||||
this._scope = this._scope === 'full' ? 'directory' : 'full';
|
||||
const btn = document.getElementById('graph-full-vault');
|
||||
if (btn) btn.textContent = this._scope === 'full' ? '📁 Dossier' : '🌐 Tout';
|
||||
if (btn) btn.textContent = this._scope === 'full' ? t('graph.btn_directory') : t('graph.btn_full');
|
||||
this.reload();
|
||||
},
|
||||
|
||||
@@ -627,14 +627,14 @@ export const GraphViewManager = {
|
||||
if (fm.statut) rows.push(`<div><span style="color:var(--text-muted)">📌 Statut</span> <span>${fm.statut}</span></div>`);
|
||||
if (fm.catégorie || fm.categorie) rows.push(`<div><span style="color:var(--text-muted)">${t('graph.category')}</span> <span>${fm.catégorie || fm.categorie}</span></div>`);
|
||||
if (fm.publish) rows.push(`<div><span style="color:var(--text-muted)">✅</span> <span>${t('graph.published')}</span></div>`);
|
||||
if (fm.favoris) rows.push('<div><span style="color:var(--text-muted)">⭐</span> <span>Favoris</span></div>');
|
||||
if (fm.favoris) rows.push('<div><span style="color:var(--text-muted)">⭐</span> <span>' + t('graph.favorites') + '</span></div>');
|
||||
if (rows.length > 0) metaRows = rows.join('');
|
||||
}
|
||||
const tags = (meta?.tags || node.tags || []).slice(0, 6);
|
||||
const inc = node.incoming_count || 0;
|
||||
const out = node.outgoing_count || 0;
|
||||
const typeIcon = node.type === 'directory' ? '📁' : '📄';
|
||||
const typeLabel = node.type === 'directory' ? 'Dossier' : (node.path || '').endsWith('.md') ? 'Markdown' : 'Fichier';
|
||||
const typeLabel = node.type === 'directory' ? t('graph.type_directory') : (node.path || '').endsWith('.md') ? t('graph.type_markdown') : t('graph.type_file');
|
||||
|
||||
this._infoContent.innerHTML = `
|
||||
<div style="display:flex;align-items:flex-start;gap:8px;margin-bottom:8px;padding-right:16px">
|
||||
@@ -796,7 +796,7 @@ export const GraphViewManager = {
|
||||
return;
|
||||
}
|
||||
// Show loading indicator
|
||||
this._showPreviewTooltip(node, '<em>Chargement...</em>', screenX, screenY);
|
||||
this._showPreviewTooltip(node, '<em>' + t('common.loading') + '</em>', screenX, screenY);
|
||||
try {
|
||||
const data = await api(`/api/file/${encodeURIComponent(this._vault)}?path=${encodeURIComponent(node.path)}`);
|
||||
// Strip HTML tags, keep line breaks, limit to 600 chars
|
||||
|
||||
@@ -137,7 +137,7 @@ export function initMobileToolbar() {
|
||||
if (!pill) return;
|
||||
const vaultName = state.selectedContextVault || 'all';
|
||||
if (vaultName === 'all') {
|
||||
pill.textContent = '📂 Toutes les vaults';
|
||||
pill.textContent = t("mobile.all_vaults");
|
||||
} else {
|
||||
pill.textContent = '📂 ' + vaultName;
|
||||
}
|
||||
|
||||
+37
-32
@@ -33,22 +33,27 @@ let _browse = { action: null, vault: null, path: '' };
|
||||
let _browseFilterEl = null, _browseFilter = '', _allItems = [];
|
||||
let _browseFilterTimer = null; // debounce for global search
|
||||
|
||||
// ── Commands ──
|
||||
const CMDS = [
|
||||
{ id:'home', label:'🏠 Accueil', desc:"Retour à l'accueil", cat:'Navigation', act:()=>{close();triggerGoHome();} },
|
||||
{ id:'edit-current', label:'✏️ Éditer fichier courant', desc:'Ouvrir le fichier actif dans l\'éditeur', cat:'Fichiers', act:()=>{close();const f=getCurrentFile();if(f)openEditor(f.vault,f.path);else showToast(t('toast.no_open_file'),'error');} },
|
||||
{ id:'popout', label:'🪟 Pop-out', desc:'Ouvrir le document dans une fenêtre', cat:'Fichiers', act:()=>{close();const f=getCurrentFile();if(f)window.open(`/popout/${encodeURIComponent(f.vault)}/${encodeURIComponent(f.path)}`,'popout','width=1000,height=700');else showToast(t('toast.no_open_file'),'error');} },
|
||||
{ id:'create-file', label:'📄 Créer fichier markdown', desc:'Choisir la vault, naviguer, puis nommer le fichier', cat:'Fichiers', act:()=>startBrowse('create-file') },
|
||||
{ id:'delete-file', label:'🗑️ Supprimer fichier', desc:'Rechercher un fichier à supprimer', cat:'Fichiers', act:()=>startBrowse('delete-file') },
|
||||
{ id:'delete-cur', label:'🗑️ Supprimer fichier courant', desc:'Supprimer le fichier de l\'onglet actif', cat:'Fichiers', act:async()=>{close();await delCurFile();} },
|
||||
{ id:'close-cur', label:'✕ Fermer fichier courant', desc:'Fermer l\'onglet actif sans supprimer', cat:'Fichiers', act:()=>{close();const f=getCurrentFile();if(f){const tab=TabManager._tabs.find(t=>t.vault===f.vault&&t.path===f.path);if(tab)TabManager.close(tab.id);else triggerGoHome();}else{showToast(t('toast.no_open_file'),'error');}} },
|
||||
{ id:'create-dir', label:'📁 Créer répertoire', desc:'Choisir la vault, naviguer, puis nommer le dossier', cat:'Répertoires', act:()=>startBrowse('create-dir') },
|
||||
{ id:'delete-dir', label:'🗑️ Supprimer répertoire', desc:'Choisir la vault, naviguer et supprimer', cat:'Répertoires', act:()=>startBrowse('delete-dir') },
|
||||
{ id:'theme', label:'🌓 Changer le thème', desc:'Basculer clair/sombre', cat:'Actions', act:()=>{close();toggleTheme();} },
|
||||
{ id:'reindex', label:'🔄 Réindexer', desc:'Forcer la réindexation complète', cat:'Actions', act:async()=>{close();try{await api('/api/index/reload');showToast('Index rechargé','success');}catch{showToast(t('common.error'),'error');}} },
|
||||
{ id:'help', label:'❓ Aide', desc:'Ouvrir le guide', cat:'Système', act:()=>{close();const b=document.getElementById('help-open-btn');if(b)b.click();} },
|
||||
{ id:'config', label:'⚙️ Configuration', desc:'Ouvrir les paramètres', cat:'Système', act:()=>{close();const b=document.getElementById('config-open-btn');if(b)b.click();} },
|
||||
];
|
||||
// ── Commands ── (lazy: built on first access so i18n is ready)
|
||||
let _cmdsCache = null;
|
||||
function getCMDS() {
|
||||
if (_cmdsCache) return _cmdsCache;
|
||||
_cmdsCache = [
|
||||
{ id:'home', label:t('palette.cmd_back_home'), desc:t('palette.cmd_back_home_desc'), cat:'Navigation', act:()=>{close();triggerGoHome();} },
|
||||
{ id:'edit-current', label:'✏️ '+t('editor.edit'), desc:t('editor.edit_current_desc'), cat:'Fichiers', act:()=>{close();const f=getCurrentFile();if(f)openEditor(f.vault,f.path);else showToast(t('toast.no_open_file'),'error');} },
|
||||
{ id:'popout', label:'🪟 Pop-out', desc:t('palette.popout_desc'), cat:'Fichiers', act:()=>{close();const f=getCurrentFile();if(f)window.open(`/popout/${encodeURIComponent(f.vault)}/${encodeURIComponent(f.path)}`,'popout','width=1000,height=700');else showToast(t('toast.no_open_file'),'error');} },
|
||||
{ id:'create-file', label:t('palette.cmd_create_file'), desc:t('palette.cmd_create_file_desc'), cat:'Fichiers', act:()=>startBrowse('create-file') },
|
||||
{ id:'delete-file', label:'🗑️ '+t('file.delete'), desc:t('palette.delete_file_desc'), cat:'Fichiers', act:()=>startBrowse('delete-file') },
|
||||
{ id:'delete-cur', label:'🗑️ '+t('palette.delete_current'), desc:t('palette.delete_current_desc'), cat:'Fichiers', act:async()=>{close();await delCurFile();} },
|
||||
{ id:'close-cur', label:'✕ '+t('palette.close_current'), desc:t('palette.close_current_desc'), cat:'Fichiers', act:()=>{close();const f=getCurrentFile();if(f){const tab=TabManager._tabs.find(t=>t.vault===f.vault&&t.path===f.path);if(tab)TabManager.close(tab.id);else triggerGoHome();}else{showToast(t('toast.no_open_file'),'error');}} },
|
||||
{ id:'create-dir', label:t('palette.cmd_create_dir'), desc:t('palette.cmd_create_dir_desc'), cat:'Répertoires', act:()=>startBrowse('create-dir') },
|
||||
{ id:'delete-dir', label:t('palette.cmd_delete_dir'), desc:t('palette.cmd_delete_dir_desc'), cat:'Répertoires', act:()=>startBrowse('delete-dir') },
|
||||
{ id:'theme', label:t('palette.cmd_theme'), desc:t('palette.cmd_theme_desc'), cat:'Actions', act:()=>{close();toggleTheme();} },
|
||||
{ id:'reindex', label:'🔄 '+t('vault.reindex'), desc:t('palette.reindex_desc'), cat:'Actions', act:async()=>{close();try{await api('/api/index/reload');showToast(t('sync.index_reloaded'),'success');}catch{showToast(t('common.error'),'error');}} },
|
||||
{ id:'help', label:'❓ '+t('help.help_title'), desc:t('palette.help_desc'), cat:'Système', act:()=>{close();const b=document.getElementById('help-open-btn');if(b)b.click();} },
|
||||
{ id:'config', label:t('palette.cmd_config'), desc:t('palette.cmd_config_desc'), cat:'Système', act:()=>{close();const b=document.getElementById('config-open-btn');if(b)b.click();} },
|
||||
];
|
||||
return _cmdsCache;
|
||||
}
|
||||
|
||||
// ── Browse: vault picker ──
|
||||
function startBrowse(action) {
|
||||
@@ -62,13 +67,13 @@ async function renderVaultPicker() {
|
||||
try {
|
||||
const data = await api('/api/vaults');
|
||||
const vaults = Array.isArray(data) ? data : [];
|
||||
_items = vaults.map(v => ({ type:'_vault', vault: v.name, label: (v.type==='DIR'?'📂':'🗂️')+' '+v.name, sublabel: v.file_count+' fichiers' }));
|
||||
_items = vaults.map(v => ({ type:'_vault', vault: v.name, label: (v.type==='DIR'?'📂':'🗂️')+' '+v.name, sublabel: t('palette.vault_count', {count: v.file_count}) }));
|
||||
if (_items.length === 0) {
|
||||
_items = [{ type:'_empty', label: 'Aucune vault trouvée', sublabel: '' }];
|
||||
_items = [{ type:'_empty', label: t('palette.no_vaults'), sublabel: '' }];
|
||||
}
|
||||
_allItems = _items;
|
||||
render();
|
||||
} catch { _items = [{ type:'_error', label: 'Erreur de chargement', sublabel: '' }]; _allItems = _items; render(); }
|
||||
} catch { _items = [{ type:'_error', label: t('palette.error_loading'), sublabel: '' }]; _allItems = _items; render(); }
|
||||
}
|
||||
|
||||
// ── Browse: directory navigation ──
|
||||
@@ -95,11 +100,11 @@ async function renderBrowse() {
|
||||
|
||||
// Action row
|
||||
const actLabel = {
|
||||
'create-file':'📄 Créer fichier ici',
|
||||
'create-dir':'📁 Créer dossier ici',
|
||||
'delete-dir':'🗑️ Supprimer ce dossier',
|
||||
'delete-file':'🗑️ Supprimer un fichier dans ce dossier',
|
||||
'open-file':'📂 Ouvrir un fichier dans ce dossier'
|
||||
'create-file': t('palette.cmd_create_file'),
|
||||
'create-dir': t('palette.cmd_create_dir'),
|
||||
'delete-dir': t('palette.cmd_delete_dir'),
|
||||
'delete-file': t('palette.delete_file_desc'),
|
||||
'open-file': t('palette.browse_open_file')
|
||||
};
|
||||
const isDeleteDir = _browse.action === 'delete-dir' && path;
|
||||
const isDeleteFile = _browse.action === 'delete-file';
|
||||
@@ -107,9 +112,9 @@ async function renderBrowse() {
|
||||
const needsName = _browse.action === 'create-file' || _browse.action === 'create-dir';
|
||||
|
||||
if (isDeleteDir) {
|
||||
_items.push({ type:'_action', label: '🗑️ Supprimer '+ (path.split('/').pop()||path), sublabel: 'Tout le contenu sera supprimé', act:()=>execDelDir(path) });
|
||||
_items.push({ type:'_action', label: '🗑️ '+t('file.delete')+' '+(path.split('/').pop()||path), sublabel: t('palette.dir_delete_confirm'), act:()=>execDelDir(path) });
|
||||
} else if (needsName) {
|
||||
_items.push({ type:'_action', label: actLabel[_browse.action]||'', sublabel: 'Dans '+(path||'racine'), act:()=>askName() });
|
||||
_items.push({ type:'_action', label: actLabel[_browse.action]||'', sublabel: t('palette.browse_in', {path: path||t('palette.browse_root')}), act:()=>askName() });
|
||||
}
|
||||
|
||||
// Parent
|
||||
@@ -135,8 +140,8 @@ async function renderBrowse() {
|
||||
}
|
||||
}
|
||||
|
||||
if (_items.length === 0) _items.push({ type:'_empty', label: '📂 Dossier vide', sublabel: '' });
|
||||
} catch { _items = [{ type:'_error', label: 'Erreur', sublabel: '' }]; }
|
||||
if (_items.length === 0) _items.push({ type:'_empty', label: t('palette.empty_dir'), sublabel: '' });
|
||||
} catch { _items = [{ type:'_error', label: t('common.error'), sublabel: '' }]; }
|
||||
|
||||
_allItems = _items;
|
||||
applyBrowseFilter();
|
||||
@@ -178,7 +183,7 @@ async function searchBrowseGlobal(rawQ) {
|
||||
});
|
||||
|
||||
if (sug.length === 0) {
|
||||
_items = [{ type:'_empty', label: 'Aucun résultat pour "'+rawQ+'"', sublabel: '' }];
|
||||
_items = [{ type:'_empty', label: t('palette.no_results', {query: rawQ}), sublabel: '' }];
|
||||
render();
|
||||
return;
|
||||
}
|
||||
@@ -220,7 +225,7 @@ async function searchBrowseGlobal(rawQ) {
|
||||
}
|
||||
|
||||
render();
|
||||
} catch { _items = [{ type:'_error', label: 'Erreur de recherche', sublabel: '' }]; render(); }
|
||||
} catch { _items = [{ type:'_error', label: t('palette.search_error'), sublabel: '' }]; render(); }
|
||||
}
|
||||
|
||||
// Navigate to a directory from global search
|
||||
@@ -501,9 +506,9 @@ async function searchFiles(rawQ) {
|
||||
}
|
||||
|
||||
function searchCmd(q) {
|
||||
if (!q) { _items = CMDS.map(c => ({ type:'cmd', ...c })); render(); return; }
|
||||
if (!q) { _items = getCMDS().map(c => ({ type:'cmd', ...c })); render(); return; }
|
||||
const lq = q.toLowerCase();
|
||||
_items = CMDS.filter(c => c.label.toLowerCase().includes(lq)||c.desc.toLowerCase().includes(lq)||(c.cat&&c.cat.toLowerCase().includes(lq))).map(c => ({ type:'cmd', ...c }));
|
||||
_items = getCMDS().filter(c => c.label.toLowerCase().includes(lq)||c.desc.toLowerCase().includes(lq)||(c.cat&&c.cat.toLowerCase().includes(lq))).map(c => ({ type:'cmd', ...c }));
|
||||
render();
|
||||
}
|
||||
|
||||
|
||||
@@ -847,7 +847,7 @@ export function renderSearchResults(data, query, tagFilter) {
|
||||
const header = buildSearchResultsHeader(data, query, tagFilter);
|
||||
area.appendChild(header);
|
||||
if (data.results.length === 0) {
|
||||
area.appendChild(el("p", { style: "color:var(--text-muted);margin-top:20px" }, [document.createTextNode("Aucun résultat trouvé.")]));
|
||||
area.appendChild(el("p", { style: "color:var(--text-muted);margin-top:20px" }, [document.createTextNode(t("search.no_results"))]));
|
||||
return;
|
||||
}
|
||||
const container = el("div", { class: "search-results" });
|
||||
@@ -965,7 +965,7 @@ export function renderAdvancedSearchResults(data, query, tagFilter) {
|
||||
header.appendChild(sortDiv);
|
||||
|
||||
// Save search button
|
||||
const saveBtn = el("button", { class: "search-save-btn", type: "button", title: "Sauvegarder cette recherche" });
|
||||
const saveBtn = el("button", { class: "search-save-btn", type: "button", title: t("search.save_search") });
|
||||
saveBtn.innerHTML = '<i data-lucide="bookmark-plus" style="width:14px;height:14px"></i> Sauver';
|
||||
saveBtn.addEventListener("click", async () => {
|
||||
const inclEl = document.getElementById("search-include-input");
|
||||
@@ -1063,7 +1063,7 @@ export function renderAdvancedSearchResults(data, query, tagFilter) {
|
||||
|
||||
// Empty state
|
||||
if (data.results.length === 0) {
|
||||
area.appendChild(el("p", { style: "color:var(--text-muted);margin-top:20px" }, [document.createTextNode("Aucun résultat trouvé.")]));
|
||||
area.appendChild(el("p", { style: "color:var(--text-muted);margin-top:20px" }, [document.createTextNode(t("search.no_results"))]));
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -788,7 +788,7 @@ function renderFilteredSidebarResults(query, results) {
|
||||
});
|
||||
|
||||
if (grouped.size === 0) {
|
||||
container.appendChild(el("div", { class: "sidebar-filter-empty" }, [document.createTextNode("Aucun répertoire ou fichier correspondant.")]));
|
||||
container.appendChild(el("div", { class: "sidebar-filter-empty" }, [document.createTextNode(t("sidebar.no_results"))]));
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -757,7 +757,7 @@ function renderFilteredSidebarResults(query, results) {
|
||||
});
|
||||
|
||||
if (grouped.size === 0) {
|
||||
container.appendChild(el("div", { class: "sidebar-filter-empty" }, [document.createTextNode("Aucun répertoire ou fichier correspondant.")]));
|
||||
container.appendChild(el("div", { class: "sidebar-filter-empty" }, [document.createTextNode(t("sidebar.no_results"))]));
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
+3
-3
@@ -319,7 +319,7 @@ function _renderSyncPanel(panel) {
|
||||
const label = typeLabels[ev.type] || ev.type;
|
||||
let detail = ev.data.vaults ? ev.data.vaults.join(", ") : ev.data.vault || "";
|
||||
if (ev.type === "index_start") detail = `${ev.data.total_vaults} vaults à traiter`;
|
||||
if (ev.type === "index_progress") detail = `${ev.data.vault} (${ev.data.files} fichiers)`;
|
||||
if (ev.type === "index_progress") detail = t("sync.vault_files", {vault: ev.data.vault, files: ev.data.files});
|
||||
if (ev.type === "index_complete" && ev.data.total_files !== undefined) detail = `${ev.data.total_files} fichiers total`;
|
||||
html += `<div class="sync-panel__event">
|
||||
<span class="sync-panel__event-type">${label}</span>
|
||||
@@ -367,7 +367,7 @@ function _renderAIStatusSection(panel) {
|
||||
let extIcon, extText, extClass;
|
||||
if (_aiProcessing) {
|
||||
extIcon = 'loader';
|
||||
extText = 'Traitement en cours…';
|
||||
extText = t('sync.processing');
|
||||
extClass = 'sync-panel__ai--processing';
|
||||
} else if (_aiConfigured === true) {
|
||||
extIcon = 'check-circle';
|
||||
@@ -375,7 +375,7 @@ function _renderAIStatusSection(panel) {
|
||||
extClass = 'sync-panel__ai--active';
|
||||
} else if (_aiConfigured === false) {
|
||||
extIcon = 'x-circle';
|
||||
extText = 'Aucun fournisseur';
|
||||
extText = t('sync.no_provider');
|
||||
extClass = 'sync-panel__ai--inactive';
|
||||
} else {
|
||||
extIcon = 'help-circle';
|
||||
|
||||
+3
-3
@@ -1701,9 +1701,9 @@ export const ContextMenuManager = {
|
||||
this._addItem('edit', 'Renommer', () => this._renameItem(), isReadonly);
|
||||
this._addItem('trash-2', 'Supprimer', () => this._deleteFile(), isReadonly);
|
||||
this._addSeparator();
|
||||
this._addItem('bookmark-plus', 'Ajouter aux bookmarks', () => this._toggleBookmark(), false);
|
||||
this._addItem('bookmark-plus', t("viewer.bookmark_add"), () => this._toggleBookmark(), false);
|
||||
this._addSeparator();
|
||||
this._addItem('history', 'Backups / Versions', () => this._openBackupViewer(), false);
|
||||
this._addItem('history', t("ui.backups_versions"), () => this._openBackupViewer(), false);
|
||||
}
|
||||
|
||||
this._menu.classList.add('active');
|
||||
@@ -1750,7 +1750,7 @@ export const ContextMenuManager = {
|
||||
callback();
|
||||
});
|
||||
} else {
|
||||
item.title = 'Vault en lecture seule';
|
||||
item.title = t("ui.vault_readonly");
|
||||
}
|
||||
|
||||
this._menu.appendChild(item);
|
||||
|
||||
+51
-31
@@ -2,9 +2,9 @@
|
||||
* Vault Home Page module for ObsiGate.
|
||||
*
|
||||
* When a specific vault is selected (not "All"), replaces the dashboard
|
||||
* with a recursive file listing sorted by modification time (newest first).
|
||||
* Files from the selected directory AND all its subdirectories are shown
|
||||
* with their relative path displayed in the metadata line.
|
||||
* with a non-recursive file listing sorted by modification time (newest first).
|
||||
* Only files from the selected directory are shown (not subdirectories)
|
||||
* to keep the listing fast and lightweight.
|
||||
* The listing updates automatically when browsing into subdirectories.
|
||||
*
|
||||
* The visual style mirrors the search results (.search-result-item) for
|
||||
@@ -18,6 +18,7 @@ import { api } from './auth.js';
|
||||
import { el } from './viewer.js';
|
||||
import { getFileIcon, safeCreateIcons } from './utils.js';
|
||||
import { TabManager } from './ui.js';
|
||||
import { t, getLocale } from './i18n.js';
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// State
|
||||
@@ -77,7 +78,7 @@ export async function showVaultHome(vaultName, dirPath = '') {
|
||||
resultsArea.innerHTML = `
|
||||
<div class="tree-loading" style="padding:2rem;text-align:center">
|
||||
<div class="loading-spinner" style="width:24px;height:24px;border-width:3px;margin:0 auto"></div>
|
||||
<p style="margin-top:0.75rem;color:var(--text-muted);font-size:0.85rem">Chargement des fichiers...</p>
|
||||
<p data-i18n="vaulthome.loading" style="margin-top:0.75rem;color:var(--text-muted);font-size:0.85rem">${t('vaulthome.loading')}</p>
|
||||
</div>`;
|
||||
|
||||
await loadAndRender(vaultName, state.currentDir, resultsArea);
|
||||
@@ -110,6 +111,10 @@ export async function updateVaultHomeDir(vaultName, dirPath) {
|
||||
safeCreateIcons();
|
||||
}
|
||||
|
||||
// Remove recent section when navigating into subdirectory
|
||||
const recentSection = container.querySelector('.vault-home-recent');
|
||||
if (recentSection) recentSection.remove();
|
||||
|
||||
// Reload results
|
||||
const resultsArea = document.getElementById('vault-home-results');
|
||||
if (resultsArea) {
|
||||
@@ -125,9 +130,31 @@ export async function updateVaultHomeDir(vaultName, dirPath) {
|
||||
// Tree click delegation — update vault home on directory clicks
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
let _treeDelegationInstalled = false;
|
||||
|
||||
function _initTreeDelegation() {
|
||||
if (_treeDelegationInstalled) return;
|
||||
|
||||
const tree = document.getElementById('vault-tree');
|
||||
if (!tree) return;
|
||||
if (!tree) {
|
||||
// Retry once when DOM might not be ready — use MutationObserver as fallback
|
||||
const observer = new MutationObserver(() => {
|
||||
const t = document.getElementById('vault-tree');
|
||||
if (t) {
|
||||
observer.disconnect();
|
||||
_attachTreeListener(t);
|
||||
}
|
||||
});
|
||||
observer.observe(document.body, { childList: true, subtree: true });
|
||||
return;
|
||||
}
|
||||
|
||||
_attachTreeListener(tree);
|
||||
}
|
||||
|
||||
function _attachTreeListener(tree) {
|
||||
if (_treeDelegationInstalled) return;
|
||||
_treeDelegationInstalled = true;
|
||||
|
||||
tree.addEventListener('click', (e) => {
|
||||
if (!state.active) return;
|
||||
@@ -192,14 +219,14 @@ function buildBreadcrumbHTML(parentEl, vaultName, dirPath) {
|
||||
|
||||
async function loadAndRender(vaultName, dirPath, container) {
|
||||
try {
|
||||
const url = `/api/vault/${encodeURIComponent(vaultName)}/files?dir=${encodeURIComponent(dirPath)}&limit=200&recursive=true`;
|
||||
const url = `/api/vault/${encodeURIComponent(vaultName)}/files?dir=${encodeURIComponent(dirPath)}&limit=200&recursive=false`;
|
||||
const data = await api(url);
|
||||
|
||||
if (!data.files || data.files.length === 0) {
|
||||
container.innerHTML = `
|
||||
<div class="vault-home-empty">
|
||||
<i data-lucide="folder-open" style="width:32px;height:32px;color:var(--text-muted)"></i>
|
||||
<p>Aucun fichier dans ce répertoire</p>
|
||||
<p data-i18n="vaulthome.empty">${t('vaulthome.empty')}</p>
|
||||
</div>`;
|
||||
safeCreateIcons();
|
||||
return;
|
||||
@@ -207,21 +234,15 @@ async function loadAndRender(vaultName, dirPath, container) {
|
||||
|
||||
// Header
|
||||
const header = el('div', { class: 'vault-home-header' });
|
||||
const count = el('span', { class: 'vault-home-count' }, [
|
||||
document.createTextNode(`${data.files.length} fichier${data.files.length > 1 ? 's' : ''}`),
|
||||
const countKey = data.files.length > 1 ? 'vaulthome.file_count_plural' : 'vaulthome.file_count';
|
||||
const countStr = t(countKey, { count: data.files.length });
|
||||
const count = el('span', { class: 'vault-home-count', 'data-i18n': countKey }, [
|
||||
document.createTextNode(countStr),
|
||||
]);
|
||||
header.appendChild(count);
|
||||
|
||||
// Recursive indicator
|
||||
if (data.recursive) {
|
||||
const recursiveBadge = el('span', { class: 'vault-home-recursive-badge' }, [
|
||||
document.createTextNode('récursif'),
|
||||
]);
|
||||
header.appendChild(recursiveBadge);
|
||||
}
|
||||
|
||||
// Directory label
|
||||
const dirLabel = dirPath ? `/${dirPath}` : ' (racine)';
|
||||
const dirLabel = dirPath ? `/${dirPath}` : ` ${t('common.root')}`;
|
||||
const dirInfo = el('span', { class: 'vault-home-dir-info' }, [
|
||||
document.createTextNode(dirLabel),
|
||||
]);
|
||||
@@ -232,28 +253,26 @@ async function loadAndRender(vaultName, dirPath, container) {
|
||||
|
||||
// File list — using search-result-item style
|
||||
const list = el('div', { class: 'search-results' });
|
||||
const locale = getLocale();
|
||||
|
||||
data.files.forEach((f) => {
|
||||
const fileIconName = getFileIcon ? getFileIcon(f.name) : 'file';
|
||||
const displayName = f.name.match(/\.md$/i) ? f.name.replace(/\.md$/i, '') : f.name;
|
||||
const displayName = f.name.endsWith('.md') ? f.name.slice(0, -3) : f.name;
|
||||
const ext = f.extension || '';
|
||||
|
||||
const titleDiv = el('div', { class: 'search-result-title' }, [
|
||||
document.createTextNode(displayName),
|
||||
]);
|
||||
|
||||
// Format date
|
||||
// Format date using current locale
|
||||
const modDate = new Date(f.modified * 1000);
|
||||
const dateStr = modDate.toLocaleDateString('fr-CA', {
|
||||
const dateStr = modDate.toLocaleDateString(locale === 'fr' ? 'fr-CA' : 'en-CA', {
|
||||
year: 'numeric', month: 'short', day: 'numeric',
|
||||
hour: '2-digit', minute: '2-digit',
|
||||
});
|
||||
|
||||
// Build metadata line: rel_dir (if any) + date + size
|
||||
// Build metadata line: date + size
|
||||
const metaParts = [];
|
||||
if (f.rel_dir) {
|
||||
metaParts.push(f.rel_dir + '/');
|
||||
}
|
||||
metaParts.push(dateStr);
|
||||
metaParts.push(formatSize(f.size));
|
||||
|
||||
@@ -284,9 +303,10 @@ async function loadAndRender(vaultName, dirPath, container) {
|
||||
container.appendChild(list);
|
||||
safeCreateIcons();
|
||||
} catch (err) {
|
||||
const errMsg = t('vaulthome.error_loading') + ' ' + escapeHtml(err?.detail || err?.message || t('common.unknown'));
|
||||
container.innerHTML = `
|
||||
<div class="vault-home-error">
|
||||
<p>Erreur de chargement: ${escapeHtml(err?.detail || err?.message || 'Inconnue')}</p>
|
||||
<p data-i18n="vaulthome.error_loading">${errMsg}</p>
|
||||
</div>`;
|
||||
}
|
||||
}
|
||||
@@ -308,13 +328,13 @@ async function loadRecentSection(vaultName, container) {
|
||||
const header = el('div', { class: 'vault-home-recent-header' });
|
||||
header.innerHTML = `
|
||||
<i data-lucide="clock" style="width:14px;height:14px"></i>
|
||||
<span>Récents</span>`;
|
||||
<span data-i18n="dashboard.recent">${t('dashboard.recent')}</span>`;
|
||||
section.appendChild(header);
|
||||
|
||||
const list = el('div', { class: 'vault-home-recent-list' });
|
||||
files.forEach((f) => {
|
||||
const title = f.title || f.path.split('/').pop() || '';
|
||||
const displayTitle = title.match(/\.md$/i) ? title.replace(/\.md$/i, '') : title;
|
||||
const displayTitle = title.endsWith('.md') ? title.slice(0, -3) : title;
|
||||
const dir = f.path.includes('/') ? f.path.split('/').slice(0, -1).join('/') + '/' : '';
|
||||
|
||||
const item = el('div', { class: 'vault-home-recent-item' });
|
||||
@@ -352,9 +372,9 @@ async function loadRecentSection(vaultName, container) {
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
function formatSize(bytes) {
|
||||
if (bytes < 1024) return bytes + ' o';
|
||||
if (bytes < 1024 * 1024) return (bytes / 1024).toFixed(1) + ' Ko';
|
||||
return (bytes / (1024 * 1024)).toFixed(1) + ' Mo';
|
||||
if (bytes < 1024) return bytes + ' ' + t('vaulthome.size_bytes');
|
||||
if (bytes < 1024 * 1024) return (bytes / 1024).toFixed(1) + ' ' + t('vaulthome.size_kb');
|
||||
return (bytes / (1024 * 1024)).toFixed(1) + ' ' + t('vaulthome.size_mb');
|
||||
}
|
||||
|
||||
function escapeHtml(str) {
|
||||
|
||||
+13
-13
@@ -499,7 +499,7 @@ export function renderFile(data) {
|
||||
const sourceBtn = el("button", { class: "btn-action", title: "Voir la source" }, [icon("code", 14), document.createTextNode("Source")]);
|
||||
|
||||
// MD download button
|
||||
const mdBtn = el("button", { class: "btn-action", title: "Télécharger en .md" }, [icon("file-text", 14), document.createTextNode(".md")]);
|
||||
const mdBtn = el("button", { class: "btn-action", title: t("viewer.download_md") }, [icon("file-text", 14), document.createTextNode(".md")]);
|
||||
mdBtn.addEventListener("click", () => {
|
||||
const dlUrl = `/api/file/${encodeURIComponent(data.vault)}/download?path=${encodeURIComponent(data.path)}`;
|
||||
const a = document.createElement("a");
|
||||
@@ -511,7 +511,7 @@ export function renderFile(data) {
|
||||
});
|
||||
|
||||
// PDF download button
|
||||
const pdfBtn = el("button", { class: "btn-action", title: "Télécharger en PDF" }, [icon("file", 14), document.createTextNode("PDF")]);
|
||||
const pdfBtn = el("button", { class: "btn-action", title: t("viewer.download_pdf") }, [icon("file", 14), document.createTextNode("PDF")]);
|
||||
pdfBtn.addEventListener("click", () => {
|
||||
const pdfUrl = `/api/file/${encodeURIComponent(data.vault)}/pdf?path=${encodeURIComponent(data.path)}`;
|
||||
window.open(pdfUrl, "_blank");
|
||||
@@ -522,7 +522,7 @@ export function renderFile(data) {
|
||||
openEditor(data.vault, data.path);
|
||||
});
|
||||
|
||||
const forgeBtn = el("button", { class: "btn-action btn-forge", title: "Forge (nouvel editeur)" }, [icon("hammer", 14), document.createTextNode("Forge")]);
|
||||
const forgeBtn = el("button", { class: "btn-action btn-forge", title: t("viewer.forge_title") }, [icon("hammer", 14), document.createTextNode("Forge")]);
|
||||
forgeBtn.addEventListener("click", () => {
|
||||
var modal = document.getElementById("editor-modal");
|
||||
var container = modal.querySelector(".editor-container");
|
||||
@@ -534,7 +534,7 @@ export function renderFile(data) {
|
||||
var brand = modal.querySelector(".editor-brand");
|
||||
var titleInp = document.getElementById("editor-title-input");
|
||||
var fileInp = document.getElementById("editor-filename-input");
|
||||
if (brand) brand.textContent = "Forge";
|
||||
if (brand) brand.textContent = t("viewer.forge_brand");
|
||||
if (titleInp) { titleInp.value = data.title || ''; titleInp.placeholder = t('forge.title_placeholder'); }
|
||||
if (fileInp) fileInp.value = data.path.split('/').pop();
|
||||
bodyEl.innerHTML = "";
|
||||
@@ -574,14 +574,14 @@ export function renderFile(data) {
|
||||
shareBtn.addEventListener("click", () => openShareDialog(data.vault, data.path));
|
||||
|
||||
// Bookmark button — check if already bookmarked
|
||||
const bookmarkBtn = el("button", { class: "btn-action btn-bookmark", title: "Ajouter/Retirer des bookmarks" }, [icon("bookmark-plus", 14), document.createTextNode("Bookmark")]);
|
||||
const bookmarkBtn = el("button", { class: "btn-action btn-bookmark", title: t("viewer.bookmark_toggle") }, [icon("bookmark-plus", 14), document.createTextNode("Bookmark")]);
|
||||
// Check bookmark status and color the button
|
||||
(async () => {
|
||||
try {
|
||||
const bms = await api("/api/bookmarks");
|
||||
if (Array.isArray(bms) && bms.some(b => b.vault === data.vault && b.path === data.path)) {
|
||||
bookmarkBtn.classList.add("active");
|
||||
bookmarkBtn.title = "Retirer des bookmarks";
|
||||
bookmarkBtn.title = t("viewer.bookmark_remove");
|
||||
}
|
||||
} catch (e) { /* ignore */ }
|
||||
})();
|
||||
@@ -589,7 +589,7 @@ export function renderFile(data) {
|
||||
try {
|
||||
const res = await api("/api/bookmarks/toggle", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ vault: data.vault, path: data.path, title: data.title }) });
|
||||
bookmarkBtn.classList.toggle("active", res.bookmarked);
|
||||
bookmarkBtn.title = res.bookmarked ? "Retirer des bookmarks" : "Ajouter aux bookmarks";
|
||||
bookmarkBtn.title = res.bookmarked ? t("viewer.bookmark_remove") : t("viewer.bookmark_add");
|
||||
showToast(res.bookmarked ? "Ajouté aux bookmarks" : "Retiré des bookmarks", "success");
|
||||
if (typeof DashboardBookmarkWidget !== "undefined") DashboardBookmarkWidget.load();
|
||||
} catch (err) { showToast("Erreur: " + err.message, "error"); }
|
||||
@@ -1351,7 +1351,7 @@ const IndexUpdateManager = (() => {
|
||||
disconnected: "Déconnecté",
|
||||
connecting: "Connexion...",
|
||||
connected: "Synchronisé",
|
||||
syncing: "Mise à jour...",
|
||||
syncing: t("viewer.syncing"),
|
||||
};
|
||||
badge.title = labels[connectionState] || connectionState;
|
||||
}
|
||||
@@ -1444,12 +1444,12 @@ function _renderSyncPanel(panel) {
|
||||
events.slice(0, 10).forEach((ev) => {
|
||||
const time = new Date(ev.timestamp).toLocaleTimeString();
|
||||
const typeLabels = {
|
||||
index_updated: "Mise à jour",
|
||||
index_updated: t("viewer.index_updated"),
|
||||
index_reloaded: "Rechargement",
|
||||
vault_added: "Vault ajouté",
|
||||
vault_removed: "Vault supprimé",
|
||||
index_start: "Démarrage index.",
|
||||
index_progress: "Vault indexé",
|
||||
vault_added: t("sync.vault_added_label"),
|
||||
vault_removed: t("sync.vault_removed_label"),
|
||||
index_start: t("viewer.index_start"),
|
||||
index_progress: t("sync.vault_indexed_label"),
|
||||
index_complete: "Indexation tech.",
|
||||
};
|
||||
const label = typeLabels[ev.type] || ev.type;
|
||||
|
||||
+139
-37
@@ -104,7 +104,9 @@
|
||||
"auth.login_title": "Secure access to your vaults",
|
||||
"auth.logout_title": "Sign out",
|
||||
"auth.network_error": "Network error — check your connection",
|
||||
"auth.new_password": "New password (empty = unchanged)",
|
||||
"auth.password": "Password",
|
||||
"auth.password_min": "Min. 8 characters",
|
||||
"auth.remember_me": "Remember me (30 days)",
|
||||
"auth.session_expired": "Session expired, please sign in again",
|
||||
"auth.user_deleted": "User deleted",
|
||||
@@ -201,6 +203,14 @@
|
||||
"backup.timestamp_not_found": "Cannot find backup timestamp",
|
||||
"backup.title": "Backups",
|
||||
"backup.version": "Version from {date}",
|
||||
"backups.delete_confirm": "Delete this backup?",
|
||||
"backups.empty": "No backups available for this file.",
|
||||
"backups.hint": "Backups are created automatically before each modification.",
|
||||
"backups.loading": "Loading backups...",
|
||||
"backups.purge_file": "Delete ALL backups of",
|
||||
"backups.purge_vault": "Delete ALL backups from vault",
|
||||
"backups.restore_confirm": "to the selected backup version?\nThe current version will be saved.",
|
||||
"backups.title": "Backups",
|
||||
"button.cancel": "Cancel",
|
||||
"common.actions": "Actions",
|
||||
"common.all": "All",
|
||||
@@ -225,8 +235,10 @@
|
||||
"common.previous": "Previous",
|
||||
"common.refresh": "Refresh",
|
||||
"common.rename": "Rename",
|
||||
"common.root": "(root)",
|
||||
"common.save": "Save",
|
||||
"common.search": "Search",
|
||||
"common.unknown": "Unknown",
|
||||
"common.yes": "Yes",
|
||||
"config.about": "About",
|
||||
"config.about_error": "Loading error",
|
||||
@@ -252,23 +264,25 @@
|
||||
"config.error_unknown": "Unknown error",
|
||||
"config.force_reindex": "Force reindex",
|
||||
"config.hidden_files": "Hidden files",
|
||||
"config.hidden_files_desc": "Manage display of hidden files and folders.",
|
||||
"config.hidden_files_desc": "Hide files/folders starting with a dot in the interface (they remain indexed and searchable)",
|
||||
"config.hidden_files_toggle": "Hide hidden files/folders",
|
||||
"config.hidden_include_label": "Include hidden files",
|
||||
"config.hidden_whitelist_label": "Whitelist (comma-separated)",
|
||||
"config.hint_activer_d_sactiver_la_surveillance_automatique_des": "Activer/désactiver la surveillance automatique des fichiers",
|
||||
"config.hint_activer_d_sactiver_la_surveillance_automatique_des": "Enable/disable automatic file monitoring",
|
||||
"config.hint_annuler_la_recherche_apr_s_ce_d_lai_5000_120000_": "Cancel search after this delay (5000-120000)",
|
||||
"config.hint_contenu_index_par_fichier_10k_1m_r_indexation_requ": "Max content size per file (bytes)",
|
||||
"config.hint_d_lai_avant_ex_cution_de_la_recherche_100_2000_": "Delay before search execution (100-2000)",
|
||||
"config.hint_d_lai_avant_traitement_des_changements_group_s_0_5": "Délai avant traitement des changements groupés (0.5-10 secondes)",
|
||||
"config.hint_d_lai_avant_traitement_des_changements_group_s_0_5": "Delay before processing grouped changes (0.5-10 seconds)",
|
||||
"config.hint_entre_5_et_100_fichiers_sauvegarde_sur_le_serveur_": "Between 5 and 100 files (stored on server)",
|
||||
"config.hint_forcer_le_mode_polling_au_lieu_de_inotify_natif_ut": "Forcer le mode polling au lieu de inotify natif (utile si le mode natif ne fonctionne pas)",
|
||||
"config.hint_intervalle_de_scrutation_en_mode_polling_1_30_seco": "Intervalle de scrutation en mode polling (1-30 secondes)",
|
||||
"config.hint_multiplicateur_de_pertinence_pour_les_correspondan": "Multiplicateur de pertinence pour les correspondances dans le titre",
|
||||
"config.hint_nombre_de_r_sultats_affich_s_par_page_10_200_": "Number of results displayed per page (10-200)",
|
||||
"config.hint_nombre_max_de_tokens_largis_par_pr_fixe_10_200_": "Nombre max de tokens élargis par préfixe (10-200)",
|
||||
"config.hint_nombre_max_de_tokens_largis_par_pr_fixe_10_200_": "Max expanded tokens per prefix (10-200)",
|
||||
"config.hint_nombre_maximum_de_versions_backup_conservees_par_f": "Maximum backup versions kept per file (1-50)",
|
||||
"config.hint_nombre_minimum_de_caract_res_avant_recherche_1_5_": "Minimum characters before search triggers (1-5)",
|
||||
"config.hint_threads_d_di_s_la_recherche_1_8_": "Threads dédiés à la recherche (1-8)",
|
||||
"config.hint_threads_d_di_s_la_recherche_1_8_": "Dedicated search threads (1-8)",
|
||||
"config.just_now": "just now",
|
||||
"config.lang_hint": "Used by autocomplete and ghost text.",
|
||||
"config.lang_label": "Preferred language",
|
||||
"config.link_copied": "Link copied!",
|
||||
@@ -314,9 +328,9 @@
|
||||
"config.search_workers": "Search workers",
|
||||
"config.search_workers_hint": "Dedicated search threads (1-8)",
|
||||
"config.search_workers_label": "Search workers",
|
||||
"config.section_a-propos": "📦 À propos",
|
||||
"config.section_a-propos": "📦 About",
|
||||
"config.section_about": "About",
|
||||
"config.section_actions-sur-fichiers": "Actions sur fichiers",
|
||||
"config.section_actions-sur-fichiers": "File actions",
|
||||
"config.section_activation": "Activation",
|
||||
"config.section_affichage": "Affichage",
|
||||
"config.section_ai": "AI API keys",
|
||||
@@ -324,56 +338,56 @@
|
||||
"config.section_astuces-et-bonnes-pratiques": "💡 Astuces et bonnes pratiques",
|
||||
"config.section_audit-log": "Audit log",
|
||||
"config.section_authentification": "Authentification",
|
||||
"config.section_autocompletion": "Autocomplétion",
|
||||
"config.section_autocompletion": "Autocompletion",
|
||||
"config.section_backend": "🖥️ Backend Settings",
|
||||
"config.section_backup-automatique": "Backup automatique",
|
||||
"config.section_backups": "Backups",
|
||||
"config.section_barre-d-outils-ai": "Barre d'outils AI",
|
||||
"config.section_breadcrumb-et-repositionnement": "Breadcrumb et repositionnement",
|
||||
"config.section_cas-d-usage": "Cas d'usage",
|
||||
"config.section_cas-d-usage-avances": "Cas d'usage avancés",
|
||||
"config.section_cas-d-usage-avances": "Advanced use cases",
|
||||
"config.section_chips-de-filtres-actifs": "Chips de filtres actifs",
|
||||
"config.section_cles-api-intelligence-artificielle": "🤖 Cles API Intelligence Artificielle",
|
||||
"config.section_configuration": "Configuration",
|
||||
"config.section_configuration-avancee": "Configuration avancée",
|
||||
"config.section_configuration-avancee": "Advanced configuration",
|
||||
"config.section_construit-avec": "Construit avec",
|
||||
"config.section_diag": "Diagnostics",
|
||||
"config.section_diagnostics": "Diagnostics",
|
||||
"config.section_editeur-codemirror": "Éditeur CodeMirror",
|
||||
"config.section_editeur-codemirror-6": "Éditeur CodeMirror 6",
|
||||
"config.section_edition-avancee": "✏️ Édition avancée",
|
||||
"config.section_edition-avec-codemirror-6": "Édition avec CodeMirror 6",
|
||||
"config.section_en-tete": "En-tête",
|
||||
"config.section_evenements-supportes": "Événements supportés",
|
||||
"config.section_editeur-codemirror": "CodeMirror Editor",
|
||||
"config.section_editeur-codemirror-6": "CodeMirror 6 Editor",
|
||||
"config.section_edition-avancee": "✏️ Advanced Editing",
|
||||
"config.section_edition-avec-codemirror-6": "Editing with CodeMirror 6",
|
||||
"config.section_en-tete": "Header",
|
||||
"config.section_evenements-supportes": "Supported events",
|
||||
"config.section_exemples-concrets": "Exemples concrets",
|
||||
"config.section_facettes-et-tri": "Facettes et tri",
|
||||
"config.section_fichiers": "📄 Fichiers",
|
||||
"config.section_fichiers": "📄 Files",
|
||||
"config.section_filtrage-de-la-sidebar": "Filtrage de la sidebar",
|
||||
"config.section_filtrage-de-tags": "Filtrage de tags",
|
||||
"config.section_filtrage-de-tags-template": "Filtrage de tags template",
|
||||
"config.section_fonctionnalites": "Fonctionnalités",
|
||||
"config.section_fonctionnalites": "Features",
|
||||
"config.section_format-du-payload": "Format du payload",
|
||||
"config.section_gestion-des-onglets": "📑 Gestion des onglets",
|
||||
"config.section_hidden": "🗂️ Hidden Files",
|
||||
"config.section_historique-recent-redemarrage-non-requis": "📋 Historique récent\n Redémarrage non requis",
|
||||
"config.section_hidden": "Hidden files",
|
||||
"config.section_historique-recent-redemarrage-non-requis": "📋 Recent History\n No restart required",
|
||||
"config.section_indicateurs-visuels": "Indicateurs visuels",
|
||||
"config.section_intelligence-artificielle-dans-l-editeur": "🤖 Intelligence Artificielle dans l'Éditeur",
|
||||
"config.section_intelligence-artificielle-dans-l-editeur": "🤖 AI in the Editor",
|
||||
"config.section_interaction": "Interaction",
|
||||
"config.section_interface": "Interface",
|
||||
"config.section_interface-utilisateur": "🧭 Interface utilisateur",
|
||||
"config.section_limitations-actuelles": "Limitations actuelles",
|
||||
"config.section_mode-commandes": "Mode commandes",
|
||||
"config.section_mode-fichiers": "Mode fichiers",
|
||||
"config.section_mode-fichiers": "File mode",
|
||||
"config.section_navigation": "Navigation",
|
||||
"config.section_navigation-entre-onglets": "Navigation entre onglets",
|
||||
"config.section_onglets": "Onglets",
|
||||
"config.section_operateurs-avances": "Opérateurs avancés",
|
||||
"config.section_operateurs-avances": "Advanced operators",
|
||||
"config.section_optimisations": "Optimisations",
|
||||
"config.section_ouverture": "Ouverture",
|
||||
"config.section_ouverture-d-onglets": "Ouverture d'onglets",
|
||||
"config.section_palette-de-commandes": "⌨️ Palette de commandes",
|
||||
"config.section_parametres-backend-redemarrage-requis": "Paramètres backend\n Redémarrage requis",
|
||||
"config.section_parametres-de-recherche": "Paramètres de recherche",
|
||||
"config.section_parametres-backend-redemarrage-requis": "Backend settings\n Restart required",
|
||||
"config.section_parametres-de-recherche": "Search settings",
|
||||
"config.section_partage-et-webhooks": "🔗 Partage et Webhooks",
|
||||
"config.section_partages-publics": "📤 Partages publics",
|
||||
"config.section_perf": "⚡ Performance",
|
||||
@@ -382,36 +396,36 @@
|
||||
"config.section_profil-utilisateur": "👤 Profil utilisateur",
|
||||
"config.section_profile": "User profile",
|
||||
"config.section_protection": "Protection",
|
||||
"config.section_providers-supportes": "Providers supportés",
|
||||
"config.section_providers-supportes": "Supported providers",
|
||||
"config.section_publication-publique": "Publication publique",
|
||||
"config.section_raccourcis-clavier": "⌨️ Raccourcis clavier",
|
||||
"config.section_recent": "📜 Recent History",
|
||||
"config.section_recherche": "🔍 Recherche",
|
||||
"config.section_recherche-et-autocompletion": "Recherche et autocomplétion",
|
||||
"config.section_recherche-et-autocompletion": "Search and autocompletion",
|
||||
"config.section_recherche-simple": "Recherche simple",
|
||||
"config.section_redimensionnement-de-la-sidebar": "Redimensionnement de la sidebar",
|
||||
"config.section_sauvegarde-automatique": "Sauvegarde automatique",
|
||||
"config.section_sauvegardes-et-audits": "💾 Sauvegardes et Audits",
|
||||
"config.section_search": "Search settings",
|
||||
"config.section_securite": "🛡️ Sécurité",
|
||||
"config.section_securite-signature-hmac-sha256": "Sécurité : signature HMAC-SHA256",
|
||||
"config.section_selection-de-vault": "Sélection de vault",
|
||||
"config.section_securite": "🛡️ Security",
|
||||
"config.section_securite-signature-hmac-sha256": "Security: HMAC-SHA256 signature",
|
||||
"config.section_selection-de-vault": "Vault selection",
|
||||
"config.section_server": "Server",
|
||||
"config.section_shares": "📤 Public Shares",
|
||||
"config.section_sidebar-barre-laterale": "Sidebar (barre latérale)",
|
||||
"config.section_sidebar-barre-laterale": "Sidebar",
|
||||
"config.section_synchronisation-automatique": "Synchronisation automatique",
|
||||
"config.section_tag-cloud": "Tag cloud",
|
||||
"config.section_tags": "🏷️ Tag Filtering",
|
||||
"config.section_tags-inline-vs-frontmatter": "Tags inline vs frontmatter",
|
||||
"config.section_theme-clair-sombre": "Thème clair/sombre",
|
||||
"config.section_themes": "🎨 Thèmes",
|
||||
"config.section_theme-clair-sombre": "Light/Dark theme",
|
||||
"config.section_themes": "🎨 Themes",
|
||||
"config.section_trucs-et-astuces": "Trucs et astuces",
|
||||
"config.section_types-de-fichiers-supportes": "Types de fichiers supportés",
|
||||
"config.section_types-de-fichiers-supportes": "Supported file types",
|
||||
"config.section_visualisation": "Visualisation",
|
||||
"config.section_vue-graphe": "🗺️ Vue Graphe",
|
||||
"config.section_watcher": "Auto sync",
|
||||
"config.section_webhooks": "🔗 Webhooks",
|
||||
"config.section_workflow-recommande": "Workflow recommandé",
|
||||
"config.section_workflow-recommande": "Recommended workflow",
|
||||
"config.section_zone-de-contenu": "Zone de contenu",
|
||||
"config.server_config": "Server config",
|
||||
"config.settings_saved": "✓ Settings saved",
|
||||
@@ -506,6 +520,9 @@
|
||||
"dragdrop.move_failed": "Move failed",
|
||||
"editor.cancel": "Cancel",
|
||||
"editor.close": "Close",
|
||||
"editor.delete_error": "Delete error",
|
||||
"editor.edit": "Edit current file",
|
||||
"editor.edit_current_desc": "Open current file in editor",
|
||||
"editor.find": "Find in file...",
|
||||
"editor.find_case": "Case sensitive",
|
||||
"editor.find_regex": "Regex",
|
||||
@@ -515,6 +532,7 @@
|
||||
"editor.no_results": "No results",
|
||||
"editor.replace": "Replace",
|
||||
"editor.save": "Save",
|
||||
"editor.save_error": "Save error",
|
||||
"editor.saved": "Saved ✓",
|
||||
"editor.unsaved": "Unsaved changes",
|
||||
"error.initialization": "Initialization error",
|
||||
@@ -529,22 +547,35 @@
|
||||
"forge.popout_label": "pop-out",
|
||||
"forge.title_placeholder": "Title...",
|
||||
"graph.back": "Back",
|
||||
"graph.btn_directory": "📁 Directory",
|
||||
"graph.btn_full": "🌐 All",
|
||||
"graph.cache_label": "(cached)",
|
||||
"graph.category": "📂 Category",
|
||||
"graph.click_to_open": "click to open",
|
||||
"graph.ctrl_hover_preview": "Ctrl+hover = full preview",
|
||||
"graph.ctrl_hover_preview_short": "Ctrl+hover = preview",
|
||||
"graph.depth": "Depth",
|
||||
"graph.depth_label": "depth={depth}",
|
||||
"graph.edges_count": "{count} links",
|
||||
"graph.error_loading": "Loading error",
|
||||
"graph.export_png": "Export PNG",
|
||||
"graph.favorites": "Favorites",
|
||||
"graph.filter_tag": "Filter by tag",
|
||||
"graph.filter_type": "Filter by type",
|
||||
"graph.focus_mode": "Focus mode",
|
||||
"graph.forward": "Forward",
|
||||
"graph.fullscreen": "Full screen",
|
||||
"graph.loading": "Building graph...",
|
||||
"graph.nodes_count": "{count} nodes",
|
||||
"graph.parent": "Parent",
|
||||
"graph.published": "Published",
|
||||
"graph.published_badge": "✅ published",
|
||||
"graph.title": "Graph",
|
||||
"graph.scope_directory": "Directory",
|
||||
"graph.scope_full": "Full vault",
|
||||
"graph.title": "Graph View — {vault}{path}",
|
||||
"graph.type_directory": "Directory",
|
||||
"graph.type_file": "File",
|
||||
"graph.type_markdown": "Markdown",
|
||||
"header.admin_panel": "Administration",
|
||||
"header.config": "Settings",
|
||||
"header.help": "Help",
|
||||
@@ -972,6 +1003,7 @@
|
||||
"help.guide_official": "Official guide",
|
||||
"help.hamburger_btn": "Hamburger menu button",
|
||||
"help.header_section": "Header",
|
||||
"help.help_title": "Help",
|
||||
"help.hide": "Hide",
|
||||
"help.hide_help": "Hide help",
|
||||
"help.highlighted_snippets": "Highlighted snippets",
|
||||
@@ -1131,6 +1163,7 @@
|
||||
"mermaid.preview": "Preview",
|
||||
"mermaid.zoom_in": "Zoom in",
|
||||
"mermaid.zoom_out": "Zoom out",
|
||||
"mobile.all_vaults": "📂 All vaults",
|
||||
"modal.create_btn": "Create",
|
||||
"modal.create_file": "Create a file",
|
||||
"modal.creating": "Creating...",
|
||||
@@ -1166,10 +1199,50 @@
|
||||
"offline.reconnected": "Connection restored — synchronizing...",
|
||||
"offline.status": "Offline",
|
||||
"offline.sync_now": "Sync now",
|
||||
"palette.browse_dirs": "📂 Browse directories...",
|
||||
"palette.browse_hint": "Navigate vaults to find a file",
|
||||
"palette.browse_in": "In {path}",
|
||||
"palette.browse_no_results": "No results — browse manually",
|
||||
"palette.browse_open_file": "📂 Open a file in this directory",
|
||||
"palette.browse_root": "root",
|
||||
"palette.close_current": "Close current file",
|
||||
"palette.close_current_desc": "Close active tab without deleting",
|
||||
"palette.cmd_back_home": "🏠 Home",
|
||||
"palette.cmd_back_home_desc": "Back to home",
|
||||
"palette.cmd_config": "⚙️ Settings",
|
||||
"palette.cmd_config_desc": "Open settings",
|
||||
"palette.cmd_create_dir": "📁 Create directory",
|
||||
"palette.cmd_create_dir_desc": "Choose vault, navigate, then name the directory",
|
||||
"palette.cmd_create_file": "📄 Create markdown file",
|
||||
"palette.cmd_create_file_desc": "Choose vault, navigate, then name the file",
|
||||
"palette.cmd_delete_dir": "🗑️ Delete directory",
|
||||
"palette.cmd_delete_dir_desc": "Choose vault, navigate and delete",
|
||||
"palette.cmd_theme": "🌓 Toggle theme",
|
||||
"palette.cmd_theme_desc": "Toggle light/dark",
|
||||
"palette.del_all_content": "All content will be deleted",
|
||||
"palette.delete_current": "Delete current file",
|
||||
"palette.delete_current_desc": "Delete file from active tab",
|
||||
"palette.delete_file_desc": "Search for a file to delete",
|
||||
"palette.dir_delete_confirm": "All content will be deleted",
|
||||
"palette.dir_name": "Directory name",
|
||||
"palette.empty_dir": "📂 Empty directory",
|
||||
"palette.error_loading": "Loading error",
|
||||
"palette.error_prefix": "Error: {msg}",
|
||||
"palette.file_name": "File name",
|
||||
"palette.help_desc": "Open the guide",
|
||||
"palette.md_hint": "(.md added if needed)",
|
||||
"palette.mode_commands": "Commands",
|
||||
"palette.mode_files": "Files",
|
||||
"palette.no_results": "No results for \"{query}\"",
|
||||
"palette.no_vaults": "No vaults found",
|
||||
"palette.popout_desc": "Open document in a window",
|
||||
"palette.reindex_desc": "Force full reindex",
|
||||
"palette.search_commands": "Type a command...",
|
||||
"palette.search_error": "Search error",
|
||||
"palette.search_files": "Search files...",
|
||||
"palette.type_command": "Type a command...",
|
||||
"palette.type_search": "Search files... (+include -exclude)",
|
||||
"palette.vault_count": "{count} files",
|
||||
"pwa.dismiss": "Later",
|
||||
"pwa.install_button": "Install",
|
||||
"pwa.install_desc": "Install this app on your device for quick access.",
|
||||
@@ -1258,7 +1331,7 @@
|
||||
"sidebar.filter_results_grouped": "Grouped results",
|
||||
"sidebar.loading": "Loading...",
|
||||
"sidebar.no_recent_files": "No recent files",
|
||||
"sidebar.no_results": "No results",
|
||||
"sidebar.no_results": "No matching directory or file.",
|
||||
"sidebar.no_saved_searches": "No saved searches",
|
||||
"sidebar.open_file": "Open file",
|
||||
"sidebar.saved_dirs_tab": "Folders",
|
||||
@@ -1287,17 +1360,25 @@
|
||||
"sync.index_started": "Indexing started ({count} vaults)",
|
||||
"sync.install_success": "ObsiGate installed successfully!",
|
||||
"sync.model_not_loaded": "Model not loaded",
|
||||
"sync.no_provider": "No provider",
|
||||
"sync.no_recent_events": "No recent events",
|
||||
"sync.not_configured": "Not configured",
|
||||
"sync.processing": "Processing…",
|
||||
"sync.update": "Update",
|
||||
"sync.updating": "Updating...",
|
||||
"sync.vault_added": "Vault \"{vault}\" added ({count} files)",
|
||||
"sync.vault_added_label": "Vault added",
|
||||
"sync.vault_files": "{vault} ({files} files)",
|
||||
"sync.vault_indexed_label": "Vault indexed",
|
||||
"sync.vault_removed": "Vault \"{vault}\" removed",
|
||||
"sync.vault_removed_label": "Vault removed",
|
||||
"sync.verifying": "Verifying…",
|
||||
"theme.change": "Change theme",
|
||||
"theme.dark": "Dark",
|
||||
"theme.light": "Light",
|
||||
"theme.title": "Theme",
|
||||
"themes.name_gradients": "Subtle gradients",
|
||||
"themes.name_terminal": "Pure black & green",
|
||||
"toast.ai_keys_saved": "API keys saved",
|
||||
"toast.ai_no_key": "No keys to save",
|
||||
"toast.bookmark_added": "Added to bookmarks",
|
||||
@@ -1351,22 +1432,42 @@
|
||||
"tree.new_file": "New file",
|
||||
"tree.new_folder": "New folder",
|
||||
"tree.vault_home": "Vault home",
|
||||
"ui.backups_versions": "Backups / Versions",
|
||||
"ui.cannot_rename": "Cannot rename this item",
|
||||
"ui.delete_name_empty": "Name cannot be empty",
|
||||
"ui.element_not_found": "Element not found in tree",
|
||||
"ui.vault_readonly": "Read-only vault",
|
||||
"vault.add_dynamic": "Add vault",
|
||||
"vault.reindex": "Reindex vault",
|
||||
"vault.remove_dynamic": "Remove vault",
|
||||
"vaulthome.empty": "No files in this directory",
|
||||
"vaulthome.error_loading": "Loading error:",
|
||||
"vaulthome.file_count": "{count} file",
|
||||
"vaulthome.file_count_plural": "{count} files",
|
||||
"vaulthome.loading": "Loading files...",
|
||||
"vaulthome.size_bytes": "B",
|
||||
"vaulthome.size_kb": "KB",
|
||||
"vaulthome.size_mb": "MB",
|
||||
"viewer.backlinks": "Backlinks",
|
||||
"viewer.binary_download": "Download file",
|
||||
"viewer.binary_unsupported": "Unsupported binary file",
|
||||
"viewer.bookmark_add": "Add to bookmarks",
|
||||
"viewer.bookmark_remove": "Remove bookmarks",
|
||||
"viewer.bookmark_toggle": "Add/Remove bookmarks",
|
||||
"viewer.breadcrumb_home": "Home",
|
||||
"viewer.click_to_download": "Click to download",
|
||||
"viewer.copied": "Copied!",
|
||||
"viewer.copy": "Copy",
|
||||
"viewer.copy_error": "Copy error",
|
||||
"viewer.download": "Download",
|
||||
"viewer.download_md": "Download as .md",
|
||||
"viewer.download_pdf": "Download as PDF",
|
||||
"viewer.edit": "Edit",
|
||||
"viewer.error": "Loading error",
|
||||
"viewer.forge_brand": "Forge",
|
||||
"viewer.forge_title": "Forge (new editor)",
|
||||
"viewer.index_start": "Starting index...",
|
||||
"viewer.index_updated": "Updated",
|
||||
"viewer.loaded_from_cache": "File loaded from offline cache",
|
||||
"viewer.loading": "Loading file...",
|
||||
"viewer.markdown": "Markdown",
|
||||
@@ -1385,6 +1486,7 @@
|
||||
"viewer.share": "Share",
|
||||
"viewer.shared_doc_title": "Shared document — click to manage",
|
||||
"viewer.source": "Source",
|
||||
"viewer.syncing": "Updating...",
|
||||
"viewer.toc": "Table of contents",
|
||||
"viewer.unsupported_file": "This file is binary and cannot be displayed",
|
||||
"webhook.trigger_create": "Creation via API or palette",
|
||||
|
||||
+105
-3
@@ -104,7 +104,9 @@
|
||||
"auth.login_title": "Accès sécurisé à vos vaults",
|
||||
"auth.logout_title": "Déconnexion",
|
||||
"auth.network_error": "Erreur réseau — vérifiez votre connexion",
|
||||
"auth.new_password": "Nouveau mot de passe (vide = inchangé)",
|
||||
"auth.password": "Mot de passe",
|
||||
"auth.password_min": "Min. 8 caracteres",
|
||||
"auth.remember_me": "Se souvenir de moi (30 jours)",
|
||||
"auth.session_expired": "Session expirée, veuillez vous reconnecter",
|
||||
"auth.user_deleted": "Utilisateur supprimé",
|
||||
@@ -201,6 +203,14 @@
|
||||
"backup.timestamp_not_found": "Impossible de trouver le timestamp du backup",
|
||||
"backup.title": "Sauvegardes",
|
||||
"backup.version": "Version du {date}",
|
||||
"backups.delete_confirm": "Supprimer ce backup ?",
|
||||
"backups.empty": "Aucun backup disponible pour ce fichier.",
|
||||
"backups.hint": "Les backups sont crees automatiquement avant chaque modification.",
|
||||
"backups.loading": "Chargement des backups...",
|
||||
"backups.purge_file": "Supprimer TOUS les backups de",
|
||||
"backups.purge_vault": "Supprimer TOUS les backups du vault",
|
||||
"backups.restore_confirm": "a la version du backup selectionne ?\nLa version actuelle sera sauvegardee.",
|
||||
"backups.title": "Backups",
|
||||
"button.cancel": "Annuler",
|
||||
"common.actions": "Actions",
|
||||
"common.all": "Tous",
|
||||
@@ -225,8 +235,10 @@
|
||||
"common.previous": "Précédent",
|
||||
"common.refresh": "Rafraîchir",
|
||||
"common.rename": "Renommer",
|
||||
"common.root": "(racine)",
|
||||
"common.save": "Enregistrer",
|
||||
"common.search": "Rechercher",
|
||||
"common.unknown": "Inconnue",
|
||||
"common.yes": "Oui",
|
||||
"config.about": "À propos",
|
||||
"config.about_error": "Erreur de chargement",
|
||||
@@ -252,7 +264,8 @@
|
||||
"config.error_unknown": "Erreur inconnue",
|
||||
"config.force_reindex": "Forcer réindexation",
|
||||
"config.hidden_files": "Fichiers cachés",
|
||||
"config.hidden_files_desc": "Gérez l'affichage des fichiers et dossiers cachés.",
|
||||
"config.hidden_files_desc": "Masquer les fichiers/dossiers commencant par un point dans l'interface (ils restent indexes et cherchables)",
|
||||
"config.hidden_files_toggle": "Masquer les fichiers/dossiers caches",
|
||||
"config.hidden_include_label": "Inclure les fichiers cachés",
|
||||
"config.hidden_whitelist_label": "Whitelist (séparés par des virgules)",
|
||||
"config.hint_activer_d_sactiver_la_surveillance_automatique_des": "Activer/désactiver la surveillance automatique des fichiers",
|
||||
@@ -269,6 +282,7 @@
|
||||
"config.hint_nombre_maximum_de_versions_backup_conservees_par_f": "Nombre maximum de versions backup conservees par fichier (1-50)",
|
||||
"config.hint_nombre_minimum_de_caract_res_avant_recherche_1_5_": "Nombre minimum de caractères avant recherche (1-5)",
|
||||
"config.hint_threads_d_di_s_la_recherche_1_8_": "Threads dédiés à la recherche (1-8)",
|
||||
"config.just_now": "a l'instant",
|
||||
"config.lang_hint": "Utilisée par l'autocomplétion et le ghost text.",
|
||||
"config.lang_label": "Langue préférée",
|
||||
"config.link_copied": "Lien copié !",
|
||||
@@ -506,6 +520,9 @@
|
||||
"dragdrop.move_failed": "Move failed",
|
||||
"editor.cancel": "Annuler",
|
||||
"editor.close": "Fermer",
|
||||
"editor.delete_error": "Erreur de suppression",
|
||||
"editor.edit": "Éditer fichier courant",
|
||||
"editor.edit_current_desc": "Ouvrir le fichier actif dans l'éditeur",
|
||||
"editor.find": "Rechercher dans le fichier...",
|
||||
"editor.find_case": "Respecter la casse",
|
||||
"editor.find_regex": "Regex",
|
||||
@@ -515,6 +532,7 @@
|
||||
"editor.no_results": "Aucun résultat",
|
||||
"editor.replace": "Remplacer",
|
||||
"editor.save": "Enregistrer",
|
||||
"editor.save_error": "Erreur de sauvegarde",
|
||||
"editor.saved": "Sauvegardé ✓",
|
||||
"editor.unsaved": "Modifications non sauvegardées",
|
||||
"error.initialization": "Erreur lors de l'initialisation",
|
||||
@@ -529,22 +547,35 @@
|
||||
"forge.popout_label": "pop-out",
|
||||
"forge.title_placeholder": "Titre...",
|
||||
"graph.back": "Retour",
|
||||
"graph.btn_directory": "📁 Dossier",
|
||||
"graph.btn_full": "🌐 Tout",
|
||||
"graph.cache_label": "(cache)",
|
||||
"graph.category": "📂 Catégorie",
|
||||
"graph.click_to_open": "cliquer pour ouvrir",
|
||||
"graph.ctrl_hover_preview": "Ctrl+survol = aperçu complet",
|
||||
"graph.ctrl_hover_preview_short": "Ctrl+survol = aperçu",
|
||||
"graph.depth": "Profondeur",
|
||||
"graph.depth_label": "prof={depth}",
|
||||
"graph.edges_count": "{count} liens",
|
||||
"graph.error_loading": "Erreur de chargement",
|
||||
"graph.export_png": "Exporter PNG",
|
||||
"graph.favorites": "Favoris",
|
||||
"graph.filter_tag": "Filtrer par tag",
|
||||
"graph.filter_type": "Filtrer par type",
|
||||
"graph.focus_mode": "Mode focus",
|
||||
"graph.forward": "Avancer",
|
||||
"graph.fullscreen": "Plein écran",
|
||||
"graph.loading": "Construction du graphe...",
|
||||
"graph.nodes_count": "{count} nœuds",
|
||||
"graph.parent": "Parent",
|
||||
"graph.published": "Publié",
|
||||
"graph.published_badge": "✅ publié",
|
||||
"graph.title": "Graphe",
|
||||
"graph.scope_directory": "Dossier",
|
||||
"graph.scope_full": "Vault complet",
|
||||
"graph.title": "Vue Graphique — {vault}{path}",
|
||||
"graph.type_directory": "Dossier",
|
||||
"graph.type_file": "Fichier",
|
||||
"graph.type_markdown": "Markdown",
|
||||
"header.admin_panel": "Administration",
|
||||
"header.config": "Configuration",
|
||||
"header.help": "Aide",
|
||||
@@ -972,6 +1003,7 @@
|
||||
"help.guide_official": "Guide officiel",
|
||||
"help.hamburger_btn": "Bouton menu hamburger",
|
||||
"help.header_section": "En-tête",
|
||||
"help.help_title": "Aide",
|
||||
"help.hide": "Masquage",
|
||||
"help.hide_help": "Masquer l'aide",
|
||||
"help.highlighted_snippets": "Snippets surlignés",
|
||||
@@ -1131,6 +1163,7 @@
|
||||
"mermaid.preview": "Aperçu",
|
||||
"mermaid.zoom_in": "Zoom avant",
|
||||
"mermaid.zoom_out": "Zoom arrière",
|
||||
"mobile.all_vaults": "📂 Toutes les vaults",
|
||||
"modal.create_btn": "Créer",
|
||||
"modal.create_file": "Créer un fichier",
|
||||
"modal.creating": "Création...",
|
||||
@@ -1166,10 +1199,50 @@
|
||||
"offline.reconnected": "Connexion rétablie — synchronisation en cours...",
|
||||
"offline.status": "Hors-ligne",
|
||||
"offline.sync_now": "Synchroniser maintenant",
|
||||
"palette.browse_dirs": "📂 Parcourir les répertoires...",
|
||||
"palette.browse_hint": "Naviguer dans les vaults pour trouver un fichier",
|
||||
"palette.browse_in": "Dans {path}",
|
||||
"palette.browse_no_results": "Aucun résultat — naviguer manuellement",
|
||||
"palette.browse_open_file": "📂 Ouvrir un fichier dans ce dossier",
|
||||
"palette.browse_root": "racine",
|
||||
"palette.close_current": "Fermer fichier courant",
|
||||
"palette.close_current_desc": "Fermer l'onglet actif sans supprimer",
|
||||
"palette.cmd_back_home": "🏠 Accueil",
|
||||
"palette.cmd_back_home_desc": "Retour à l'accueil",
|
||||
"palette.cmd_config": "⚙️ Configuration",
|
||||
"palette.cmd_config_desc": "Ouvrir les paramètres",
|
||||
"palette.cmd_create_dir": "📁 Créer répertoire",
|
||||
"palette.cmd_create_dir_desc": "Choisir la vault, naviguer, puis nommer le dossier",
|
||||
"palette.cmd_create_file": "📄 Créer fichier markdown",
|
||||
"palette.cmd_create_file_desc": "Choisir la vault, naviguer, puis nommer le fichier",
|
||||
"palette.cmd_delete_dir": "🗑️ Supprimer répertoire",
|
||||
"palette.cmd_delete_dir_desc": "Choisir la vault, naviguer et supprimer",
|
||||
"palette.cmd_theme": "🌓 Changer le thème",
|
||||
"palette.cmd_theme_desc": "Basculer clair/sombre",
|
||||
"palette.del_all_content": "Tout le contenu sera supprimé",
|
||||
"palette.delete_current": "Supprimer fichier courant",
|
||||
"palette.delete_current_desc": "Supprimer le fichier de l'onglet actif",
|
||||
"palette.delete_file_desc": "Rechercher un fichier à supprimer",
|
||||
"palette.dir_delete_confirm": "Tout le contenu sera supprimé",
|
||||
"palette.dir_name": "Nom du dossier",
|
||||
"palette.empty_dir": "📂 Dossier vide",
|
||||
"palette.error_loading": "Erreur de chargement",
|
||||
"palette.error_prefix": "Erreur : {msg}",
|
||||
"palette.file_name": "Nom du fichier",
|
||||
"palette.help_desc": "Ouvrir le guide",
|
||||
"palette.md_hint": "(.md ajouté si besoin)",
|
||||
"palette.mode_commands": "Commandes",
|
||||
"palette.mode_files": "Fichiers",
|
||||
"palette.no_results": "Aucun résultat pour \"{query}\"",
|
||||
"palette.no_vaults": "Aucune vault trouvée",
|
||||
"palette.popout_desc": "Ouvrir le document dans une fenêtre",
|
||||
"palette.reindex_desc": "Forcer la réindexation complète",
|
||||
"palette.search_commands": "Tapez une commande...",
|
||||
"palette.search_error": "Erreur de recherche",
|
||||
"palette.search_files": "Rechercher un fichier...",
|
||||
"palette.type_command": "Tapez une commande...",
|
||||
"palette.type_search": "Rechercher un fichier... (+inclure -exclure)",
|
||||
"palette.vault_count": "{count} fichiers",
|
||||
"pwa.dismiss": "Plus tard",
|
||||
"pwa.install_button": "Installer",
|
||||
"pwa.install_desc": "Installez cette application sur votre appareil pour un accès rapide.",
|
||||
@@ -1258,7 +1331,7 @@
|
||||
"sidebar.filter_results_grouped": "Résultats groupés",
|
||||
"sidebar.loading": "Chargement...",
|
||||
"sidebar.no_recent_files": "Aucun fichier récent",
|
||||
"sidebar.no_results": "Aucun résultat",
|
||||
"sidebar.no_results": "Aucun repertoire ou fichier correspondant.",
|
||||
"sidebar.no_saved_searches": "Aucune recherche sauvegardée",
|
||||
"sidebar.open_file": "Ouvrir un fichier",
|
||||
"sidebar.saved_dirs_tab": "Répertoires",
|
||||
@@ -1287,17 +1360,25 @@
|
||||
"sync.index_started": "Indexation démarrée ({count} vaults)",
|
||||
"sync.install_success": "ObsiGate installé avec succès !",
|
||||
"sync.model_not_loaded": "Modèle non chargé",
|
||||
"sync.no_provider": "Aucun fournisseur",
|
||||
"sync.no_recent_events": "Aucun événement récent",
|
||||
"sync.not_configured": "Non configuré",
|
||||
"sync.processing": "Traitement en cours…",
|
||||
"sync.update": "Mettre à jour",
|
||||
"sync.updating": "Mise à jour...",
|
||||
"sync.vault_added": "Vault \"{vault}\" ajouté ({count} fichiers)",
|
||||
"sync.vault_added_label": "Vault ajouté",
|
||||
"sync.vault_files": "{vault} ({files} fichiers)",
|
||||
"sync.vault_indexed_label": "Vault indexé",
|
||||
"sync.vault_removed": "Vault \"{vault}\" supprimé",
|
||||
"sync.vault_removed_label": "Vault supprimé",
|
||||
"sync.verifying": "Vérification…",
|
||||
"theme.change": "Changer le thème",
|
||||
"theme.dark": "Sombre",
|
||||
"theme.light": "Clair",
|
||||
"theme.title": "Thème",
|
||||
"themes.name_gradients": "Degrades subtils",
|
||||
"themes.name_terminal": "Noir pur & vert",
|
||||
"toast.ai_keys_saved": "Clés API sauvegardées",
|
||||
"toast.ai_no_key": "Aucune clé à sauvegarder",
|
||||
"toast.bookmark_added": "Ajouté aux favoris",
|
||||
@@ -1351,22 +1432,42 @@
|
||||
"tree.new_file": "Nouveau fichier",
|
||||
"tree.new_folder": "Nouveau dossier",
|
||||
"tree.vault_home": "Accueil du vault",
|
||||
"ui.backups_versions": "Backups / Versions",
|
||||
"ui.cannot_rename": "Impossible de renommer cet élément",
|
||||
"ui.delete_name_empty": "Le nom ne peut pas etre vide",
|
||||
"ui.element_not_found": "Élément introuvable dans l'arborescence",
|
||||
"ui.vault_readonly": "Vault en lecture seule",
|
||||
"vault.add_dynamic": "Ajouter une vault",
|
||||
"vault.reindex": "Réindexer la vault",
|
||||
"vault.remove_dynamic": "Retirer la vault",
|
||||
"vaulthome.empty": "Aucun fichier dans ce repertoire",
|
||||
"vaulthome.error_loading": "Erreur de chargement:",
|
||||
"vaulthome.file_count": "{count} fichier",
|
||||
"vaulthome.file_count_plural": "{count} fichiers",
|
||||
"vaulthome.loading": "Chargement des fichiers...",
|
||||
"vaulthome.size_bytes": "o",
|
||||
"vaulthome.size_kb": "Ko",
|
||||
"vaulthome.size_mb": "Mo",
|
||||
"viewer.backlinks": "Backlinks",
|
||||
"viewer.binary_download": "Télécharger le fichier",
|
||||
"viewer.binary_unsupported": "Fichier binaire non supporté",
|
||||
"viewer.bookmark_add": "Ajouter aux bookmarks",
|
||||
"viewer.bookmark_remove": "Retirer des bookmarks",
|
||||
"viewer.bookmark_toggle": "Ajouter/Retirer des bookmarks",
|
||||
"viewer.breadcrumb_home": "Accueil",
|
||||
"viewer.click_to_download": "Cliquez pour le télécharger",
|
||||
"viewer.copied": "Copié !",
|
||||
"viewer.copy": "Copier",
|
||||
"viewer.copy_error": "Erreur lors de la copie",
|
||||
"viewer.download": "Télécharger",
|
||||
"viewer.download_md": "Télécharger en .md",
|
||||
"viewer.download_pdf": "Télécharger en PDF",
|
||||
"viewer.edit": "Éditer",
|
||||
"viewer.error": "Erreur de chargement",
|
||||
"viewer.forge_brand": "Forge",
|
||||
"viewer.forge_title": "Forge (nouvel éditeur)",
|
||||
"viewer.index_start": "Démarrage index.",
|
||||
"viewer.index_updated": "Mise à jour",
|
||||
"viewer.loaded_from_cache": "Fichier chargé depuis le cache hors-ligne",
|
||||
"viewer.loading": "Chargement du fichier...",
|
||||
"viewer.markdown": "Markdown",
|
||||
@@ -1385,6 +1486,7 @@
|
||||
"viewer.share": "Partager",
|
||||
"viewer.shared_doc_title": "Document partagé — cliquer pour gérer",
|
||||
"viewer.source": "Source",
|
||||
"viewer.syncing": "Mise à jour...",
|
||||
"viewer.toc": "Table des matières",
|
||||
"viewer.unsupported_file": "Ce fichier est binaire et ne peut pas être affiché",
|
||||
"webhook.trigger_create": "Création via API ou palette",
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
/* ObsiGate Service Worker - PWA v2 with IndexedDB offline support */
|
||||
|
||||
const CACHE_VERSION = 'obsigate-v5-pwa';
|
||||
const CACHE_VERSION = 'obsigate-v6-i18n';
|
||||
const STATIC_CACHE = CACHE_VERSION + '-static';
|
||||
const DYNAMIC_CACHE = CACHE_VERSION + '-dynamic';
|
||||
const MAX_DYNAMIC_CACHE_SIZE = 100;
|
||||
|
||||
Reference in New Issue
Block a user