"""Batch i18n: replace all remaining French strings in JS modules with t() calls.""" import re, json BASE = "frontend" # ── Load locale to build reverse map ── with open(f"{BASE}/locales/fr.json", encoding="utf-8") as f: fr = json.load(f) text_to_key = {} for k, v in fr.items(): if k.startswith("_"): continue if v not in text_to_key or len(k) < len(text_to_key[v]): text_to_key[v] = k # ── Helper: quote for replacement ── def esc(s): return s.replace('\\', '\\\\').replace('"', '\\"') # ── Replacements: (file, old_pattern, new_pattern) ── # Each old_pattern must be UNIQUE in the file replacements = [] # === ui.js === f = f"{BASE}/js/ui.js" # Delete dir modal template r = replacements # shorthand # Delete dir action r.append((f, "confirmBtn.disabled = true;\n confirmBtn.textContent = 'Suppression...';\n \n try {\n const result = await api(`/api/directory", "confirmBtn.disabled = true;\n confirmBtn.textContent = t('modal.creating');\n \n try {\n const result = await api(`/api/directory")) r.append((f, "showToast(`Dossier supprimé (${result.deleted_count} fichiers)`, 'success');", "showToast(t('toast.dir_deleted', {count: result.deleted_count}), 'success');")) r.append((f, "showToast(err.message || 'Erreur lors de la suppression', 'error');\n confirmBtn.disabled = false;\n confirmBtn.textContent = 'Supprimer définitivement';", "showToast(err.message || t('toast.delete_error'), 'error');\n confirmBtn.disabled = false;\n confirmBtn.textContent = t('modal.delete_permanently');")) # Rename toasts r.append((f, "showToast(type === 'directory' ? 'Dossier renommé' : 'Fichier renommé', 'success');", "showToast(type === 'directory' ? t('toast.dir_renamed') : t('toast.file_renamed'), 'success');")) r.append((f, "showToast(err.message || 'Erreur lors du renommage', 'error');", "showToast(err.message || t('toast.rename_error'), 'error');")) # Copy path toast r.append((f, "showToast(`Chemin copié : ${path}`, 'success');", "showToast(t('toast.path_copied', {path: path}), 'success');")) r.append((f, "showToast('Erreur lors de la copie', 'error');", "showToast(t('toast.copy_error'), 'error');")) # Bookmark toast r.append((f, 'showToast(data.bookmarked ? "Ajouté aux bookmarks" : "Retiré des bookmarks", "success");', 'showToast(data.bookmarked ? t("toast.bookmark_added") : t("toast.bookmark_removed"), "success");')) # Dir saved search toast r.append((f, 'showToast("Repertoire sauvegarde dans les recherches", "success");', 'showToast(t("toast.dir_saved_search"), "success");')) # Viewer error toast r.append((f, 'showToast("Erreur lors du chargement du viewer: " + err.message, "error");', 'showToast(t("toast.viewer_error") + ": " + err.message, "error");')) # === palette.js === f = f"{BASE}/js/palette.js" pal = text_to_key # Confirm dialogs r.append((f, 'confirm(`Supprimer le fichier \\"${path}\\" ?`)', 'confirm(t("confirm.delete_file_named", {path: path}))')) r.append((f, 'confirm(`Supprimer \\"${path}\\" et TOUT son contenu ?`)', 'confirm(t("confirm.delete_dir_named", {path: path}))')) # Show toasts r.append((f, "showToast('Erreur de création','error')", "showToast(t('toast.create_error'),'error')")) r.append((f, "showToast('Erreur','error')", "showToast(t('common.error'),'error')")) # === config.js === f = f"{BASE}/js/config.js" # About sections r.append((f, 'title: "Application",', 'title: t("about.section_app"),')) r.append((f, 'title: "Environnement",', 'title: t("about.section_env"),')) r.append((f, 'title: "Composants",', 'title: t("about.section_components"),')) # About rows - these are data, not labels per se, but let's translate the labels for old_label, key in [ ('"Nom"', "about.name"), ('"Version"', "about.version"), ('"Version API"', "about.api_version"), ('"Statut"', "about.status"), ('"Vaults configurés"', "about.vaults_configured"), ('"Fichiers indexés"', "about.files_indexed"), ('"Navigateur"', "about.browser"), ('"Plateforme"', "about.platform"), ('"Langue"', "about.language"), ('"Backend"', "about.backend"), ('"Rendu Markdown"', "about.markdown_renderer"), ('"Surveillance fichiers"', "about.file_watcher"), ('"Frontend"', "about.frontend"), ('"Icônes"', "about.icons"), ('"Coloration syntaxe"', "about.syntax_highlight"), ('"Éditeur"', "about.editor"), ]: r.append((f, f'[{old_label},', f'[t("{key}"),')) # Admin-only / no webhooks r.append((f, "list.innerHTML = '