- {extractApiError(historyQuery.error, 'Could not load history')}
+ {extractApiError(historyQuery.error, t('c2.modal.import.error.import'))}
)}
{!historyQuery.isLoading && historyTasks.length === 0 && !historyQuery.isError && (
- No task history for this callback.
+
@@ -175,7 +177,7 @@ export function ImportC2HistoryModal({
- {task.completed ? 'Yes' : 'No'}
+ {task.completed ? t('common.yes') : t('common.no')}
|
{task.created_at}
@@ -195,10 +197,10 @@ export function ImportC2HistoryModal({
onClick={() => setPage((p) => Math.max(1, p - 1))}
disabled={page <= 1}
>
- Prev
+ {t('c2.modal.import.prev')}
- Page {page} of {totalPages}
+ {t('c2.modal.import.page')} {page} {t('c2.modal.import.of')} {totalPages}
{checkedIds.size > 0 && (
- {checkedIds.size} selected
+ {checkedIds.size} {t('c2.modal.import.selected')}
)}
@@ -235,7 +237,7 @@ export function ImportC2HistoryModal({
onClick={onImport}
disabled={!canImport || importMutation.isPending}
>
- {importMutation.isPending ? 'Importing…' : 'Import selected'}
+ {importMutation.isPending ? t('c2.modal.import.btn.importing') : t('c2.modal.import.btn.import')}
diff --git a/frontend/src/i18n/fr.json b/frontend/src/i18n/fr.json
index 15fd608..938b9ac 100644
--- a/frontend/src/i18n/fr.json
+++ b/frontend/src/i18n/fr.json
@@ -14,7 +14,9 @@
"create": "Créer",
"creating": "Création…",
"close": "Fermer",
- "confirm": "Confirmer"
+ "confirm": "Confirmer",
+ "yes": "Oui",
+ "no": "Non"
},
"nav": {
"engagements": "Engagements",
@@ -389,7 +391,7 @@
"commandsRequired": "Aucune commande à exécuter"
},
"toast": {
- "launched": "Tâche C2 lancée"
+ "launched": "{{count}} tâche(s) C2 lancée(s)"
},
"error": {
"launch": "Impossible de lancer la tâche C2"
@@ -409,9 +411,13 @@
},
"selected": "sélectionné(s)",
"empty": "Aucun historique C2 disponible.",
+ "col": {
+ "timestamp": "Horodatage",
+ "completed": "Terminé"
+ },
"toast": {
- "imported": "Historique C2 importé",
- "partial": "Import partiel"
+ "imported": "{{count}} tâche(s) importée(s)",
+ "partial": "{{imported}} importée(s), {{skipped}} déjà attachée(s)"
},
"error": {
"import": "Impossible d'importer l'historique C2"
@@ -421,7 +427,19 @@
"title": "Sélectionner un agent",
"empty": "Aucun agent disponible.",
"hostnameColon": "Hôte :",
- "lastCheckinColon": "Dernière connexion :"
+ "lastCheckinColon": "Dernière connexion :",
+ "col": {
+ "displayId": "ID",
+ "active": "Actif",
+ "host": "Hôte",
+ "user": "Utilisateur",
+ "domain": "Domaine",
+ "lastCheckin": "Dernière connexion"
+ },
+ "status": {
+ "active": "Actif",
+ "inactive": "Inactif"
+ }
}
}
},
diff --git a/frontend/tests/components/C2ConfigCard.test.tsx b/frontend/tests/components/C2ConfigCard.test.tsx
index cc6e349..a8d92c7 100644
--- a/frontend/tests/components/C2ConfigCard.test.tsx
+++ b/frontend/tests/components/C2ConfigCard.test.tsx
@@ -57,7 +57,7 @@ describe('C2ConfigCard — with config (has_token=true)', () => {
it('shows Replace token affordance when has_token=true', async () => {
renderWithProviders();
await waitFor(() => {
- expect(screen.getByText('Replace token')).toBeInTheDocument();
+ expect(screen.getByText('Remplacer le token')).toBeInTheDocument();
});
// Token input shows placeholder bullets (readOnly)
const tokenInput = screen.getByTestId('c2-token-input') as HTMLInputElement;
@@ -75,9 +75,9 @@ describe('C2ConfigCard — with config (has_token=true)', () => {
it('clicking Replace token makes input editable', async () => {
renderWithProviders();
await waitFor(() => {
- expect(screen.getByText('Replace token')).toBeInTheDocument();
+ expect(screen.getByText('Remplacer le token')).toBeInTheDocument();
});
- fireEvent.click(screen.getByText('Replace token'));
+ fireEvent.click(screen.getByText('Remplacer le token'));
await waitFor(() => {
const tokenInput = screen.getByTestId('c2-token-input') as HTMLInputElement;
expect(tokenInput.readOnly).toBeFalsy();
@@ -99,7 +99,7 @@ describe('C2ConfigCard — with config (has_token=true)', () => {
});
fireEvent.click(screen.getByTestId('c2-test-btn'));
await waitFor(() => {
- expect(screen.getByText('Connected')).toBeInTheDocument();
+ expect(screen.getByText('Connecté')).toBeInTheDocument();
});
});
@@ -124,7 +124,7 @@ describe('C2ConfigCard — 503 disabled state', () => {
renderWithProviders();
await waitFor(() => {
expect(
- screen.getByText(/C2 features are disabled/i),
+ screen.getByText(/fonctionnalités C2 sont désactivées/i),
).toBeInTheDocument();
});
expect(screen.getByTestId('c2-save-btn')).toBeDisabled();
diff --git a/frontend/tests/components/C2TasksPanel.test.tsx b/frontend/tests/components/C2TasksPanel.test.tsx
index b4214aa..2a52b5d 100644
--- a/frontend/tests/components/C2TasksPanel.test.tsx
+++ b/frontend/tests/components/C2TasksPanel.test.tsx
@@ -66,7 +66,7 @@ describe('C2TasksPanel — empty state', () => {
await waitFor(() => {
expect(screen.getByTestId('c2-tasks-panel')).toBeInTheDocument();
});
- expect(screen.getByText(/No C2 tasks yet/i)).toBeInTheDocument();
+ expect(screen.getByText(/Aucune tâche C2/i)).toBeInTheDocument();
expect(screen.queryByTestId('c2-task-row')).toBeNull();
});
});
diff --git a/frontend/tests/components/ExecuteViaC2Modal.test.tsx b/frontend/tests/components/ExecuteViaC2Modal.test.tsx
index a92d1dc..713e433 100644
--- a/frontend/tests/components/ExecuteViaC2Modal.test.tsx
+++ b/frontend/tests/components/ExecuteViaC2Modal.test.tsx
@@ -66,7 +66,7 @@ describe('ExecuteViaC2Modal', () => {
it('renders modal with title and callback table', async () => {
renderModal();
expect(screen.getByTestId('c2-modal')).toBeInTheDocument();
- expect(screen.getByText('Execute via C2')).toBeInTheDocument();
+ expect(screen.getByText('Exécuter via C2')).toBeInTheDocument();
await waitFor(() => {
expect(screen.getAllByTestId('c2-callback-row')).toHaveLength(2);
});
@@ -148,7 +148,7 @@ describe('ExecuteViaC2Modal', () => {
await waitFor(() => {
expect(screen.getAllByTestId('c2-callback-row')).toHaveLength(2);
});
- fireEvent.click(screen.getByRole('button', { name: /cancel/i }));
+ fireEvent.click(screen.getByRole('button', { name: /Annuler/i }));
expect(onClose).toHaveBeenCalled();
});
diff --git a/frontend/tests/components/ImportC2HistoryModal.test.tsx b/frontend/tests/components/ImportC2HistoryModal.test.tsx
index 58f98d2..237a723 100644
--- a/frontend/tests/components/ImportC2HistoryModal.test.tsx
+++ b/frontend/tests/components/ImportC2HistoryModal.test.tsx
@@ -88,7 +88,7 @@ describe('ImportC2HistoryModal — step 1: callback picker', () => {
it('renders modal with title and callback rows', async () => {
renderModal();
expect(screen.getByTestId('c2-import-modal')).toBeInTheDocument();
- expect(screen.getByText('Import C2 history')).toBeInTheDocument();
+ expect(screen.getByText("Importer l'historique C2")).toBeInTheDocument();
await waitFor(() => {
expect(screen.getAllByTestId('c2-import-callback-row')).toHaveLength(2);
});
@@ -322,7 +322,7 @@ describe('ImportC2HistoryModal — toast wording', () => {
fireEvent.click(screen.getByTestId('c2-import-submit-btn'));
await waitFor(() => {
- expect(screen.getByText('Imported 1 task(s)')).toBeInTheDocument();
+ expect(screen.getByText('1 tâche(s) importée(s)')).toBeInTheDocument();
});
});
@@ -342,7 +342,7 @@ describe('ImportC2HistoryModal — toast wording', () => {
await waitFor(() => {
expect(
- screen.getByText('Imported 0 task(s), 1 already attached'),
+ screen.getByText('0 importée(s), 1 déjà attachée(s)'),
).toBeInTheDocument();
});
});
@@ -374,7 +374,7 @@ describe('ImportC2HistoryModal — Cancel button', () => {
await waitFor(() => {
expect(screen.getAllByTestId('c2-import-callback-row')).toHaveLength(2);
});
- fireEvent.click(screen.getByRole('button', { name: /cancel/i }));
+ fireEvent.click(screen.getByRole('button', { name: /Annuler/i }));
expect(onClose).toHaveBeenCalled();
});
});
|