mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-07-31 04:12:10 +03:00
fix(audit): translate event types and A2A task states (Phase 2)
- Add compliance.eventTypes (36 labels) to en.json + pt-BR.json. - ComplianceTab: render translated label via t.has/t fallback instead of raw entry.action. - A2aAuditTab: render translated task state via a2aState* keys instead of raw task.state. - Memory type/strategy dropdowns needed no i18n change — keys already exist; the Phase 1 Select fix makes them render.
This commit is contained in:
@@ -182,7 +182,7 @@ export default function A2aAuditTab() {
|
||||
<span
|
||||
className={`rounded-full border px-2 py-1 text-xs font-medium ${STATE_STYLES[task.state]}`}
|
||||
>
|
||||
{task.state}
|
||||
{t(`a2aState${task.state.charAt(0).toUpperCase()}${task.state.slice(1)}`)}
|
||||
</span>
|
||||
</td>
|
||||
<td className="px-4 py-3 text-text-muted">{taskDuration(task)}</td>
|
||||
|
||||
@@ -330,7 +330,7 @@ export default function ComplianceTab() {
|
||||
</td>
|
||||
<td className="px-4 py-3">
|
||||
<span className="rounded-md border border-border bg-surface px-2 py-1 font-mono text-xs text-text-main">
|
||||
{entry.action}
|
||||
{t.has(`eventTypes.${entry.action}`) ? t(`eventTypes.${entry.action}`) : entry.action}
|
||||
</span>
|
||||
</td>
|
||||
<td className="px-4 py-3">
|
||||
|
||||
@@ -1283,7 +1283,45 @@
|
||||
"a2aNoTasks": "No A2A tasks recorded.",
|
||||
"a2aLoadingTasks": "Loading A2A tasks...",
|
||||
"actor": "Actor",
|
||||
"actorPlaceholder": "Filter by actor"
|
||||
"actorPlaceholder": "Filter by actor",
|
||||
"eventTypes": {
|
||||
"apiKey.activate": "API Key Activated",
|
||||
"apiKey.ban": "API Key Banned",
|
||||
"apiKey.deactivate": "API Key Deactivated",
|
||||
"apiKey.regenerate": "API Key Regenerated",
|
||||
"apiKey.scopes.grant": "API Key Scopes Granted",
|
||||
"apiKey.scopes.revoke": "API Key Scopes Revoked",
|
||||
"apiKey.scopes.update": "API Key Scopes Updated",
|
||||
"apiKey.unban": "API Key Unbanned",
|
||||
"auth.login.error": "Login Error",
|
||||
"auth.login.failed": "Login Failed",
|
||||
"auth.login.locked": "Login Locked",
|
||||
"auth.login.misconfigured": "Login Misconfigured",
|
||||
"auth.login.setup_required": "Login Setup Required",
|
||||
"auth.login.success": "Login Success",
|
||||
"auth.logout.success": "Logout Success",
|
||||
"compliance.cleanup": "Compliance Cleanup",
|
||||
"provider.credentials.applied": "Provider Credentials Applied",
|
||||
"provider.credentials.batch_revoked": "Provider Credentials Batch Revoked",
|
||||
"provider.credentials.bulk_created": "Provider Credentials Bulk Created",
|
||||
"provider.credentials.bulk_imported": "Provider Credentials Bulk Imported",
|
||||
"provider.credentials.created": "Provider Credentials Created",
|
||||
"provider.credentials.imported": "Provider Credentials Imported",
|
||||
"provider.credentials.revoked": "Provider Credentials Revoked",
|
||||
"provider.credentials.updated": "Provider Credentials Updated",
|
||||
"provider.validation.ssrf_blocked": "Provider SSRF Blocked",
|
||||
"quota.plan.updated": "Quota Plan Updated",
|
||||
"quota.pool.created": "Quota Pool Created",
|
||||
"quota.pool.deleted": "Quota Pool Deleted",
|
||||
"quota.pool.updated": "Quota Pool Updated",
|
||||
"quota.store.driver_changed": "Quota Store Driver Changed",
|
||||
"server.start": "Server Start",
|
||||
"service.reveal_api_key": "Service API Key Revealed",
|
||||
"settings.update": "Settings Updated",
|
||||
"settings.update_failed": "Settings Update Failed",
|
||||
"sync.token.created": "Sync Token Created",
|
||||
"sync.token.revoked": "Sync Token Revoked"
|
||||
}
|
||||
},
|
||||
"themesPage": {
|
||||
"title": "Themes",
|
||||
|
||||
@@ -2465,7 +2465,45 @@
|
||||
"a2aNoTasks": "Nenhuma tarefa A2A registrada.",
|
||||
"a2aLoadingTasks": "Carregando tarefas A2A...",
|
||||
"actor": "Autor",
|
||||
"actorPlaceholder": "Filtrar por autor"
|
||||
"actorPlaceholder": "Filtrar por autor",
|
||||
"eventTypes": {
|
||||
"apiKey.activate": "API Key Ativada",
|
||||
"apiKey.ban": "API Key Banida",
|
||||
"apiKey.deactivate": "API Key Desativada",
|
||||
"apiKey.regenerate": "API Key Regenerada",
|
||||
"apiKey.scopes.grant": "Escopos de API Key Concedidos",
|
||||
"apiKey.scopes.revoke": "Escopos de API Key Revogados",
|
||||
"apiKey.scopes.update": "Escopos de API Key Atualizados",
|
||||
"apiKey.unban": "API Key Desbanida",
|
||||
"auth.login.error": "Erro de Login",
|
||||
"auth.login.failed": "Login Falhou",
|
||||
"auth.login.locked": "Login Bloqueado",
|
||||
"auth.login.misconfigured": "Login Mal Configurado",
|
||||
"auth.login.setup_required": "Configuração de Login Necessária",
|
||||
"auth.login.success": "Login com Sucesso",
|
||||
"auth.logout.success": "Logout com Sucesso",
|
||||
"compliance.cleanup": "Limpeza de Conformidade",
|
||||
"provider.credentials.applied": "Credenciais do Provedor Aplicadas",
|
||||
"provider.credentials.batch_revoked": "Credenciais do Provedor Revogadas em Lote",
|
||||
"provider.credentials.bulk_created": "Credenciais do Provedor Criadas em Massa",
|
||||
"provider.credentials.bulk_imported": "Credenciais do Provedor Importadas em Massa",
|
||||
"provider.credentials.created": "Credenciais do Provedor Criadas",
|
||||
"provider.credentials.imported": "Credenciais do Provedor Importadas",
|
||||
"provider.credentials.revoked": "Credenciais do Provedor Revogadas",
|
||||
"provider.credentials.updated": "Credenciais do Provedor Atualizadas",
|
||||
"provider.validation.ssrf_blocked": "SSRF do Provedor Bloqueado",
|
||||
"quota.plan.updated": "Plano de Cota Atualizado",
|
||||
"quota.pool.created": "Pool de Cota Criado",
|
||||
"quota.pool.deleted": "Pool de Cota Excluído",
|
||||
"quota.pool.updated": "Pool de Cota Atualizado",
|
||||
"quota.store.driver_changed": "Driver do Store de Cota Alterado",
|
||||
"server.start": "Servidor Iniciado",
|
||||
"service.reveal_api_key": "API Key do Serviço Revelada",
|
||||
"settings.update": "Configurações Atualizadas",
|
||||
"settings.update_failed": "Falha ao Atualizar Configurações",
|
||||
"sync.token.created": "Token de Sincronização Criado",
|
||||
"sync.token.revoked": "Token de Sincronização Revogado"
|
||||
}
|
||||
},
|
||||
"contextCaveman": {
|
||||
"title": "Motor Caveman",
|
||||
|
||||
27
tests/unit/audit-eventtype-i18n.test.ts
Normal file
27
tests/unit/audit-eventtype-i18n.test.ts
Normal file
@@ -0,0 +1,27 @@
|
||||
import test from "node:test";
|
||||
import assert from "node:assert/strict";
|
||||
import { readFileSync } from "node:fs";
|
||||
import { join } from "node:path";
|
||||
|
||||
const root = join(import.meta.dirname, "../..");
|
||||
const read = (p: string) => readFileSync(join(root, p), "utf8");
|
||||
const en = JSON.parse(read("src/i18n/messages/en.json"));
|
||||
const pt = JSON.parse(read("src/i18n/messages/pt-BR.json"));
|
||||
|
||||
test("audit: compliance.eventTypes exists with en/pt-BR parity and key coverage", () => {
|
||||
const enKeys = Object.keys(en.compliance?.eventTypes ?? {});
|
||||
const ptKeys = Object.keys(pt.compliance?.eventTypes ?? {});
|
||||
assert.ok(enKeys.length >= 30, `expected >=30 event-type labels, got ${enKeys.length}`);
|
||||
assert.deepEqual(enKeys.sort(), ptKeys.sort(), "en/pt-BR eventTypes keys must match");
|
||||
for (const k of ["provider.credentials.created", "auth.login.success", "quota.pool.created", "sync.token.revoked"]) {
|
||||
assert.ok(en.compliance.eventTypes[k], `en missing eventTypes.${k}`);
|
||||
assert.ok(pt.compliance.eventTypes[k], `pt-BR missing eventTypes.${k}`);
|
||||
}
|
||||
});
|
||||
|
||||
test("audit: ComplianceTab translates action and A2aAuditTab translates task state", () => {
|
||||
const ct = read("src/app/(dashboard)/dashboard/audit/ComplianceTab.tsx");
|
||||
const a2a = read("src/app/(dashboard)/dashboard/audit/A2aAuditTab.tsx");
|
||||
assert.ok(ct.includes("eventTypes.${entry.action}"), "ComplianceTab uses eventTypes i18n lookup");
|
||||
assert.ok(a2a.includes("a2aState${task.state"), "A2aAuditTab uses a2aState i18n lookup");
|
||||
});
|
||||
Reference in New Issue
Block a user