#74 — Support PDF complet:
- backend/pdf_reader.py — pymupdf/pypdf text extraction
- .pdf added to SUPPORTED_EXTENSIONS in indexer.py
- PDF-aware file view API endpoint (metadata, text preview)
- Streaming endpoint /api/file/{vault}/pdf/stream
- Frontend PDF viewer with iframe, toolbar, download
- CSS for PDF viewer container
#75 — Split View (PaneManager):
- New module frontend/js/pane-manager.js — ES module
- 1-4 pane CSS grid with resize handles
- Split right/down via keyboard (Ctrl+Alt+\) or PaneManager API
- Persistence in localStorage (obsigate-panes)
- Collapse to single pane, per-pane active state
285 tests passent
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.
The SW was the root cause of all persistent French text issues.
Even after rebuild, browsers with a registered SW would serve
cached old files (viewer.js without data-i18n, old locale JSONs).
SW-killer runs before any module script:
1. Detects if SW is controlling the page
2. Unregisters all SW registrations
3. Clears all caches
4. Reloads the page once (sessionStorage flag to prevent loop)
Other fixes in this commit:
- auth.js: import setLocale statically (was dynamic import)
- auth.js: import loadVaults/loadTags from sidebar.js
- sw.js: add JS modules + locales to STATIC_ASSETS for versioning
- sw.js: CACHE_VERSION v4→v5
Root cause: cacheFirstStatic() in sw.js was caching viewer.js,
i18n.js, auth.js, dashboard.js, and locale JSON files under the old
CACHE_VERSION. Even after rebuild, the old SW served stale cached
files without data-i18n attributes, so dashboard stayed in French.
Changes:
- sw.js: add js/viewer.js, js/i18n.js, js/auth.js, js/dashboard.js,
js/app.js, locales/en.json, locales/fr.json to STATIC_ASSETS
so they are versioned with CACHE_VERSION and properly invalidated
- CACHE_VERSION already bumped to v5 in previous commit
Manual fix for existing clients:
Chrome → F12 → Application → Service Workers → Unregister
Or: chrome://serviceworker-internals/ → Unregister
Then Ctrl+Shift+R to hard-refresh
- auth.js: window.handleLogout at module top level (was inside
renderUserMenu, not always called). Fixes settings dropdown
'Sign out' onclick='handleLogout()' doing nothing.
- auth.js: add missing imports (loadVaults, loadTags from sidebar.js)
and dynamic import for IndexUpdateManager (circular dep avoidance).
Fixes 'loadVaults is not defined' error on login.
- sw.js: CACHE_VERSION v4→v5 to bust stale Service Worker cache
that was serving old viewer.js without data-i18n attributes,
causing dashboard tabs to stay French despite English profile.
To apply: rebuild container + unregister SW in DevTools + reload.
The header dropdown 'Sign out' menu item used onclick='handleLogout()'
but handleLogout was never defined as a global function.
Added window.handleLogout in auth.js that delegates to
AuthManager.logout(), same as the existing logout-btn handler.
Root cause: initI18n() runs before auth on login page, so
/api/auth/me fails (401) and locale falls back to browser language.
After login, showWelcome() renders with stale locale without
re-checking server preference. French users always got French UI.
Fix: after successful login, fetch /api/auth/me and call setLocale()
if server language differs from current. This ensures the dashboard
renders in the user's saved language preference.
Problem: language preference stored only in localStorage, lost on
'clear site data'. French users with browser lang=fr always got French
UI even when profile was English.
Solution:
- Backend: add 'language' field to user profile (default 'fr')
- Backend: PATCH /api/auth/me to update language preference
- Frontend: initI18n() priority: server > localStorage > navigator > 'fr'
- Frontend: initAuth() runs before initI18n() so server check works
- Frontend: profile Save persists language to server via PATCH
Verified: tabs show English after server profile set to 'en'
Root cause: dashboard tabs rendered via t() template literals had no
data-i18n attributes, so setLocale() _applyDOM() could not re-translate
them live. User switching to English in profile saw no effect without
page reload.
Changes:
- i18n.js: expose t/initI18n/setLocale/getLocale/tr globally (window.*)
for non-module script compatibility
- viewer.js: add data-i18n attributes to all 4 dashboard tabs + loading
text + empty state messages (12 elements total)
Verified: tabs show 'Statistics/Bookmarks/Recent/Shared' in EN mode
- Add 89 auto-generated i18n keys covering remaining hardcoded text
- Fix truncated EN value for auto.b114ed1c (server settings description)
- Add data-i18n attributes to menu items, help TOC entries, and form labels
- Bump CACHE_VERSION to v4 for new static assets
- Remove stale orphaned file from repo
- 285 tests passing, 0 failures
- All 509 HTML i18n refs have corresponding keys
- EN/FR perfectly aligned at 1357 keys each
- Added data-i18n to section title, badge, labels, hints
- New keys: config.recent_history_count, config.recent_history_count_desc, config.max_backups_desc
- All 6 hardcoded FR strings now use t()
- Restored from 8db9f44 (pristine original)
- Added IDs only (cfg-recent, cfg-backend-settings, cfg-hidden-files, cfg-webhooks, cfg-partages-publics, cfg-tags, cfg-performance)
- TOC order matches original section order
- No section reordering (avoids DOM breakage)
- Extracted correct lines (2052-2098, skipping stray </section> from prev)
- All 13 sections verified present in order
- Webhooks/Partages have config-section help-section classes
- Webhooks and Public Shares now positioned between Hidden Files and Diagnostics
- Matches TOC order: Hidden → Webhooks → Shares → Diags → AI → Themes → Profile → About
- Restored from 8db9f44 (clean base)
- Added IDs to all subsections via unique HTML context
- TOC reordered: Search, Recent, Backend, Tags, Sync, Hidden, Webhooks, Shares, Diags, AI, Themes, Profile, About
- About section at original position (last), no moved sections
- Replaced config-nav ul with 14 cfg- links
- Removed duplicate id='help-nav-list' from config-nav ul
- Previous fix wrote to wrong ul (outside config-nav)
- SW cached / and /static/index.html with cache-first strategy
- Old HTML with 422 error persisted after rebuild
- Bumping CACHE_VERSION forces reinstall with fresh assets
- Changed q=* to q=** in autocomplete.js and offline.js
- Backend requires min_query_length=2, single * was 1 char → 422
- Caused blank page on F5 refresh (non-hard-refresh)
- Removed id='help-nav-list' from settings TOC ul (inside config-nav)
- Help TOC ul now has unique id, so click handlers work correctly
- Root cause: getElementById returned wrong ul (settings instead of help)
- Help TOC: 18 help-* links restored from git
- Settings TOC: 14 cfg-* links with correct section anchors
- Both TOCs now live in their respective nav containers
- Restored help-nav-list (User Guide TOC) from git history
- Settings TOC (config-nav) now has 14 sections in proper order
- Root cause: both TOCs shared help-nav-list class,
replacement targeted wrong ul in help modal
- Split merged <li> containing both cfg-about and cfg-themes
- Reordered: search, sync, diags, ai, themes, profile, about
- All 7 TOC links now match section IDs 1:1
- 15 config-hint spans now have data-i18n with English translations
- Removed dead cfg-backend TOC link (section doesn't exist)
- Fixed TOC order: cfg-themes moved before cfg-profile
- +17 new locale keys (1258 total)
Backend config labels: debounce, results/page, min query, search timeout,
max backups, search workers, max content size, title boost, prefix expansions
Section headers: Backend, Reading & editing, Experience, Access
Misc: Open in new window, project repository, name placeholder
+17 new keys (1241 total)
- Line 629: changed single quotes to backticks for published span
- Line 653: changed to string concatenation for ctrl_hover_preview
- Line 675: removed unnecessary template literal for published_badge
- Root cause: ${t(...)} inside '...' is not interpolated
- Translated auto-generated help.desc_* keys with French text
- EN locale now clean of accented French for all user-facing text
- 44 remaining are keyboard shortcuts/symbols (safe)
- 2 unwrapped multiline descriptions: popout and navigate list
- 4 pre-existing keys with French EN values: shortcuts, tab toggle, type name
- All palette text now properly i18n with English translations
- Opening keyboard shortcuts descriptions
- File mode: type file name, API search, press Enter
- Command mode: type > to see actions
- 7 new help.pal_* keys with English translations
- Palette, Shortcuts, Sharing, Webhooks, Backups, Security, Tips
- All auto-generated help.desc_* keys now have proper EN text
- 0 placeholder [EN] keys remaining
- en.json: 1162 keys, all translated
- Filtres de chemin: changed to data-i18n-attr
- help close/hide/clear buttons: changed to data-i18n-attr
- aria-label spans: changed to data-i18n-attr
- This fixes the visible HTML tag leakage in the UI
- help-ai now at position 10 (between help-graphe and help-palette)
- help-personnalisation moved to position 17 (before help-astuces)
- All 18 sections now match TOC order
- 94 <p>, <li>, <h3>, <h4> elements now have data-i18n
- AI Editor section: 16 English translations provided
- 251 new keys total across all sections
- Remaining 80 placeholder keys in sharing/webhooks/backups/security/tips
- en.json: 1068 -> 1162, fr.json: 1068 -> 1162
- AI Editor: Complète, flashe en vert, Ton décontracté
- Webhooks: notify, POST HTTP, blog post, note événement
- Tips: Utilisez les tags, sidebar, filtrage
- Added 10 new keys to en.json/fr.json (1046 -> 1056)
- toggleTheme() in ui.js now calls toggleThemeMode() from themes.js
- This properly toggles dark/light within the current named theme
- Updates the theme label and icon after mode change
- app.js: import { t } alongside initI18n, move initI18n() before UI.initTheme()
- sidebar.js: add import { t } from ./i18n.js
- These fix ReferenceError: t is not defined on startup
- Zoom/Pan, Depth slider, Filter by tag, Filter by type
- Visual search, Navigation arrows, Nodes, Info panel, Export PNG
- Context menu
All → EN translations
- Added missing help.desc_filter_usage + help.desc_vault_context keys
- Fixed truncated auto paragraphs (full text now in locale)
- All truncated paragraphs restored to complete text
- 5 feature tag badges: data-i18n on span.help-badge
- 3 stat labels: Experience, Search → English
- Access label fixed with dedicated key
- All EN translations provided
16 descriptions after <strong> now wrapped in <span data-i18n>
All have EN translations (Show/hide sidebar, Return to home, etc.)
Fixed broken hamburger span ('obile)' → '(mobile)')
- 36 new data-i18n tags on h2/h3/p in help modal body
- Fixed concatenated attributes (pdata-i18n → p data-i18n)
- All section headings translated (Palette, AI Editor, Search, etc.)
- 827 locale keys total, 354 data-i18n attributes
- Help guide title 'Guide utilisation ObsiGate' now translated
- Help badges, stat labels, headings tagged
- All <li> descriptions after <strong> wrapped in data-i18n
- 30 text fragments in help body tagged + EN translations
- 791 locale keys total, 0 untranslated help keys
- Emojis preserved in nav items
- 82 new data-i18n tags on remaining French text in index.html
- 80 auto-generated keys translated to English
- 315 total data-i18n attributes, 739 locale keys per language
- Help body paragraphs, settings descriptions, about footer
- Dashboard quick help, config parameter labels
- ALL user-visible text now has i18n coverage
- Help modal: 18 nav links with data-i18n, title, search placeholder
- Settings sidebar: 7 nav items tagged (Recherche..Themes)
- About modal: subtitle tagged
- Header dropdown: all 7 menu items tagged
- 226 total data-i18n attributes in index.html
- showWelcome() dashboard: all tabs, empty states, hints → ${t()}
- Header dropdown: 7 menu items with data-i18n (Thème..Déconnexion)
- 61 new locale keys for dashboard, settings nav, help nav, about
- Total: 658 keys per language
The template literal ${t('modal.in_folder', {path: parentPath || '/'}\nwas missing the closing )} — the / after || was interpreted\nas the start of a regex literal, causing:\n Uncaught SyntaxError: Invalid regular expression: missing /
Fixed both occurrences (directory + file create modals).
Add Ollama autocomplete status endpoint to AI routes, update sync panel
UI to display autocomplete state, replace monolithic test compose files
with separate Linux/Windows variants, and add PowerShell build script
for Windows deployment