feat: complete i18n coverage — all dynamic content translated
CI / test (push) Has been cancelled
CI / security (push) Has been cancelled
CI / build (push) Has been cancelled
CI / e2e (push) Has been cancelled
CI / lint (push) Has been cancelled

All remaining French strings converted to t() calls:
- ui.js: create/delete file/dir modals, rename/copy/bookmark toasts
- palette.js: confirm dialogs, error toasts
- search.js: result summary text with interpolation
- config.js: about/diagnostics section labels
- auth.js: admin panel title
- viewer.js: forge popout labels
- dashboard.js: shared widget buttons, date locale-aware

57 new locale keys for dynamic content (modals, toasts, admin, about)
Total: 597 keys per language

All 26 modules validated — 163 exports, 0 errors
This commit is contained in:
2026-06-18 14:18:25 -04:00
parent f91a386566
commit 0403be4516
12 changed files with 796 additions and 147 deletions
+6 -5
View File
@@ -7,6 +7,7 @@ import { searchOffline } from './offline.js';
import { _getEffective } from './config.js';
import { TabManager, showToast } from './ui.js';
import { addTagFilter, buildSearchResultsHeader, shouldDisplayPath, removeTagFilter, TagFilterService } from './sidebar.js';
import { t } from './i18n.js';
// ---------------------------------------------------------------------------
// Search History Service (localStorage, LIFO, max 50, dedup)
// ---------------------------------------------------------------------------
@@ -915,17 +916,17 @@ export function renderAdvancedSearchResults(data, query, tagFilter) {
const freeText = parsed.freeText;
if (freeText && tagFilter) {
summaryText.textContent = `${data.total} résultat(s) pour "${freeText}" avec filtres`;
summaryText.textContent = t('search.results_filtered', {count: data.total, query: freeText});
} else if (freeText) {
summaryText.textContent = `${data.total} résultat(s) pour "${freeText}"`;
summaryText.textContent = t('search.results_for', {count: data.total, query: freeText});
} else if (parsed.tags.length > 0 || tagFilter) {
summaryText.textContent = `${data.total} fichier(s) avec filtres`;
summaryText.textContent = t('search.files_filtered', {count: data.total});
} else {
summaryText.textContent = `${data.total} résultat(s)`;
summaryText.textContent = t('search.results_count', {count: data.total});
}
if (data.query_time_ms !== undefined && data.query_time_ms > 0) {
const timeBadge = el("span", { class: "search-time-badge" });
timeBadge.textContent = `(${data.query_time_ms} ms)`;
timeBadge.textContent = t('search.query_time', {time: data.query_time_ms});
summaryText.appendChild(timeBadge);
}
header.appendChild(summaryText);