From 5f38173387ff4f2ae556b04bef1ce1ac33062735 Mon Sep 17 00:00:00 2001 From: diegosouzapw Date: Wed, 25 Feb 2026 15:00:12 -0300 Subject: [PATCH] =?UTF-8?q?fix(i18n):=20settings=20remnants=20=E2=80=94=20?= =?UTF-8?q?PoliciesPanel,=20PricingTab=20desc,=20ThinkingBudget,=20Fallbac?= =?UTF-8?q?kChains,=20Resilience?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - PoliciesPanel.tsx: full migration (10 strings + 2 notify.error) - PricingTab.tsx: translate description block, confirm, subtitle - ThinkingBudgetTab.tsx: translate 'Off' label - FallbackChainsEditor.tsx: translate confirm() string - ResilienceTab.tsx: translate 2 notify.error('Failed to unlock') - Added 25 keys to en.json + pt-BR.json settings namespace --- .../components/FallbackChainsEditor.tsx | 2 +- .../settings/components/PoliciesPanel.tsx | 24 ++++++++--------- .../settings/components/PricingTab.tsx | 17 ++++-------- .../settings/components/ResilienceTab.tsx | 4 +-- .../settings/components/ThinkingBudgetTab.tsx | 2 +- src/i18n/config.ts | 2 +- src/i18n/messages/en.json | 26 ++++++++++++++++++- src/i18n/messages/pt-BR.json | 26 ++++++++++++++++++- 8 files changed, 72 insertions(+), 31 deletions(-) diff --git a/src/app/(dashboard)/dashboard/settings/components/FallbackChainsEditor.tsx b/src/app/(dashboard)/dashboard/settings/components/FallbackChainsEditor.tsx index fd6947a889..18c0a78cd7 100644 --- a/src/app/(dashboard)/dashboard/settings/components/FallbackChainsEditor.tsx +++ b/src/app/(dashboard)/dashboard/settings/components/FallbackChainsEditor.tsx @@ -94,7 +94,7 @@ export default function FallbackChainsEditor() { }; const handleDelete = async (model) => { - if (!confirm(`Delete fallback chain for "${model}"?`)) return; + if (!confirm(t("deleteChainConfirm", { model }))) return; try { const res = await fetch("/api/fallback/chains", { method: "DELETE", diff --git a/src/app/(dashboard)/dashboard/settings/components/PoliciesPanel.tsx b/src/app/(dashboard)/dashboard/settings/components/PoliciesPanel.tsx index 459ea8544a..2ac4c6e451 100644 --- a/src/app/(dashboard)/dashboard/settings/components/PoliciesPanel.tsx +++ b/src/app/(dashboard)/dashboard/settings/components/PoliciesPanel.tsx @@ -11,6 +11,7 @@ import { useState, useEffect, useCallback } from "react"; import { Card, Button, EmptyState } from "@/shared/components"; import { useNotificationStore } from "@/store/notificationStore"; +import { useTranslations } from "next-intl"; const CB_STATUS = { closed: { icon: "check_circle", color: "#22c55e", label: "Closed" }, @@ -23,6 +24,7 @@ export default function PoliciesPanel() { const [loading, setLoading] = useState(true); const [unlocking, setUnlocking] = useState(null); const notify = useNotificationStore(); + const t = useTranslations("settings"); const fetchPolicies = useCallback(async () => { try { @@ -56,10 +58,10 @@ export default function PoliciesPanel() { notify.success(`Unlocked: ${identifier}`); await fetchPolicies(); } else { - notify.error("Failed to unlock"); + notify.error(t("failedUnlock")); } } catch { - notify.error("Failed to unlock"); + notify.error(t("failedUnlock")); } finally { setUnlocking(null); } @@ -70,7 +72,7 @@ export default function PoliciesPanel() {
security - Loading policies... + {t("loadingPolicies")}
); @@ -88,10 +90,8 @@ export default function PoliciesPanel() { verified_user
-

Policies & Circuit Breakers

-

- All systems operational — no lockouts or tripped breakers -

+

{t("policiesCircuitBreakers")}

+

{t("allOperational")}

@@ -106,8 +106,8 @@ export default function PoliciesPanel() { gpp_maybe
-

Policies & Circuit Breakers

-

Active issues detected

+

{t("policiesCircuitBreakers")}

+

{t("activeIssuesDetected")}

); diff --git a/src/app/(dashboard)/dashboard/settings/components/PricingTab.tsx b/src/app/(dashboard)/dashboard/settings/components/PricingTab.tsx index 1861a1be22..870b6281f6 100644 --- a/src/app/(dashboard)/dashboard/settings/components/PricingTab.tsx +++ b/src/app/(dashboard)/dashboard/settings/components/PricingTab.tsx @@ -142,7 +142,7 @@ export default function PricingTab() { ); const resetProvider = useCallback(async (providerAlias) => { - if (!confirm(`Reset all pricing for ${providerAlias.toUpperCase()} to defaults?`)) return; + if (!confirm(t("resetPricingConfirm", { provider: providerAlias.toUpperCase() }))) return; try { const response = await fetch(`/api/pricing?provider=${providerAlias}`, { method: "DELETE" }); if (response.ok) { @@ -187,9 +187,7 @@ export default function PricingTab() {

{t("modelPricing")}

-

- Configure cost rates per model • All rates in $/1M tokens -

+

{t("modelPricingDesc")}

@@ -290,15 +288,10 @@ export default function PricingTab() {

- Input: tokens sent to the model • Output: tokens - generated • Cached: reused input (~50% of input rate) •{" "} - Reasoning: thinking tokens (falls back to Output) •{" "} - Cache Write: creating cache entries (falls back to Input) -

-

- Cost = (input × input_rate) + (output × output_rate) + (cached × cached_rate) per - million tokens. + {t("pricingDescInput")} • {t("pricingDescOutput")} • {t("pricingDescCached")} •{" "} + {t("pricingDescReasoning")} • {t("pricingDescCacheWrite")}

+

{t("pricingDescFormula")}

diff --git a/src/app/(dashboard)/dashboard/settings/components/ResilienceTab.tsx b/src/app/(dashboard)/dashboard/settings/components/ResilienceTab.tsx index f10aa603fb..722a55895d 100644 --- a/src/app/(dashboard)/dashboard/settings/components/ResilienceTab.tsx +++ b/src/app/(dashboard)/dashboard/settings/components/ResilienceTab.tsx @@ -374,10 +374,10 @@ function PoliciesCard() { notify.success(`Unlocked: ${identifier}`); await fetchPolicies(); } else { - notify.error("Failed to unlock"); + notify.error(t("failedUnlock")); } } catch { - notify.error("Failed to unlock"); + notify.error(t("failedUnlock")); } finally { setUnlocking(null); } diff --git a/src/app/(dashboard)/dashboard/settings/components/ThinkingBudgetTab.tsx b/src/app/(dashboard)/dashboard/settings/components/ThinkingBudgetTab.tsx index 5b8bd14842..47003edf74 100644 --- a/src/app/(dashboard)/dashboard/settings/components/ThinkingBudgetTab.tsx +++ b/src/app/(dashboard)/dashboard/settings/components/ThinkingBudgetTab.tsx @@ -153,7 +153,7 @@ export default function ThinkingBudgetTab() { className="w-full accent-violet-500" />
- Off + {t("off")} 1K 10K 64K diff --git a/src/i18n/config.ts b/src/i18n/config.ts index 546b16bf85..aeee8ab609 100644 --- a/src/i18n/config.ts +++ b/src/i18n/config.ts @@ -9,7 +9,7 @@ export const LANGUAGES: readonly { flag: string; }[] = [ { code: "en", label: "EN", name: "English", flag: "🇺🇸" }, - { code: "pt-BR", label: "PT", name: "Português", flag: "🇧🇷" }, + { code: "pt-BR", label: "PT-BR", name: "Português (Brasil)", flag: "🇧🇷" }, ] as const; export const LOCALE_COOKIE = "NEXT_LOCALE"; diff --git a/src/i18n/messages/en.json b/src/i18n/messages/en.json index e97d2dc0f6..16679aab29 100644 --- a/src/i18n/messages/en.json +++ b/src/i18n/messages/en.json @@ -852,7 +852,31 @@ "models": "models", "withPricing": "with pricing configured", "loadingPricing": "Loading pricing data...", - "databaseSize": "Database Size" + "databaseSize": "Database Size", + "policiesCircuitBreakers": "Policies & Circuit Breakers", + "activeIssuesDetected": "Active issues detected", + "off": "Off", + "resetPricingConfirm": "Reset all pricing for {provider} to defaults?", + "pricingDescInput": "Input: tokens sent to the model", + "pricingDescOutput": "Output: tokens generated", + "pricingDescCached": "Cached: reused input (~50% of input rate)", + "pricingDescReasoning": "Reasoning: thinking tokens (falls back to Output)", + "pricingDescCacheWrite": "Cache Write: creating cache entries (falls back to Input)", + "pricingDescFormula": "Cost = (input × input_rate) + (output × output_rate) + (cached × cached_rate) per million tokens.", + "pricingSettingsTitle": "Pricing Settings", + "totalModels": "Total Models", + "active": "Active", + "costCalculation": "Cost Calculation", + "costCalculationDesc": "Costs are calculated based on token usage and pricing rates configured for each model.", + "pricingFormat": "Pricing Format", + "pricingFormatDesc": "All rates are in $/1M tokens (dollars per million tokens).", + "tokenTypes": "Token Types", + "inputTokenDesc": "Standard prompt tokens", + "outputTokenDesc": "Completion/response tokens", + "cachedTokenDesc": "Cached input tokens (typically 50% of input rate)", + "reasoningTokenDesc": "Special reasoning/thinking tokens (fallback to output rate)", + "cacheCreationTokenDesc": "Tokens used to create cache entries (fallback to input rate)", + "customPricingNote": "You can override default pricing for specific models. Custom overrides take priority over auto-detected pricing." }, "translator": { "title": "Translator", diff --git a/src/i18n/messages/pt-BR.json b/src/i18n/messages/pt-BR.json index 5b68be35f1..0f0b2990bc 100644 --- a/src/i18n/messages/pt-BR.json +++ b/src/i18n/messages/pt-BR.json @@ -852,7 +852,31 @@ "models": "modelos", "withPricing": "com preço configurado", "loadingPricing": "Carregando dados de preços...", - "databaseSize": "Tamanho do Banco de Dados" + "databaseSize": "Tamanho do Banco de Dados", + "policiesCircuitBreakers": "Políticas e Disjuntores", + "activeIssuesDetected": "Problemas ativos detectados", + "off": "Desligado", + "resetPricingConfirm": "Resetar todos os preços de {provider} para os padrões?", + "pricingDescInput": "Input: tokens enviados ao modelo", + "pricingDescOutput": "Output: tokens gerados", + "pricingDescCached": "Cached: input reutilizado (~50% da taxa de input)", + "pricingDescReasoning": "Reasoning: tokens de raciocínio (fallback para Output)", + "pricingDescCacheWrite": "Cache Write: criação de entradas de cache (fallback para Input)", + "pricingDescFormula": "Custo = (input × taxa_input) + (output × taxa_output) + (cached × taxa_cached) por milhão de tokens.", + "pricingSettingsTitle": "Configurações de Preços", + "totalModels": "Total de Modelos", + "active": "Ativo", + "costCalculation": "Cálculo de Custo", + "costCalculationDesc": "Custos são calculados com base no uso de tokens e taxas de preço configuradas para cada modelo.", + "pricingFormat": "Formato de Preços", + "pricingFormatDesc": "Todas as taxas são em $/1M tokens (dólares por milhão de tokens).", + "tokenTypes": "Tipos de Token", + "inputTokenDesc": "Tokens de prompt padrão", + "outputTokenDesc": "Tokens de conclusão/resposta", + "cachedTokenDesc": "Tokens de input em cache (tipicamente 50% da taxa de input)", + "reasoningTokenDesc": "Tokens especiais de raciocínio (fallback para taxa de output)", + "cacheCreationTokenDesc": "Tokens usados para criar entradas de cache (fallback para taxa de input)", + "customPricingNote": "Você pode sobrescrever preços padrão para modelos específicos. Sobrescritas personalizadas têm prioridade sobre preços detectados automaticamente." }, "translator": { "title": "Tradutor",