From 3d86ad7dc85f71f26aac8bcd68ffdc29b67e5921 Mon Sep 17 00:00:00 2001 From: diegosouzapw Date: Wed, 25 Feb 2026 15:08:38 -0300 Subject: [PATCH] feat(i18n): migrate providers/new + AuditLogTab + remaining keys MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Phase 4: providers/new/page.tsx — 15 strings (form labels, errors, buttons) Phase 5: logs/AuditLogTab.tsx — 15 strings (headers, filters, pagination) Phase 6: Added ~50 new keys to en.json + pt-BR.json Providers namespace: selectProvider, apiKeyRequired, authMethod, etc. Logs namespace: auditLogDesc, filterByAction, filterByActor, etc. --- .../dashboard/logs/AuditLogTab.tsx | 32 +++++++------- .../dashboard/providers/new/page.tsx | 42 +++++++++---------- src/i18n/messages/en.json | 35 +++++++++++++++- src/i18n/messages/pt-BR.json | 35 +++++++++++++++- 4 files changed, 102 insertions(+), 42 deletions(-) diff --git a/src/app/(dashboard)/dashboard/logs/AuditLogTab.tsx b/src/app/(dashboard)/dashboard/logs/AuditLogTab.tsx index 4adf9a1c..e8f3a981 100644 --- a/src/app/(dashboard)/dashboard/logs/AuditLogTab.tsx +++ b/src/app/(dashboard)/dashboard/logs/AuditLogTab.tsx @@ -6,6 +6,7 @@ */ import { useState, useEffect, useCallback } from "react"; +import { useTranslations } from "next-intl"; interface AuditEntry { id: number; @@ -27,6 +28,7 @@ export default function AuditLogTab() { const [actorFilter, setActorFilter] = useState(""); const [offset, setOffset] = useState(0); const [hasMore, setHasMore] = useState(false); + const t = useTranslations("logs"); const fetchEntries = useCallback(async () => { setLoading(true); @@ -85,10 +87,8 @@ export default function AuditLogTab() { {/* Header */}
-

Audit Log

-

- Administrative actions and security events -

+

{t("auditLog")}

+

{t("auditLogDesc")}

@@ -108,7 +108,7 @@ export default function AuditLogTab() { > setActionFilter(e.target.value)} onKeyDown={(e) => e.key === "Enter" && handleSearch()} @@ -117,7 +117,7 @@ export default function AuditLogTab() { /> setActorFilter(e.target.value)} onKeyDown={(e) => e.key === "Enter" && handleSearch()} @@ -128,7 +128,7 @@ export default function AuditLogTab() { onClick={handleSearch} className="px-4 py-2 rounded-lg text-sm font-medium bg-[var(--color-accent)] text-white hover:bg-[var(--color-accent-hover)] transition-colors focus:outline-2 focus:outline-offset-2 focus:outline-[var(--color-accent)]" > - Search + {t("search")} @@ -148,19 +148,19 @@ export default function AuditLogTab() { - Timestamp + {t("timestamp")} - Action + {t("action")} - Actor + {t("actor")} - Target + {t("target")} - Details + {t("details")} IP @@ -169,7 +169,7 @@ export default function AuditLogTab() { {entries.length === 0 && !loading ? ( - No audit log entries found + {t("noEntries")} ) : ( @@ -216,14 +216,14 @@ export default function AuditLogTab() { disabled={offset === 0} className="px-3 py-1.5 rounded-lg text-xs font-medium bg-[var(--color-surface)] border border-[var(--color-border)] text-[var(--color-text-main)] hover:bg-[var(--color-bg-alt)] disabled:opacity-30 transition-colors" > - ← Previous + ← {t("previous")} diff --git a/src/app/(dashboard)/dashboard/providers/new/page.tsx b/src/app/(dashboard)/dashboard/providers/new/page.tsx index 6e8546e6..fc61dd99 100644 --- a/src/app/(dashboard)/dashboard/providers/new/page.tsx +++ b/src/app/(dashboard)/dashboard/providers/new/page.tsx @@ -5,6 +5,7 @@ import { useRouter } from "next/navigation"; import Link from "next/link"; import { Card, Button, Input, Select, Toggle } from "@/shared/components"; import { AI_PROVIDERS, AUTH_METHODS } from "@/shared/constants/config"; +import { useTranslations } from "next-intl"; const providerOptions = Object.values(AI_PROVIDERS).map((p) => ({ value: p.id, @@ -19,6 +20,7 @@ const authMethodOptions = Object.values(AUTH_METHODS).map((m) => ({ export default function NewProviderPage() { const router = useRouter(); const [loading, setLoading] = useState(false); + const t = useTranslations("providers"); const [formData, setFormData] = useState({ provider: "", authMethod: "api_key", @@ -37,9 +39,9 @@ export default function NewProviderPage() { const validate = () => { const newErrors: any = {}; - if (!formData.provider) newErrors.provider = "Please select a provider"; + if (!formData.provider) newErrors.provider = t("selectProvider"); if (formData.authMethod === "api_key" && !formData.apiKey) { - newErrors.apiKey = "API Key is required"; + newErrors.apiKey = t("apiKeyRequired"); } setErrors(newErrors); return Object.keys(newErrors).length === 0; @@ -61,10 +63,10 @@ export default function NewProviderPage() { router.push("/dashboard/providers"); } else { const data = await response.json(); - setErrors({ submit: data.error || "Failed to create provider" }); + setErrors({ submit: data.error || t("failedCreateProvider") }); } } catch (error) { - setErrors({ submit: "An error occurred. Please try again." }); + setErrors({ submit: t("errorOccurredRetry") }); } finally { setLoading(false); } @@ -81,12 +83,10 @@ export default function NewProviderPage() { className="inline-flex items-center gap-1 text-sm text-text-muted hover:text-primary transition-colors mb-4" > arrow_back - Back to Providers + {t("backToProviders")} -

Add New Provider

-

- Configure a new AI provider to use with your applications. -

+

{t("addNewProvider")}

+

{t("configureNewProvider")}

{/* Form */} @@ -98,7 +98,7 @@ export default function NewProviderPage() { options={providerOptions} value={formData.provider} onChange={(e) => handleChange("provider", e.target.value)} - placeholder="Select a provider" + placeholder={t("selectProviderPlaceholder")} error={errors.provider as string} required /> @@ -116,7 +116,7 @@ export default function NewProviderPage() {

{selectedProvider.name}

-

Selected provider

+

{t("selectedProvider")}

)} @@ -124,7 +124,7 @@ export default function NewProviderPage() { {/* Auth Method */}
{authMethodOptions.map((method) => ( @@ -152,11 +152,11 @@ export default function NewProviderPage() { handleChange("apiKey", e.target.value)} error={errors.apiKey as string} - hint="Your API key will be encrypted and stored securely." + hint={t("apiKeyEncrypted")} required /> )} @@ -164,11 +164,9 @@ export default function NewProviderPage() { {/* OAuth2 Button */} {formData.authMethod === "oauth2" && ( -

- Connect your account using OAuth2 authentication. -

+

{t("connectOAuth2")}

)} @@ -186,8 +184,8 @@ export default function NewProviderPage() { handleChange("isActive", checked)} - label="Active" - description="Enable this provider for use in your applications" + label={t("activeLabel")} + description={t("activeDescription")} /> {/* Error Message */} @@ -201,11 +199,11 @@ export default function NewProviderPage() {
diff --git a/src/i18n/messages/en.json b/src/i18n/messages/en.json index b84bbe92..5af61577 100644 --- a/src/i18n/messages/en.json +++ b/src/i18n/messages/en.json @@ -439,7 +439,21 @@ "requestLogs": "Request Logs", "proxyLogs": "Proxy Logs", "auditLog": "Audit Log", - "console": "Console" + "console": "Console", + "auditLogDesc": "Administrative actions and security events", + "loading": "Loading...", + "refresh": "Refresh", + "filterByAction": "Filter by action...", + "filterByActor": "Filter by actor...", + "search": "Search", + "timestamp": "Timestamp", + "action": "Action", + "actor": "Actor", + "target": "Target", + "details": "Details", + "noEntries": "No audit log entries found", + "previous": "Previous", + "next": "Next" }, "onboarding": { "welcome": "Welcome", @@ -598,7 +612,24 @@ "disableRateLimitProtection": "Click to disable rate limit protection", "productionKey": "Production Key", "enterNewApiKey": "Enter new API key", - "optional": "Optional" + "optional": "Optional", + "selectProvider": "Please select a provider", + "apiKeyRequired": "API Key is required", + "failedCreateProvider": "Failed to create provider", + "errorOccurredRetry": "An error occurred. Please try again.", + "addNewProvider": "Add New Provider", + "configureNewProvider": "Configure a new AI provider to use with your applications.", + "selectProviderPlaceholder": "Select a provider", + "selectedProvider": "Selected provider", + "authMethod": "Authentication Method", + "enterApiKey": "Enter your API key", + "apiKeyEncrypted": "Your API key will be encrypted and stored securely.", + "connectOAuth2": "Connect your account using OAuth2 authentication.", + "connectWithOAuth2": "Connect with OAuth2", + "activeLabel": "Active", + "activeDescription": "Enable this provider for use in your applications", + "cancel": "Cancel", + "createProvider": "Create Provider" }, "settings": { "title": "Settings", diff --git a/src/i18n/messages/pt-BR.json b/src/i18n/messages/pt-BR.json index 7745d1f8..0f8902ed 100644 --- a/src/i18n/messages/pt-BR.json +++ b/src/i18n/messages/pt-BR.json @@ -439,7 +439,21 @@ "requestLogs": "Logs de Requisições", "proxyLogs": "Logs do Proxy", "auditLog": "Log de Auditoria", - "console": "Console" + "console": "Console", + "auditLogDesc": "Ações administrativas e eventos de segurança", + "loading": "Carregando...", + "refresh": "Atualizar", + "filterByAction": "Filtrar por ação...", + "filterByActor": "Filtrar por ator...", + "search": "Buscar", + "timestamp": "Data/Hora", + "action": "Ação", + "actor": "Ator", + "target": "Alvo", + "details": "Detalhes", + "noEntries": "Nenhuma entrada de log de auditoria encontrada", + "previous": "Anterior", + "next": "Próximo" }, "onboarding": { "welcome": "Bem-vindo", @@ -598,7 +612,24 @@ "disableRateLimitProtection": "Clique para desabilitar proteção de limite de taxa", "productionKey": "Chave de Produção", "enterNewApiKey": "Insira a nova chave API", - "optional": "Opcional" + "optional": "Opcional", + "selectProvider": "Por favor, selecione um provedor", + "apiKeyRequired": "Chave API é obrigatória", + "failedCreateProvider": "Falha ao criar provedor", + "errorOccurredRetry": "Ocorreu um erro. Tente novamente.", + "addNewProvider": "Adicionar Novo Provedor", + "configureNewProvider": "Configure um novo provedor de IA para usar com suas aplicações.", + "selectProviderPlaceholder": "Selecione um provedor", + "selectedProvider": "Provedor selecionado", + "authMethod": "Método de Autenticação", + "enterApiKey": "Insira sua chave API", + "apiKeyEncrypted": "Sua chave API será criptografada e armazenada com segurança.", + "connectOAuth2": "Conecte sua conta usando autenticação OAuth2.", + "connectWithOAuth2": "Conectar com OAuth2", + "activeLabel": "Ativo", + "activeDescription": "Habilitar este provedor para uso em suas aplicações", + "cancel": "Cancelar", + "createProvider": "Criar Provedor" }, "settings": { "title": "Configurações",