feat(i18n): Replace hardcoded strings with translation keys in support and donation components

Replaced hardcoded Portuguese text with next-intl translation keys in the support page, header, and donation card components to enable internationalization and support multiple languages. This improves the app's accessibility and localization capabilities.
This commit is contained in:
Evandro Fonseca Junior committed 2025-10-26 22:40:21 -03:00
1 parent 5ccc9120c4
commit bb6b320d1f
5 files changed
+196 -63

No files matched your search

+1 -1
View File
@@ -23,7 +23,7 @@ export default function Header() {
{ href: `/${locale}/market`, label: t("market") },
{ href: `/${locale}/sobre`, label: t("about") },
{ href: `/${locale}/precos`, label: t("prices") },
{ href: `/${locale}/apoiar`, label: "Apoiar", highlight: true },
{ href: `/${locale}/apoiar`, label: t("support"), highlight: true },
];
return (
+69 -54
View File
@@ -26,6 +26,7 @@ import {
DialogTitle,
} from "@/components/ui/dialog";
import { DonationTier, DonationResponse } from "@/types/donation";
import { useTranslations } from "next-intl";
interface DonationCardProps extends DonationTier {}
@@ -63,6 +64,8 @@ export function DonationCard({
const [paymentConfirmed, setPaymentConfirmed] = useState(false);
const [showThankYouModal, setShowThankYouModal] = useState(false);
const t = useTranslations("donation");
const icons = {
coffee: Coffee,
pizza: Pizza,
@@ -440,27 +443,31 @@ export function DonationCard({
htmlFor="customAmount"
className="text-sm text-muted-foreground"
>
Valor (R$)
{t("form.value")}
</label>
<Input
id="customAmount"
type="text"
inputMode="decimal"
placeholder="Ex: 15,50 ou 15.50"
placeholder={t("form.chooseAmount")}
value={customAmount}
onChange={handleCustomAmountChange}
className="text-lg text-center"
/>
<p className="text-xs text-muted-foreground">
Mín: R$ {customProduct.minAmount.toFixed(2)} | Máx: R${" "}
{customProduct.maxAmount.toFixed(2)}
{t("form.min")}: R$ {customProduct.minAmount.toFixed(2)} |{" "}
{t("form.max")}: R$ {customProduct.maxAmount.toFixed(2)}
</p>
</div>
{customAmount && !isValidCustomAmount() && (
<p className="text-xs text-red-500">
{parseFloat(customAmount) < customProduct.minAmount
? `Mínimo é R$ ${customProduct.minAmount.toFixed(2)}`
: `Máximo é R$ ${customProduct.maxAmount.toFixed(2)}`}
? `${t(
"form.minAmount"
)} ${customProduct.minAmount.toFixed(2)}`
: `${t(
"form.maxAmount"
)} ${customProduct.maxAmount.toFixed(2)}`}
</p>
)}
</div>
@@ -474,12 +481,14 @@ export function DonationCard({
{loading ? (
<>
<Loader2 className="mr-2 h-5 w-5 animate-spin" />
Processando...
{t("form.processing")}
</>
) : customAmount ? (
`Doar R$ ${parseFloat(customAmount || "0").toFixed(2)}`
`${t("form.donate")} ${parseFloat(
customAmount || "0"
).toFixed(2)}`
) : (
"Escolha o valor"
t("form.chooseAmount")
)}
</Button>
</>
@@ -500,10 +509,10 @@ export function DonationCard({
{loading ? (
<>
<Loader2 className="mr-2 h-5 w-5 animate-spin" />
Processando...
{t("form.processing")}
</>
) : (
"Apoiar com PIX"
t("form.supportWithPix")
)}
</Button>
</>
@@ -516,7 +525,7 @@ export function DonationCard({
<DialogContent className="max-w-4xl">
<DialogHeader>
<DialogTitle className="text-center text-2xl">
Como deseja contribuir?
{t("form.howToContribute")}
</DialogTitle>
</DialogHeader>
@@ -530,13 +539,15 @@ export function DonationCard({
<div className="p-2 rounded-full bg-muted">
<Lock className="h-5 w-5" />
</div>
<h3 className="text-xl font-bold">Doação Anônima</h3>
<h3 className="text-xl font-bold">
{t("form.anonymousTitle")}
</h3>
</div>
<p className="text-muted-foreground mb-4">
Rápido e sem cadastro. Gere o PIX imediatamente.
{t("form.anonymousDesc")}
</p>
<Button className="w-full" variant="outline" disabled={loading}>
Continuar Anônimo
{t("form.anonymousButton")}
</Button>
</div>
@@ -546,35 +557,37 @@ export function DonationCard({
onClick={handleIdentifiedClick}
>
<Badge className="absolute -top-3 right-6 bg-primary">
Recomendado
{t("form.recommended")}
</Badge>
<div className="flex items-center gap-3 mb-3">
<div className="p-2 rounded-full bg-primary/10">
<User className="h-5 w-5 text-primary" />
</div>
<h3 className="text-xl font-bold">Quero me Identificar</h3>
<h3 className="text-xl font-bold">
{t("form.identifiedTitle")}
</h3>
</div>
<p className="text-muted-foreground mb-4">
Ajude-nos a agradecer e oferecer benefícios
{t("form.identifiedDesc")}
</p>
<div className="space-y-2 mb-4">
<div className="flex items-center gap-2 text-sm text-muted-foreground">
<CheckCircle className="h-4 w-4 text-primary" />
<span>Agradecimento personalizado por email</span>
<span>{t("form.thankByEmail")}</span>
</div>
<div className="flex items-center gap-2 text-sm text-muted-foreground">
<CheckCircle className="h-4 w-4 text-primary" />
<span>Acesso antecipado a novos recursos</span>
<span>{t("form.earlyAccess")}</span>
</div>
<div className="flex items-center gap-2 text-sm text-muted-foreground">
<CheckCircle className="h-4 w-4 text-primary" />
<span>Histórico de suas contribuições</span>
<span>{t("form.contributionHistory")}</span>
</div>
</div>
<Button className="w-full" disabled={loading}>
Identificar-me
{t("form.identifyMe")}
</Button>
</div>
</div>
@@ -585,7 +598,7 @@ export function DonationCard({
<Dialog open={showDonorForm} onOpenChange={setShowDonorForm}>
<DialogContent className="max-w-md">
<DialogHeader>
<DialogTitle>Informações para Doação</DialogTitle>
<DialogTitle>{t("form.donorInfo")}</DialogTitle>
</DialogHeader>
<div className="space-y-4">
@@ -597,47 +610,51 @@ export function DonationCard({
<div>
<label className="text-sm font-medium mb-2 block">
Nome *{" "}
{t("form.name")}{" "}
<span className="text-muted-foreground text-xs">
(min. 3 caracteres)
({t("form.nameHint")})
</span>
</label>
<Input
value={donorName}
onChange={(e) => setDonorName(e.target.value)}
placeholder="Seu nome ou apelido"
placeholder={t("form.namePlaceholder")}
maxLength={50}
/>
</div>
<div>
<label className="text-sm font-medium mb-2 block">Email *</label>
<label className="text-sm font-medium mb-2 block">
{t("form.email")}
</label>
<Input
type="email"
value={donorEmail}
onChange={(e) => setDonorEmail(e.target.value)}
placeholder="[email protected]"
placeholder={t("form.emailPlaceholder")}
/>
</div>
<div>
<label className="text-sm font-medium mb-2 block">
Telefone *{" "}
<span className="text-muted-foreground text-xs">(com DDD)</span>
{t("form.phone")}{" "}
<span className="text-muted-foreground text-xs">
({t("form.phoneHint")})
</span>
</label>
<Input
value={donorPhone}
onChange={(e) => setDonorPhone(formatPhone(e.target.value))}
placeholder="(11) 98888-7777"
placeholder={t("form.phonePlaceholder")}
maxLength={15}
/>
</div>
<div>
<label className="text-sm font-medium mb-2 block">
CPF/CNPJ *{" "}
{t("form.taxId")}{" "}
<span className="text-muted-foreground text-xs">
(formato automático)
({t("form.taxIdHint")})
</span>
</label>
<Input
@@ -650,16 +667,16 @@ export function DonationCard({
setDonorTaxId(formatCNPJ(value));
}
}}
placeholder="000.000.000-00 ou 00.000.000/0000-00"
placeholder={t("form.taxIdPlaceholder")}
maxLength={18}
/>
</div>
<div>
<label className="text-sm font-medium mb-2 block">
Mensagem{" "}
{t("form.message")}{" "}
<span className="text-muted-foreground text-xs">
(opcional, máx. 280 chars)
({t("form.messageHint")})
</span>
</label>
<Textarea
@@ -669,7 +686,7 @@ export function DonationCard({
setDonorMessage(e.target.value);
}
}}
placeholder="Deixe uma mensagem para a equipe..."
placeholder={t("form.messagePlaceholder")}
rows={3}
maxLength={280}
/>
@@ -689,7 +706,7 @@ export function DonationCard({
className="flex-1"
disabled={loading}
>
Voltar
{t("form.close")}
</Button>
<Button
onClick={handleSubmitForm}
@@ -699,10 +716,10 @@ export function DonationCard({
{loading ? (
<>
<Loader2 className="mr-2 h-4 w-4 animate-spin" />
Processando...
{t("form.processing")}
</>
) : (
"Gerar PIX"
t("form.generatePix")
)}
</Button>
</div>
@@ -715,7 +732,7 @@ export function DonationCard({
<DialogContent className="max-w-md">
<DialogHeader>
<DialogTitle className="text-center">
Escaneie o QR Code para Pagar
{t("form.qrTitle")}
</DialogTitle>
</DialogHeader>
@@ -731,7 +748,7 @@ export function DonationCard({
<div className="space-y-2">
<p className="text-sm text-muted-foreground text-center">
Ou copie o código PIX:
{t("form.copyCode")}
</p>
<div className="flex gap-2">
<Input
@@ -747,12 +764,12 @@ export function DonationCard({
{copied ? (
<>
<Check className="h-4 w-4" />
Copiado!
{t("form.copied")}
</>
) : (
<>
<Copy className="h-4 w-4" />
Copiar
{t("form.copy")}
</>
)}
</Button>
@@ -761,7 +778,7 @@ export function DonationCard({
{timeRemaining && (
<p className="text-xs text-center text-muted-foreground">
⏱️ Tempo restante: {timeRemaining}
⏱️ {t("form.remainingTime")} {timeRemaining}
</p>
)}
@@ -771,13 +788,13 @@ export function DonationCard({
variant="outline"
className="flex-1"
>
Fechar
{t("form.close")}
</Button>
<Button
onClick={() => (window.location.href = "/apoiar/obrigado")}
className="flex-1"
>
Já Paguei
{t("form.paid")}
</Button>
</div>
</div>
@@ -802,19 +819,17 @@ export function DonationCard({
{/* Título e mensagem */}
<div>
<h2 className="text-2xl font-bold mb-2">
Pagamento Confirmado! 🎉
{t("form.paymentConfirmed")} 🎉
</h2>
<p className="text-muted-foreground">
Obrigado pela sua contribuição! Cada doação nos ajuda a manter o
projeto funcionando.
{t("form.paymentConfirmedDesc")}
</p>
</div>
{/* Mensagem especial */}
<div className="p-4 rounded-lg bg-primary/5 border border-primary/20">
<p className="text-sm text-muted-foreground">
Sua doação faz toda a diferença para nossa comunidade. Muito
obrigado pelo apoio! ❤️
{t("form.contributionMatters")} ❤️
</p>
</div>
@@ -828,7 +843,7 @@ export function DonationCard({
className="flex-1"
size="lg"
>
Ver Página de Agradecimento
{t("form.viewThankYouPage")}
</Button>
<Button
onClick={() => {
@@ -839,7 +854,7 @@ export function DonationCard({
className="flex-1"
size="lg"
>
Voltar ao Início
{t("form.backToHome")}
</Button>
</div>
</div>