i18n: traducir toda la app (ES + EN) — páginas y componentes con texto hardcodeado
Se externaliza el texto español hardcodeado de ~55 archivos a next-intl y se añaden traducciones al inglés, con paridad de claves es/en. Nuevos namespaces: History, CharService, CharServiceB, Points, Legal, UI, Misc (+ altas en Common/Admin). - Historiales (PD/PV, transacciones, sanciones, seguridad), servicios de personaje (transfer, send-gift, quest, restore-*, change-*, customize, level-up, gold, rename), PD/pagos (d-points, trade, promo, transfer-dp, rename-guild, DPointsTabs), páginas legales (cookies, privacidad, términos, reembolsos, aviso legal, contacto), layout (cabecera, footer, cookies, 2FA, descargas, jugadores, recluta) y páginas varias (home, reino, ayuda, addons, 2falogin). - Textos con markup inline via t.rich; interpolación con ICU. - Componente <NoteLegend/> para la leyenda NOTA/NOTE compartida. - payLabel/confirmText de los servicios de pago traducidos. - Verificado: tsc OK, next build OK, todas las claves t() resuelven en es y en, todos los t.rich casan etiquetas, páginas 200 en /es/ y /en/ sin claves crudas. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
'use client'
|
||||
|
||||
import { useEffect, useState } from 'react'
|
||||
import { useTranslations } from 'next-intl'
|
||||
import { Link } from '@/i18n/navigation'
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
@@ -93,6 +94,7 @@ function revokeConsent() {
|
||||
// Banner de consentimiento (fijo abajo, en todo el sitio).
|
||||
// ---------------------------------------------------------------------------
|
||||
export function CookieBanner() {
|
||||
const t = useTranslations('UI')
|
||||
const [visible, setVisible] = useState(false)
|
||||
const [details, setDetails] = useState(false)
|
||||
// Estado de los checkboxes granulares (categorías no necesarias).
|
||||
@@ -129,45 +131,45 @@ export function CookieBanner() {
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="uw-cookie-content" role="dialog" aria-label="Consentimiento de cookies">
|
||||
<div className="uw-cookie-content" role="dialog" aria-label={t('cookie.dialogLabel')}>
|
||||
<div className="uw-cookie-text">
|
||||
<h3>Utilizamos cookies</h3>
|
||||
<p>Este sitio utiliza cookies propias y de terceros para garantizar el funcionamiento del sitio, analizar el tráfico y ofrecerte publicidad personalizada. Consulta nuestra política de cookies para más información.</p>
|
||||
<Link href="/cookies" className="uw-cookie-link">Política de Cookies</Link>
|
||||
<h3>{t('cookie.title')}</h3>
|
||||
<p>{t('cookie.description')}</p>
|
||||
<Link href="/cookies" className="uw-cookie-link">{t('cookie.policyLink')}</Link>
|
||||
|
||||
{details && (
|
||||
<div className="uw-cookie-details" style={{ display: 'block' }}>
|
||||
<div className="uw-cookie-category">
|
||||
<label>
|
||||
<input type="checkbox" checked disabled readOnly />
|
||||
<span className="uw-cookie-cat-name">Necesarias</span>
|
||||
<span className="uw-cookie-cat-name">{t('cookie.catNecessary')}</span>
|
||||
</label>
|
||||
<p>Esenciales para el funcionamiento del sitio. No se pueden desactivar.</p>
|
||||
<p>{t('cookie.descNecessary')}</p>
|
||||
</div>
|
||||
<div className="uw-cookie-category">
|
||||
<label>
|
||||
<input type="checkbox" id="uw-cookie-analytics" checked={!!prefs.analytics} onChange={(e) => setPrefs((s) => ({ ...s, analytics: e.target.checked }))} />
|
||||
<span className="uw-cookie-cat-name">Analíticas</span>
|
||||
<span className="uw-cookie-cat-name">{t('cookie.catAnalytics')}</span>
|
||||
</label>
|
||||
<p>Nos ayudan a entender cómo usas el sitio para mejorarlo.</p>
|
||||
<p>{t('cookie.descAnalytics')}</p>
|
||||
</div>
|
||||
<div className="uw-cookie-category">
|
||||
<label>
|
||||
<input type="checkbox" id="uw-cookie-marketing" checked={!!prefs.marketing} onChange={(e) => setPrefs((s) => ({ ...s, marketing: e.target.checked }))} />
|
||||
<span className="uw-cookie-cat-name">Marketing</span>
|
||||
<span className="uw-cookie-cat-name">{t('cookie.catMarketing')}</span>
|
||||
</label>
|
||||
<p>Se utilizan para mostrarte anuncios relevantes.</p>
|
||||
<p>{t('cookie.descMarketing')}</p>
|
||||
</div>
|
||||
<div className="uw-cookie-actions-detail">
|
||||
<button type="button" className="uw-cookie-btn uw-cookie-btn-save" data-action="save" onClick={savePrefs}>Guardar preferencias</button>
|
||||
<button type="button" className="uw-cookie-btn uw-cookie-btn-save" data-action="save" onClick={savePrefs}>{t('cookie.savePrefs')}</button>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<div className="uw-cookie-actions">
|
||||
<button type="button" className="uw-cookie-btn uw-cookie-btn-reject" data-action="reject" onClick={() => { rejectAll(); setVisible(false) }}>Rechazar</button>
|
||||
<button type="button" className="uw-cookie-btn uw-cookie-btn-customize" data-action="customize" onClick={() => setDetails((v) => !v)}>Personalizar</button>
|
||||
<button type="button" className="uw-cookie-btn uw-cookie-btn-accept" data-action="accept" onClick={() => { acceptAll(); setVisible(false) }}>Aceptar todas</button>
|
||||
<button type="button" className="uw-cookie-btn uw-cookie-btn-reject" data-action="reject" onClick={() => { rejectAll(); setVisible(false) }}>{t('cookie.reject')}</button>
|
||||
<button type="button" className="uw-cookie-btn uw-cookie-btn-customize" data-action="customize" onClick={() => setDetails((v) => !v)}>{t('cookie.customize')}</button>
|
||||
<button type="button" className="uw-cookie-btn uw-cookie-btn-accept" data-action="accept" onClick={() => { acceptAll(); setVisible(false) }}>{t('cookie.acceptAll')}</button>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
@@ -177,16 +179,17 @@ export function CookieBanner() {
|
||||
// Botones «Cambiar / Retirar consentimiento» de la página /cookies.
|
||||
// ---------------------------------------------------------------------------
|
||||
export function CookieConsentButtons() {
|
||||
const t = useTranslations('UI')
|
||||
useEffect(() => {
|
||||
window.UWCookies = { showBanner, revokeConsent, acceptAll, rejectAll }
|
||||
}, [])
|
||||
return (
|
||||
<div className="uw-consent-buttons">
|
||||
<button type="button" onClick={showBanner} className="btn-uw btn-uw-form">
|
||||
Cambiar consentimiento
|
||||
{t('cookie.changeConsent')}
|
||||
</button>
|
||||
<button type="button" onClick={revokeConsent} className="btn-uw btn-uw-form btn-uw-secondary">
|
||||
Retirar consentimiento
|
||||
{t('cookie.revokeConsent')}
|
||||
</button>
|
||||
</div>
|
||||
)
|
||||
@@ -197,6 +200,7 @@ export function CookieConsentButtons() {
|
||||
// (o, si Zaraz no está, la preferencia guardada en la cookie uw_cookie_consent).
|
||||
// ---------------------------------------------------------------------------
|
||||
export function ConsentStatus() {
|
||||
const t = useTranslations('UI')
|
||||
const [state, setState] = useState<{ source: string; values: Consent | null }>({
|
||||
source: 'cookie',
|
||||
values: null,
|
||||
@@ -224,15 +228,20 @@ export function ConsentStatus() {
|
||||
|
||||
const zarazData = state.source === 'zaraz' && state.values
|
||||
const values = state.values
|
||||
const catLabel: Record<string, string> = {
|
||||
necessary: t('cookie.catNecessary'),
|
||||
analytics: t('cookie.catAnalytics'),
|
||||
marketing: t('cookie.catMarketing'),
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="uw-consent-status">
|
||||
<p className="uw-consent-source">
|
||||
{zarazData
|
||||
? 'Estado actual (Cloudflare Zaraz Consent API):'
|
||||
? t('cookie.statusZaraz')
|
||||
: values
|
||||
? 'Estado actual (preferencia guardada):'
|
||||
: 'Cloudflare Zaraz no está disponible en este dominio; aún no hay preferencia guardada.'}
|
||||
? t('cookie.statusSaved')
|
||||
: t('cookie.statusUnavailable')}
|
||||
</p>
|
||||
<ul>
|
||||
{zarazData ? (
|
||||
@@ -241,7 +250,7 @@ export function ConsentStatus() {
|
||||
<li key={purpose}>
|
||||
<span>{purpose}</span>
|
||||
<span className={granted ? 'uw-consent-on' : 'uw-consent-off'}>
|
||||
{granted ? 'Aceptada' : 'Rechazada'}
|
||||
{granted ? t('cookie.accepted') : t('cookie.rejected')}
|
||||
</span>
|
||||
</li>
|
||||
))
|
||||
@@ -251,9 +260,9 @@ export function ConsentStatus() {
|
||||
const on = cat.always || Boolean(values?.[cat.key])
|
||||
return (
|
||||
<li key={cat.key}>
|
||||
<span>{cat.label}</span>
|
||||
<span>{catLabel[cat.key] ?? cat.label}</span>
|
||||
<span className={cat.always ? 'uw-consent-always' : on ? 'uw-consent-on' : 'uw-consent-off'}>
|
||||
{cat.always ? 'Siempre activas' : values ? (on ? 'Aceptada' : 'Rechazada') : '—'}
|
||||
{cat.always ? t('cookie.alwaysOn') : values ? (on ? t('cookie.accepted') : t('cookie.rejected')) : '—'}
|
||||
</span>
|
||||
</li>
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user