From 651d8deafcf8ed707c1e71d7b60d436af8aef732 Mon Sep 17 00:00:00 2001 From: adevopg Date: Tue, 14 Jul 2026 18:58:54 +0000 Subject: [PATCH] =?UTF-8?q?i18n:=20traducir=20toda=20la=20app=20(ES=20+=20?= =?UTF-8?q?EN)=20=E2=80=94=20p=C3=A1ginas=20y=20componentes=20con=20texto?= =?UTF-8?q?=20hardcodeado?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 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) --- web-next/app/[locale]/[realm]/page.tsx | 5 +- web-next/app/[locale]/ban-history/page.tsx | 44 +- .../change-faction-character/page.tsx | 59 +- .../[locale]/change-race-character/page.tsx | 38 +- web-next/app/[locale]/contact-us/page.tsx | 22 +- web-next/app/[locale]/cookies/page.tsx | 166 +-- .../app/[locale]/customize-character/page.tsx | 45 +- .../app/[locale]/d-points-success/page.tsx | 13 +- web-next/app/[locale]/d-points/page.tsx | 5 +- .../app/[locale]/download-addons/page.tsx | 44 +- web-next/app/[locale]/gold-character/page.tsx | 24 +- web-next/app/[locale]/help/page.tsx | 113 +- web-next/app/[locale]/legal-notice/page.tsx | 18 +- .../app/[locale]/level-up-character/page.tsx | 31 +- web-next/app/[locale]/page.tsx | 37 +- web-next/app/[locale]/points-history/page.tsx | 28 +- web-next/app/[locale]/privacy-policy/page.tsx | 64 +- web-next/app/[locale]/promo-code/page.tsx | 18 +- .../app/[locale]/quest-character/page.tsx | 50 +- web-next/app/[locale]/refund-policy/page.tsx | 102 +- .../app/[locale]/rename-character/page.tsx | 28 +- web-next/app/[locale]/rename-guild/page.tsx | 33 +- .../app/[locale]/restore-character/page.tsx | 26 +- web-next/app/[locale]/restore-items/page.tsx | 33 +- .../app/[locale]/security-2falogin/page.tsx | 37 +- .../app/[locale]/security-history/page.tsx | 51 +- web-next/app/[locale]/security-token/page.tsx | 3 +- web-next/app/[locale]/send-gift/page.tsx | 27 +- .../[locale]/terms-and-conditions/page.tsx | 110 +- web-next/app/[locale]/trade-points/page.tsx | 66 +- web-next/app/[locale]/trans-history/page.tsx | 39 +- .../app/[locale]/transfer-character/page.tsx | 34 +- .../app/[locale]/transfer-d-points/page.tsx | 24 +- .../app/[locale]/unstuck-character/page.tsx | 3 +- web-next/components/ClientDownload.tsx | 118 +- web-next/components/CookieConsent.tsx | 53 +- web-next/components/DPointsTabs.tsx | 171 +-- web-next/components/Footer.tsx | 18 +- web-next/components/NoteLegend.tsx | 7 + web-next/components/PlayersBoard.tsx | 56 +- web-next/components/PromoCodeForm.tsx | 26 +- web-next/components/QuestTrackerForm.tsx | 52 +- web-next/components/RealmInfo.tsx | 37 +- web-next/components/RecruitPanel.tsx | 48 +- web-next/components/RenameGuildForm.tsx | 30 +- web-next/components/RestoreCharacterForm.tsx | 36 +- web-next/components/RestoreItemsForm.tsx | 42 +- web-next/components/ReviveServiceContent.tsx | 3 +- web-next/components/SendGiftForm.tsx | 44 +- web-next/components/SiteHeader.tsx | 35 +- web-next/components/Social.tsx | 7 +- web-next/components/TradePointsForm.tsx | 100 +- web-next/components/TransferDPointsForm.tsx | 31 +- web-next/components/TransferForm.tsx | 20 +- web-next/components/TwoFactorLogin.tsx | 40 +- web-next/messages/en.json | 1146 ++++++++++++++++- web-next/messages/es.json | 1146 ++++++++++++++++- 57 files changed, 3516 insertions(+), 1190 deletions(-) create mode 100644 web-next/components/NoteLegend.tsx diff --git a/web-next/app/[locale]/[realm]/page.tsx b/web-next/app/[locale]/[realm]/page.tsx index 2dc3592..2574779 100644 --- a/web-next/app/[locale]/[realm]/page.tsx +++ b/web-next/app/[locale]/[realm]/page.tsx @@ -1,5 +1,5 @@ import type { Metadata } from 'next' -import { setRequestLocale } from 'next-intl/server' +import { getTranslations, setRequestLocale } from 'next-intl/server' import { notFound } from 'next/navigation' import { getRealmName, realmSlug } from '@/lib/realm' import { RealmInfo } from '@/components/RealmInfo' @@ -38,10 +38,11 @@ export default async function RealmPage({ }) { const { locale, realm } = await params setRequestLocale(locale) + const t = await getTranslations('Misc') const r = await resolve(realm) if (!r) notFound() - const heading = r.kind === 'players' ? 'Personajes' : 'Reino' + const heading = r.kind === 'players' ? t('realm.charactersHeading') : t('realm.realmHeading') return (
diff --git a/web-next/app/[locale]/ban-history/page.tsx b/web-next/app/[locale]/ban-history/page.tsx index a2e574f..332fe5d 100644 --- a/web-next/app/[locale]/ban-history/page.tsx +++ b/web-next/app/[locale]/ban-history/page.tsx @@ -1,5 +1,5 @@ import type { Metadata } from 'next' -import { setRequestLocale } from 'next-intl/server' +import { setRequestLocale, getTranslations } from 'next-intl/server' import { redirect, Link } from '@/i18n/navigation' import { getSession } from '@/lib/session' import { getSanctions, type Sanction } from '@/lib/ban-history' @@ -21,7 +21,7 @@ function StatusCell({ s }: { s: Sanction }) { } /** Caja con la tabla de sanciones (baneos o muteos), o el vacío del diseño. */ -function SanctionBox({ +async function SanctionBox({ title, emptyText, rows, @@ -32,6 +32,7 @@ function SanctionBox({ rows: Sanction[] showScope: boolean }) { + const t = await getTranslations('History') return (
@@ -52,12 +53,12 @@ function SanctionBox({ - {showScope && } - - - - - + {showScope && } + + + + + {rows.map((s, i) => ( @@ -76,7 +77,7 @@ function SanctionBox({ {fmt(s.date)} diff --git a/web-next/app/[locale]/gold-character/page.tsx b/web-next/app/[locale]/gold-character/page.tsx index 0a8f349..a621da4 100644 --- a/web-next/app/[locale]/gold-character/page.tsx +++ b/web-next/app/[locale]/gold-character/page.tsx @@ -1,5 +1,5 @@ import type { Metadata } from 'next' -import { setRequestLocale } from 'next-intl/server' +import { getTranslations, setRequestLocale } from 'next-intl/server' import { redirect } from '@/i18n/navigation' import { getSession } from '@/lib/session' import { getGameCharacters } from '@/lib/characters' @@ -24,34 +24,28 @@ export default async function GoldCharacterPage({ params }: { params: Promise<{ const [chars, options] = await Promise.all([getGameCharacters(session.accountId!), getGoldOptions()]) + const t = await getTranslations('CharServiceB.gold') + return (
-

- La herramienta Adquirir oro te permite enviar oro a un personaje. -

+

{t.rich('intro', { s: (c) => {c} })}


-

- Al usar el botón ENVIAR ORO del personaje que hayas escogido, se enviará un correo con la cantidad de oro - elegida al personaje. -

-

Cuando entres al reino con dicho personaje, tendrás el mensaje con la cantidad de oro seleccionada en tu buzón.

+

{t('instructions')}

+

{t('mailInfo')}


- NOTA + {t('noteLegend')}
-

- Por favor, asegúrate de haber escogido al personaje correcto ya que esta acción no es reversible una vez - realizada. -

+

{t('noteConfirm')}



-

Requiere

+

{t('requiresLabel')}

AlcanceMotivoSancionado porFechaExpiraEstado{t('ban.thScope')}{t('ban.thReason')}{t('ban.thBy')}{t('ban.thDate')}{t('ban.thExpires')}{t('ban.thStatus')}
- {s.expires ? fmt(s.expires) : 'Permanente'} + {s.expires ? fmt(s.expires) : t('ban.permanent')} @@ -94,6 +95,7 @@ function SanctionBox({ export default async function BanHistoryPage({ params }: { params: Promise<{ locale: string }> }) { const { locale } = await params setRequestLocale(locale) + const t = await getTranslations('History') const session = await getSession() if (!session.bnetId) redirect({ href: '/login', locale }) @@ -102,38 +104,34 @@ export default async function BanHistoryPage({ params }: { params: Promise<{ loc const { bans, mutes } = await getSanctions(session.accountId!, session.bnetId) return ( - +
-

Aquí podrás ver todas las sanciones que ha tenido la cuenta.

+

{t('ban.intro1')}

- Si tienes una sanción vigente, verás que su estado indica Activo. + {t.rich('ban.intro2', { s: (c) => {c} })}

-

Para evitar que tu cuenta sea sancionada, recuerda respetar las normas de nuestro servidor.

+

{t('ban.intro3')}


- Importante: + {t('ban.important')}

- Si tu cuenta aparece como sancionada o cerrada al intentar ingresar al reino, pero tu historial no tiene - ninguna sanción activa, significa que has tenido un bloqueo automático temporal por demasiados intentos de - inicio de sesión fallidos. + {t('ban.autoBlock1')}

- Espera al menos 10 minutos para volver a intentar y asegúrate de usar nombre de cuenta y contraseña - correctas. + {t('ban.autoBlock2')}


- Para realizar un reclamo de sanción, por favor ingresa en nuestro foro y visita la - sección Reclamaciones. + {t.rich('ban.claim', { link: (c) => {c} })}

- - + +
) } diff --git a/web-next/app/[locale]/change-faction-character/page.tsx b/web-next/app/[locale]/change-faction-character/page.tsx index fdc6afe..79d325c 100644 --- a/web-next/app/[locale]/change-faction-character/page.tsx +++ b/web-next/app/[locale]/change-faction-character/page.tsx @@ -1,5 +1,5 @@ import type { Metadata } from 'next' -import { setRequestLocale } from 'next-intl/server' +import { getTranslations, setRequestLocale } from 'next-intl/server' import { redirect } from '@/i18n/navigation' import { getSession } from '@/lib/session' import { getGameCharacters } from '@/lib/characters' @@ -34,34 +34,33 @@ export default async function ChangeFactionCharacterPage({ params }: { params: P const [chars, price] = await Promise.all([getGameCharacters(session.accountId!), getChangeFactionPrice()]) + const t = await getTranslations('CharServiceB.changeFaction') + return (
-

- La herramienta Cambiar facción del personaje te permite cambiar de la Alianza a la Horda y - viceversa. -

-

Si también deseas cambiar el nombre del personaje, debes usar la herramienta Renombrar personaje.

+

{t.rich('intro', { s: (c) => {c} })}

+

{t('alsoRename')}


-

Al hacer un cambio de Facción:

-

- Los items, hechizos, títulos, reputaciones, monturas y logros se cambiarán a la nueva facción

-

- Las misiones activas en el Registro de misiones serán abandonadas

-

- Los teams de arena serán borrados

-

- Los amigos en la Lista de amigos se borrarán

+

{t('onChange')}

+

{t('change1')}

+

{t('change2')}

+

{t('change3')}

+

{t('change4')}


-

Restricciones del personaje:

-

- No debe tener subastas activas

-

- No debe tener correos en el buzón

-

- No debe ser capitán de un team de arenas

-

- No debe ser miembro de una hermandad

-

- No debe tener demasiado oro

+

{t('restrictionsTitle')}

+

{t('restriction1')}

+

{t('restriction2')}

+

{t('restriction3')}

+

{t('restriction4')}

+

{t('restriction5')}


- - + + @@ -70,36 +69,30 @@ export default async function ChangeFactionCharacterPage({ params }: { params: P
NivelMax. Oro{t('tableLevel')}{t('tableMaxGold')}
10-30
31-50

-

- Al usar el botón CAMBIAR FACCIÓN del personaje que hayas escogido, se enviará una petición de cambio de - facción de dicho personaje. -

-

Cuando ingreses a la lista de personajes de tu cuenta, verás un ícono a la izquierda de tu personaje escogido.

-

Al darle click a dicho ícono ingresarás al menú de edición de personaje que te permitirá pasar a la facción contraria.

+

{t('instructions')}

+

{t('iconInfo')}

+

{t('iconClick')}


- NOTA + {t('noteLegend')}
-

- Por favor, asegúrate de haber escogido al personaje correcto ya que esta acción no es reversible una vez - realizada. -

+

{t('noteConfirm')}



-

Requiere {price} (SumUp)

+

{t.rich('requires', { price, s: (c) => {c}, y: (c) => {c} })}

({ name: c.name, classCss: c.classCss }))} checkoutEndpoint="/api/character/change-faction/checkout" - payLabel="CAMBIAR FACCIÓN" + payLabel={t('payLabel')} buttonClass="change-faction-button" provider="sumup" - confirmText={`¿Estás seguro de cambiar de facción al personaje seleccionado por ${price} € (SumUp)?`} + confirmText={t('confirm', { price })} />
diff --git a/web-next/app/[locale]/change-race-character/page.tsx b/web-next/app/[locale]/change-race-character/page.tsx index fe07e5e..5fb6331 100644 --- a/web-next/app/[locale]/change-race-character/page.tsx +++ b/web-next/app/[locale]/change-race-character/page.tsx @@ -1,5 +1,5 @@ import type { Metadata } from 'next' -import { setRequestLocale } from 'next-intl/server' +import { getTranslations, setRequestLocale } from 'next-intl/server' import { redirect } from '@/i18n/navigation' import { getSession } from '@/lib/session' import { getGameCharacters } from '@/lib/characters' @@ -22,53 +22,43 @@ export default async function ChangeRaceCharacterPage({ params }: { params: Prom const [chars, price] = await Promise.all([getGameCharacters(session.accountId!), getChangeRacePrice()]) + const t = await getTranslations('CharServiceB.changeRace') + return (

- ESTE CAMBIO NO PERMITE CAMBIAR A LA FACCIÓN CONTRARIA{' '} + {t('warning')}{' '}

-

- La herramienta Cambiar raza del personaje te permite cambiar la raza del personaje entre otras de - la MISMA facción. -

-

Si también deseas cambiar el nombre del personaje, debes usar la herramienta Renombrar personaje.

+

{t.rich('intro', { s: (c) => {c} })}

+

{t('alsoRename')}


-

- Al usar el botón CAMBIAR RAZA del personaje que hayas escogido, se enviará una petición de cambio de raza de - dicho personaje. -

-

Cuando ingreses a la lista de personajes de tu cuenta, verás un ícono a la izquierda de tu personaje escogido.

-

- Al darle click a dicho ícono ingresarás al menú de edición de personaje que te permitirá escoger entre las - razas de la misma facción. -

+

{t('instructions')}

+

{t('iconInfo')}

+

{t('iconClick')}


- NOTA + {t('noteLegend')}
-

- Por favor, asegúrate de haber escogido al personaje correcto ya que esta acción no es reversible una vez - realizada. -

+

{t('noteConfirm')}



-

Requiere {price} (SumUp)

+

{t.rich('requires', { price, s: (c) => {c}, y: (c) => {c} })}

({ name: c.name, classCss: c.classCss }))} checkoutEndpoint="/api/character/change-race/checkout" - payLabel="CAMBIAR RAZA" + payLabel={t('payLabel')} buttonClass="change-race-button" provider="sumup" - confirmText={`¿Estás seguro de cambiar de raza al personaje seleccionado por ${price} € (SumUp)?`} + confirmText={t('confirm', { price })} />
diff --git a/web-next/app/[locale]/contact-us/page.tsx b/web-next/app/[locale]/contact-us/page.tsx index bf85ce3..c716ee1 100644 --- a/web-next/app/[locale]/contact-us/page.tsx +++ b/web-next/app/[locale]/contact-us/page.tsx @@ -1,31 +1,33 @@ import type { Metadata } from 'next' +import { getTranslations } from 'next-intl/server' export const metadata: Metadata = { title: 'Contáctanos', } -export default function ContactUsPage() { +export default async function ContactUsPage() { + const t = await getTranslations('Legal') return (
-

Contáctanos

+

{t('contact.title')}

-

¡Gracias por tu interés en contactar con nosotros!

-

Si tienes alguna pregunta, consulta o comentario, estaremos encantados de ayudarte. Por favor, envía un correo electrónico a la siguiente dirección:

+

{t('contact.p1')}

+

{t('contact.p2')}

contacto@ultimowow.com


-

Error 404 es la empresa que representa el servicio de UltimoWoW.

-

Nos esforzamos por responder a todos los mensajes en un plazo de 48 horas hábiles.

-

Asegúrate de incluir la información relevante en tu correo para que podamos brindarte una respuesta precisa y oportuna.

+

{t('contact.p3')}

+

{t('contact.p4')}

+

{t('contact.p5')}


-

En Error 404, valoramos tus comentarios y opiniones. Tu satisfacción es nuestra prioridad y nos esforzamos por brindarte la mejor experiencia posible en UltimoWoW.

-

¡Esperamos tener noticias tuyas pronto!

+

{t('contact.p6')}

+

{t('contact.p7')}


-

Atentamente, el equipo de Error 404.

+

{t('contact.p8')}

diff --git a/web-next/app/[locale]/cookies/page.tsx b/web-next/app/[locale]/cookies/page.tsx index 0150fdb..9fb72eb 100644 --- a/web-next/app/[locale]/cookies/page.tsx +++ b/web-next/app/[locale]/cookies/page.tsx @@ -1,4 +1,5 @@ import type { Metadata } from 'next' +import { getTranslations } from 'next-intl/server' import { Link } from '@/i18n/navigation' import { CookieConsentButtons, ConsentStatus } from '@/components/CookieConsent' @@ -6,172 +7,173 @@ export const metadata: Metadata = { title: 'Declaración de Cookies', } -export default function CookiesPage() { +export default async function CookiesPage() { + const t = await getTranslations('Legal') return (
-

Declaración de Cookies

+

{t('cookies.title')}

-

Esta página web usa cookies. Las cookies de este sitio web se usan para personalizar el contenido y los anuncios, ofrecer funciones de redes sociales y analizar el tráfico. Además, compartimos información sobre el uso que haga del sitio web con nuestros partners de redes sociales, publicidad y análisis web, quienes pueden combinarla con otra información que les haya proporcionado o que hayan recopilado a partir del uso que haya hecho de sus servicios.

+

{t('cookies.p1')}


-

Las cookies son pequeños archivos de texto que las páginas web pueden utilizar para hacer más eficiente la experiencia del usuario.

-

La ley afirma que podemos almacenar cookies en tu dispositivo si son estrictamente necesarias para el funcionamiento de esta página. Para todos los demás tipos de cookies necesitamos tu permiso.

+

{t('cookies.p2')}

+

{t('cookies.p3')}


-

Esta página utiliza tipos diferentes de cookies. Algunas cookies son colocadas por servicios de terceros que aparecen en nuestras páginas.

-

En cualquier momento puedes cambiar o retirar tu consentimiento desde esta Declaración de cookies en nuestro sitio web.

+

{t('cookies.p4')}

+

{t('cookies.p5')}


-

Obten más información sobre quiénes somos, cómo puedes contactarnos y cómo procesamos los datos personales en nuestra Política de Privacidad.

+

{t.rich('cookies.p6', { link: (c) => {c} })}




- Tipos de cookies que utilizamos + {t('cookies.h1cat')}
- Cookies Necesarias -

Las cookies necesarias ayudan a hacer una página web utilizable activando funciones básicas como la navegación en la página y el acceso a áreas seguras de la página web. La página web no puede funcionar adecuadamente sin estas cookies.

+ {t('cookies.necessaryTitle')} +

{t('cookies.necessaryDesc')}

- - - - + + + + - - - - - - - - - - - + + + + + + + + + + +
CookieProveedorPropósitoDuración{t('cookies.thCookie')}{t('cookies.thProvider')}{t('cookies.thPurpose')}{t('cookies.thDuration')}
PHPSESSIDUltimoWoWMantiene el estado de la sesión del usuario entre páginas. Presente en ultimowow.com y wotlk.ultimowow.com.Sesión
uw_cookie_consentUltimoWoWAlmacena tus preferencias de consentimiento de cookies. Se comparte entre ultimowow.com y wotlk.ultimowow.com.1 año
cf_clearanceCloudflareIdentifica tráfico legítimo y protege contra bots.1 año
__cf_bmCloudflareBot management y protección contra ataques DDoS.30 minutos
_cfuvidCloudflareIdentificador de sesión para gestión de tráfico.Sesión
CF_VERIFIED_DEVICE_*CloudflareVerificación de dispositivo para seguridad.30 días
_cf_logged_inCloudflareIndica estado de autenticación en servicios Cloudflare.Sesión
cf_chl_*Cloudflare TurnstileCookies del sistema de verificación captcha Turnstile.Variable
cf.turnstile.uCloudflare TurnstileDistingue entre humanos y bots en el sistema de verificación.Persistente
zaraz-consentCloudflare ZarazGestión de consentimiento del sistema Zaraz.1 año
cfz_*Cloudflare ZarazCookies técnicas del sistema de gestión de tags Zaraz.Variable
PHPSESSIDUltimoWoW{t('cookies.nPurpose1')}{t('cookies.durSession')}
uw_cookie_consentUltimoWoW{t('cookies.nPurpose2')}{t('cookies.dur1Year')}
cf_clearanceCloudflare{t('cookies.nPurpose3')}{t('cookies.dur1Year')}
__cf_bmCloudflare{t('cookies.nPurpose4')}{t('cookies.dur30Min')}
_cfuvidCloudflare{t('cookies.nPurpose5')}{t('cookies.durSession')}
CF_VERIFIED_DEVICE_*Cloudflare{t('cookies.nPurpose6')}{t('cookies.dur30Days')}
_cf_logged_inCloudflare{t('cookies.nPurpose7')}{t('cookies.durSession')}
cf_chl_*Cloudflare Turnstile{t('cookies.nPurpose8')}{t('cookies.durVariable')}
cf.turnstile.uCloudflare Turnstile{t('cookies.nPurpose9')}{t('cookies.durPersistent')}
zaraz-consentCloudflare Zaraz{t('cookies.nPurpose10')}{t('cookies.dur1Year')}
cfz_*Cloudflare Zaraz{t('cookies.nPurpose11')}{t('cookies.durVariable')}
-

Nota sobre Cloudflare: Utilizamos Cloudflare como proveedor de seguridad y rendimiento. Cloudflare puede establecer cookies adicionales de forma dinámica para proteger el sitio contra amenazas, gestionar el tráfico y optimizar el rendimiento. Estas cookies son estrictamente necesarias para el funcionamiento seguro del sitio. Para más información, consulta la Política de Cookies de Cloudflare.

+

{t.rich('cookies.cfNote', { link: (c) => {c} })}


- Cookies de Preferencias -

Las cookies de preferencias permiten a la página web recordar información que cambia la forma en que la página se comporta o el aspecto que tiene, como su idioma preferido o la región en la que usted se encuentra.

+ {t('cookies.prefTitle')} +

{t('cookies.prefDesc')}

- - - - + + + + - - - + + +
CookieProveedorPropósitoDuración{t('cookies.thCookie')}{t('cookies.thProvider')}{t('cookies.thPurpose')}{t('cookies.thDuration')}
comments_sortwotlk.ultimowow.comGuarda tu preferencia de ordenación de comentarios.1 año
wwcomments_sortwotlk.ultimowow.comGuarda tu preferencia de ordenación de comentarios.1 año
temp_default_3dmodelwotlk.ultimowow.comGuarda la configuración del visor 3D de modelos.1 año
comments_sortwotlk.ultimowow.com{t('cookies.prefPurpose1')}{t('cookies.dur1Year')}
wwcomments_sortwotlk.ultimowow.com{t('cookies.prefPurpose2')}{t('cookies.dur1Year')}
temp_default_3dmodelwotlk.ultimowow.com{t('cookies.prefPurpose3')}{t('cookies.dur1Year')}
- Cookies Analíticas -

Las cookies analíticas nos permiten contar las visitas y fuentes de tráfico para poder medir y mejorar el rendimiento de nuestro sitio. Nos ayudan a saber qué páginas son las más y menos populares, y a ver cómo se mueven los visitantes por el sitio. Toda la información que recogen estas cookies es agregada y, por lo tanto, anónima.

+ {t('cookies.analyticsTitle')} +

{t('cookies.analyticsDesc')}

- - - - + + + + - - - - - + + + + +
CookieProveedorPropósitoDuración{t('cookies.thCookie')}{t('cookies.thProvider')}{t('cookies.thPurpose')}{t('cookies.thDuration')}
_gaGoogle AnalyticsDistingue usuarios únicos asignando un número aleatorio.2 años
_ga_*Google AnalyticsMantiene el estado de la sesión.2 años
_gidGoogle AnalyticsDistingue usuarios para análisis estadístico.24 horas
_gatGoogle AnalyticsLimita la velocidad de solicitudes.1 minuto
sparrow_idCloudflareIdentificador para análisis de rendimiento web.1 año
_gaGoogle Analytics{t('cookies.aPurpose1')}{t('cookies.dur2Years')}
_ga_*Google Analytics{t('cookies.aPurpose2')}{t('cookies.dur2Years')}
_gidGoogle Analytics{t('cookies.aPurpose3')}{t('cookies.dur24Hours')}
_gatGoogle Analytics{t('cookies.aPurpose4')}{t('cookies.dur1Minute')}
sparrow_idCloudflare{t('cookies.aPurpose5')}{t('cookies.dur1Year')}
- Cookies de Marketing -

Las cookies de marketing se utilizan para rastrear a los visitantes en las páginas web. La intención es mostrar anuncios relevantes y atractivos para el usuario individual, y por lo tanto, más valiosos para los editores y terceros anunciantes.

+ {t('cookies.marketingTitle')} +

{t('cookies.marketingDesc')}

- - - - + + + + - - - - - - - + + + + + + +
CookieProveedorPropósitoDuración{t('cookies.thCookie')}{t('cookies.thProvider')}{t('cookies.thPurpose')}{t('cookies.thDuration')}
_gcl_*GoogleConversiones de Google Ads.90 días
IDEGoogle DoubleClickPublicidad personalizada.1 año
_fbpFacebook (Meta)Identifica navegadores para proporcionar servicios de publicidad y análisis.3 meses
_fbcFacebook (Meta)Almacena el último clic en anuncios de Facebook.3 meses
frFacebook (Meta)Habilita la entrega y medición de anuncios.3 meses
AMCV_*Adobe Experience CloudIdentificación de visitantes para servicios de Adobe.2 años
_q_state_*VariosGestión de estado para servicios de publicidad.Variable
_gcl_*Google{t('cookies.mPurpose1')}{t('cookies.dur90Days')}
IDEGoogle DoubleClick{t('cookies.mPurpose2')}{t('cookies.dur1Year')}
_fbpFacebook (Meta){t('cookies.mPurpose3')}{t('cookies.dur3Months')}
_fbcFacebook (Meta){t('cookies.mPurpose4')}{t('cookies.dur3Months')}
frFacebook (Meta){t('cookies.mPurpose5')}{t('cookies.dur3Months')}
AMCV_*Adobe Experience Cloud{t('cookies.mPurpose6')}{t('cookies.dur2Years')}
_q_state_*{t('cookies.providerVarious')}{t('cookies.mPurpose7')}{t('cookies.durVariable')}
-

Nota sobre servicios de terceros: Utilizamos Cloudflare Zaraz como sistema de gestión de tags. Los servicios de marketing (Google Ads, Facebook, Adobe, etc.) pueden establecer cookies adicionales cuando aceptas cookies de marketing. Para más información sobre cada servicio, consulta sus respectivas políticas de privacidad.

+

{t('cookies.thirdPartyNote')}


- Cookies de Contenido Embebido -

Algunas páginas de nuestro sitio incluyen contenido embebido de terceros (vídeos de YouTube, widgets de Discord, publicaciones de redes sociales, etc.). Estos servicios pueden establecer sus propias cookies cuando visualizas dicho contenido.

+ {t('cookies.embeddedTitle')} +

{t('cookies.embeddedDesc')}

- - - + + + - - - - + + + +
ProveedorTipo de contenidoMás información{t('cookies.thProvider')}{t('cookies.thContentType')}{t('cookies.thMoreInfo')}
YouTube (Google)Vídeos embebidosPolítica de Privacidad
DiscordWidgets de servidorPolítica de Privacidad
TwitchStreams embebidosPolítica de Privacidad
Facebook (Meta)Vídeos y publicacionesPolítica de Privacidad
YouTube (Google){t('cookies.embType1')}{t('cookies.privacyPolicyLink')}
Discord{t('cookies.embType2')}{t('cookies.privacyPolicyLink')}
Twitch{t('cookies.embType3')}{t('cookies.privacyPolicyLink')}
Facebook (Meta){t('cookies.embType4')}{t('cookies.privacyPolicyLink')}
-

Utilizamos youtube-nocookie.com cuando es posible para minimizar el seguimiento. Sin embargo, los servicios de terceros pueden establecer cookies como: YSC, VISITOR_INFO1_LIVE, yt-remote-*, __Secure-*, y otras relacionadas con la reproducción de contenido.

+

{t('cookies.embeddedNote')}




- Cómo eliminar cookies de tu navegador -

Además de utilizar nuestro panel de configuración, puedes eliminar las cookies directamente desde tu navegador:

+ {t('cookies.h2cat')} +

{t('cookies.deleteP')}

    -
  • Chrome: Configuración → Privacidad y seguridad → Cookies y otros datos de sitios
  • -
  • Firefox: Opciones → Privacidad & Seguridad → Cookies y datos del sitio
  • -
  • Safari: Preferencias → Privacidad → Gestionar datos de sitios web
  • -
  • Edge: Configuración → Cookies y permisos del sitio → Cookies
  • +
  • {t('cookies.deleteLi1')}
  • +
  • {t('cookies.deleteLi2')}
  • +
  • {t('cookies.deleteLi3')}
  • +
  • {t('cookies.deleteLi4')}



- Tu estado de consentimiento -

Puedes cambiar o retirar tu consentimiento en cualquier momento. Al contactarnos respecto a su consentimiento, por favor, indique la fecha de su consentimiento.

+ {t('cookies.h3cat')} +

{t('cookies.consentP')}




- Más información -

Si tienes alguna pregunta sobre nuestra política de cookies, puedes contactarnos a través de nuestra página de Contacto.

+ {t('cookies.h4cat')} +

{t.rich('cookies.moreInfoP', { link: (c) => {c} })}


-

Última actualización: Marzo 2026

+

{t('cookies.updated')}

diff --git a/web-next/app/[locale]/customize-character/page.tsx b/web-next/app/[locale]/customize-character/page.tsx index a8cada6..2a7edd3 100644 --- a/web-next/app/[locale]/customize-character/page.tsx +++ b/web-next/app/[locale]/customize-character/page.tsx @@ -1,5 +1,5 @@ import type { Metadata } from 'next' -import { setRequestLocale } from 'next-intl/server' +import { getTranslations, setRequestLocale } from 'next-intl/server' import { redirect } from '@/i18n/navigation' import { getSession } from '@/lib/session' import { getGameCharacters } from '@/lib/characters' @@ -22,53 +22,44 @@ export default async function CustomizeCharacterPage({ params }: { params: Promi const [chars, price] = await Promise.all([getGameCharacters(session.accountId!), getCustomizePrice()]) + const t = await getTranslations('CharServiceB.customize') + return (
-

- La herramienta Personalizar personaje te permite cambiar los siguientes aspectos un personaje: -

-

- Color de la piel

-

- Rostro

-

- Pelo

-

- Sexo

-

- Características correspondientes a cada raza como cuernos, pendientes, marcas, vello facial

-

Si también deseas cambiar el nombre del personaje, debes usar la herramienta Renombrar personaje.

+

{t.rich('intro', { s: (c) => {c} })}

+

{t('aspect1')}

+

{t('aspect2')}

+

{t('aspect3')}

+

{t('aspect4')}

+

{t('aspect5')}

+

{t('alsoRename')}


-

- Al usar el botón PERSONALIZAR del personaje que hayas escogido, se enviará una petición de personalización de - dicho personaje. -

-

Cuando ingreses a la lista de personajes de tu cuenta, verás un ícono a la izquierda de tu personaje escogido.

-

- Al darle click a dicho ícono ingresarás al menú de edición de personaje que te permitirá escoger diferentes - características. -

+

{t('instructions')}

+

{t('iconInfo')}

+

{t('iconClick')}


- NOTA + {t('noteLegend')}
-

- Por favor, asegúrate de haber escogido al personaje correcto ya que esta acción no es reversible una vez - realizada. -

+

{t('noteConfirm')}



-

Requiere {price} (SumUp)

+

{t.rich('requires', { price, s: (c) => {c}, y: (c) => {c} })}

({ name: c.name, classCss: c.classCss }))} checkoutEndpoint="/api/character/customize/checkout" - payLabel="PERSONALIZAR" + payLabel={t('payLabel')} buttonClass="customize-button" provider="sumup" - confirmText={`¿Estás seguro de personalizar al personaje seleccionado por ${price} € (SumUp)?`} + confirmText={t('confirm', { price })} />
diff --git a/web-next/app/[locale]/d-points-success/page.tsx b/web-next/app/[locale]/d-points-success/page.tsx index e27f3a2..82d2fc1 100644 --- a/web-next/app/[locale]/d-points-success/page.tsx +++ b/web-next/app/[locale]/d-points-success/page.tsx @@ -1,4 +1,4 @@ -import { setRequestLocale } from 'next-intl/server' +import { getTranslations, setRequestLocale } from 'next-intl/server' import { Link } from '@/i18n/navigation' import { fulfillCheckoutSession } from '@/lib/fulfill' import { isSessionPaid } from '@/lib/stripe' @@ -16,6 +16,7 @@ export default async function DPointsSuccessPage({ }) { const { locale } = await params setRequestLocale(locale) + const t = await getTranslations('Points') const { provider, session_id, ref } = await searchParams // Entrega compartida con el webhook/return (idempotente vía reclamo atómico). @@ -32,20 +33,20 @@ export default async function DPointsSuccessPage({ } return ( - +
{status === 'ok' ? ( - ¡Pago completado! Tus PD ya fueron acreditados a tu cuenta. + {t('dpointsSuccess.paidOk')} ) : status === 'already' ? ( - Este pago ya había sido procesado. Tus PD están acreditados. + {t('dpointsSuccess.alreadyPaid')} ) : ( - No pudimos confirmar tu pago. Si se realizó el cargo, contacta con soporte. + {t('dpointsSuccess.error')} )}

- ← Regresar a mi cuenta + {t('dpointsSuccess.backToAccount')}

diff --git a/web-next/app/[locale]/d-points/page.tsx b/web-next/app/[locale]/d-points/page.tsx index ebd6813..ea0fa8d 100644 --- a/web-next/app/[locale]/d-points/page.tsx +++ b/web-next/app/[locale]/d-points/page.tsx @@ -1,5 +1,5 @@ import type { Metadata } from 'next' -import { setRequestLocale } from 'next-intl/server' +import { getTranslations, setRequestLocale } from 'next-intl/server' import { redirect } from '@/i18n/navigation' import { getSession } from '@/lib/session' import { getRealmName } from '@/lib/realm' @@ -14,6 +14,7 @@ export const metadata: Metadata = { title: 'Adquirir PD' } export default async function DPointsPage({ params }: { params: Promise<{ locale: string }> }) { const { locale } = await params setRequestLocale(locale) + const t = await getTranslations('Points') const session = await getSession() if (!session.bnetId) redirect({ href: '/login', locale }) @@ -27,7 +28,7 @@ export default async function DPointsPage({ params }: { params: Promise<{ locale const currency = (process.env.DP_CURRENCY || 'eur').toLowerCase() return ( - + ) diff --git a/web-next/app/[locale]/download-addons/page.tsx b/web-next/app/[locale]/download-addons/page.tsx index 0a847ff..d6cba63 100644 --- a/web-next/app/[locale]/download-addons/page.tsx +++ b/web-next/app/[locale]/download-addons/page.tsx @@ -1,40 +1,42 @@ import type { Metadata } from 'next' +import { getTranslations } from 'next-intl/server' export const metadata: Metadata = { title: 'Descarga de addons' } -// Lista de addons (edítala con los tuyos). name/desc/url. -const ADDONS: { name: string; desc: string; url: string }[] = [ - { name: 'Deadly Boss Mods (DBM)', desc: 'Avisos y temporizadores de habilidades de jefes en mazmorras y bandas.', url: 'https://www.curseforge.com/wow/addons/deadly-boss-mods' }, - { name: 'Details! Damage Meter', desc: 'Medidor de daño, curación y amenaza con gráficas detalladas.', url: 'https://www.curseforge.com/wow/addons/details' }, - { name: 'AtlasLoot', desc: 'Consulta el botín de jefes de mazmorras y bandas dentro del juego.', url: 'https://www.curseforge.com/wow/addons/atlasloot-enhanced' }, - { name: 'Questie', desc: 'Muestra objetivos y ubicaciones de misiones en el mapa y el minimapa.', url: 'https://www.curseforge.com/wow/addons/questie' }, - { name: 'Bagnon', desc: 'Unifica todas tus bolsas y el banco en una sola ventana con búsqueda.', url: 'https://www.curseforge.com/wow/addons/bagnon' }, - { name: 'Bartender4', desc: 'Personaliza por completo tus barras de acción.', url: 'https://www.curseforge.com/wow/addons/bartender4' }, - { name: 'Auctioneer', desc: 'Herramientas avanzadas para la casa de subastas.', url: 'https://www.curseforge.com/wow/addons/auctioneer' }, - { name: 'Pawn', desc: 'Compara equipo y te indica qué objeto es una mejora para tu personaje.', url: 'https://www.curseforge.com/wow/addons/pawn' }, +// Lista de addons (edítala con los tuyos). name/descKey/url. +const ADDONS: { name: string; descKey: string; url: string }[] = [ + { name: 'Deadly Boss Mods (DBM)', descKey: 'descDbm', url: 'https://www.curseforge.com/wow/addons/deadly-boss-mods' }, + { name: 'Details! Damage Meter', descKey: 'descDetails', url: 'https://www.curseforge.com/wow/addons/details' }, + { name: 'AtlasLoot', descKey: 'descAtlasLoot', url: 'https://www.curseforge.com/wow/addons/atlasloot-enhanced' }, + { name: 'Questie', descKey: 'descQuestie', url: 'https://www.curseforge.com/wow/addons/questie' }, + { name: 'Bagnon', descKey: 'descBagnon', url: 'https://www.curseforge.com/wow/addons/bagnon' }, + { name: 'Bartender4', descKey: 'descBartender4', url: 'https://www.curseforge.com/wow/addons/bartender4' }, + { name: 'Auctioneer', descKey: 'descAuctioneer', url: 'https://www.curseforge.com/wow/addons/auctioneer' }, + { name: 'Pawn', descKey: 'descPawn', url: 'https://www.curseforge.com/wow/addons/pawn' }, ] -export default function DownloadAddonsPage() { +export default async function DownloadAddonsPage() { + const t = await getTranslations('Misc') return (
-

Descarga de addons

+

{t('downloadAddons.title')}

-

Addons recomendados

+

{t('downloadAddons.recommended')}

-

Los addons son complementos opcionales que mejoran y personalizan tu experiencia de juego.

-

Descarga los que quieras desde su página oficial (elige la versión compatible con WotLK 3.4.3).

+

{t('downloadAddons.intro1')}

+

{t('downloadAddons.intro2')}


-

Cómo instalarlos

-

1) Descarga el addon y descomprime el archivo .zip.

-

2) Copia la carpeta resultante dentro de Interface/AddOns (en la carpeta de tu cliente).

-

3) Inicia el juego y, en la pantalla de selección de personaje, pulsa Complementos para activarlos.

+

{t('downloadAddons.howToInstall')}

+

{t('downloadAddons.step1')}

+

{t.rich('downloadAddons.step2', { s: (c) => {c} })}

+

{t.rich('downloadAddons.step3', { s: (c) => {c} })}




@@ -44,11 +46,11 @@ export default function DownloadAddonsPage() {
{a.name} -

{a.desc}

+

{t(`downloadAddons.${a.descKey}`)}

- Descargar + {t('downloadAddons.download')}
{options.map((o) => ( diff --git a/web-next/app/[locale]/help/page.tsx b/web-next/app/[locale]/help/page.tsx index de7e567..36957d9 100644 --- a/web-next/app/[locale]/help/page.tsx +++ b/web-next/app/[locale]/help/page.tsx @@ -1,5 +1,5 @@ import type { Metadata } from 'next' -import { setRequestLocale } from 'next-intl/server' +import { getTranslations, setRequestLocale } from 'next-intl/server' import { getRealmName } from '@/lib/realm' export const metadata: Metadata = { title: 'Ayuda' } @@ -9,6 +9,7 @@ export const dynamic = 'force-dynamic' export default async function HelpPage({ params }: { params: Promise<{ locale: string }> }) { const { locale } = await params setRequestLocale(locale) + const t = await getTranslations('Misc') const realm = await getRealmName() return ( @@ -16,80 +17,78 @@ export default async function HelpPage({ params }: { params: Promise<{ locale: s
-

Ayuda

+

{t('help.title')}

-

Guía de asistencia

+

{t('help.subtitle')}

-

En esta guía podrás saber qué pasos seguir para obtener asistencia adecuada dependiendo del tipo de problema que hayas encontrado en nuestro servidor.

-

Ofrecemos un conjunto de problemas comunes, qué medios utilizar para cada caso y una explicación de cada medio de contacto.

-

Los diferentes medios para cada problema se listan desde el más ideal hasta la última opción.

+

{t('help.intro1')}

+

{t('help.intro2')}

+

{t('help.intro3')}


- Con el cliente -

Problemas que impiden arrancar el cliente, conectar al servidor o errores que provocan el cierre abrupto del cliente.

-

Los medios son:

-

- Foros

-

- Discord

+ {t('help.clientTitle')} +

{t('help.clientText')}

+

{t('help.mediaAre')}

+

{t('help.mediaForos')}

+

{t('help.mediaDiscord')}


- Con errores del servidor -

Problemas relacionados a errores que deben ser reparados por nuestro equipo de reparación para mejorar el servidor.

-

Los medios son:

-

- Foros

+ {t('help.serverErrorsTitle')} +

{t('help.serverErrorsText')}

+

{t('help.mediaAre')}

+

{t('help.mediaForos')}


- Con el personaje -

Problemas relacionados a errores que puedan afectar al personaje, habilidades, hechizos, misiones, etc.

-

Los medios son:

-

- Ticket

-

- Discord

+ {t('help.characterTitle')} +

{t('help.characterText')}

+

{t('help.mediaAre')}

+

{t('help.mediaTicket')}

+

{t('help.mediaDiscord')}


- Con otro jugador -

Problemas relacionados a otros usuarios cometiendo faltas a las normas del servidor.

-

Este tipo de problemas requieren de una denuncia con las pruebas correspondientes de lo que haya sucedido.

-

Los medios son:

-

- Foros

+ {t('help.otherPlayerTitle')} +

{t('help.otherPlayerText1')}

+

{t('help.otherPlayerText2')}

+

{t('help.mediaAre')}

+

{t('help.mediaForos')}


- Con bloqueos de cuenta -

Problemas relacionados a bloqueos de cuenta realizados por el equipo de {realm}.

-

Los medios son:

-

- Foros

+ {t('help.accountBlocksTitle')} +

{t('help.accountBlocksText', { realm })}

+

{t('help.mediaAre')}

+

{t('help.mediaForos')}


- Con la página web -

Problemas relacionados a errores, fallas o sugerencias respecto de este sitio web.

-

Los medios son:

-

- Correo a ryuzaki@ultimowow.com

+ {t('help.websiteTitle')} +

{t('help.websiteText')}

+

{t('help.mailTo')} ryuzaki@ultimowow.com


- Con PD -

Problemas relacionados a PD o PV.

-

Los medios son:

-

- Correo a contacto@ultimowow.com

+ {t('help.pdTitle')} +

{t('help.pdText')}

+

{t('help.mailTo')} contacto@ultimowow.com


- Medios de contacto + {t('help.contactMeans')}
- Ticket -

Para colocar un ticket, debes hacer click al signo de interrogación rojo en la parte inferior derecha de la interfaz del cliente (a la izquierda del llavero del personaje).

-

Al hacerle click, aparecerá una ventana en el medio de la pantalla.

-

En dicha ventana, hacer click al primer botón en la esquina inferior izquierda llamado 'Hablar con un MJ'

-

Aparecerá una ventana con un texto informativo y debajo en medio, un botón llamado 'Abrir una consulta'.

-

Al darle click al botón, aparecerá un campo de texto en el que puedes describir tu problema

-

Cuando hayas finalizado haz click en el botón en el primer botón en la esquina inferior derecha llamado 'Enviar'.

-

El ticket ya ha sido creado y está pendiente de respuesta de un miembro del equipo.

+ {t('help.ticketTitle')} +

{t('help.ticket1')}

+

{t('help.ticket2')}

+

{t('help.ticket3')}

+

{t('help.ticket4')}

+

{t('help.ticket5')}

+

{t('help.ticket6')}

+

{t('help.ticket7')}


- Discord -

Discord es una plataforma de chat y comunicación por voz que puede descargarse aquí.

-

Para entrar en el servidor de Discord de nuestro servidor, haz click aquí.

-

Una vez que seas miembro de nuestro Discord podrás pedir ayuda en el canal 'Asistencia' o enviar un mensaje directo a cualquier miembro del equipo solicitando ayuda.

+ {t('help.discordTitle')} +

{t.rich('help.discord1', { link: (c) => {c} })}

+

{t.rich('help.discord2', { link: (c) => {c} })}

+

{t('help.discord3')}


- Foros -

Los foros son una gran herramienta en donde no sólo puede ayudarte el equipo de {realm} sino que además otros jugadores pueden asistirte si conocen cómo resolver el problema que tengas.

-

Para solicitar ayuda por este medio, debes tener un usuario con el cual poder conectar y abrir un nuevo tema en el foro adecuado.

-

Puedes visitar nuestros foros aquí.

+ {t('help.forosTitle')} +

{t('help.foros1', { realm })}

+

{t('help.foros2')}

+

{t.rich('help.foros3', { link: (c) => {c} })}


- Correo electrónico -

El servidor tiene diferentes direcciones de correo dedicados a diferentes temas del servidor.

-

Depende cual sea tu problema, usa el adecuado para enviarnos un mensaje de correo.

+ {t('help.emailTitle')} +

{t('help.email1')}

+

{t('help.email2')}

diff --git a/web-next/app/[locale]/legal-notice/page.tsx b/web-next/app/[locale]/legal-notice/page.tsx index a898383..18953f9 100644 --- a/web-next/app/[locale]/legal-notice/page.tsx +++ b/web-next/app/[locale]/legal-notice/page.tsx @@ -1,30 +1,32 @@ import type { Metadata } from 'next' +import { getTranslations } from 'next-intl/server' export const metadata: Metadata = { title: 'Aviso legal', } -export default function LegalNoticePage() { +export default async function LegalNoticePage() { + const t = await getTranslations('Legal') return (
-

Aviso legal

+

{t('legalNotice.title')}

-

El sitio web "UltimoWoW.com" y sus subdominios (en adelante, "el sitio web") se ofrecen únicamente con fines informativos y de entretenimiento. UltimoWoW no se hace responsable del uso que los usuarios hagan del sitio web. Aunque se procura que se dé un uso correcto, UltimoWoW no asume responsabilidad por las acciones, decisiones o consecuencias derivadas del uso del sitio web. Los usuarios son responsables de verificar la precisión, integridad y utilidad de la información proporcionada, así como de cumplir con las leyes y regulaciones aplicables al utilizar el contenido del sitio web.

+

{t('legalNotice.p1')}


-

Enlaces a terceros: El sitio web puede contener enlaces a sitios web de terceros. Estos enlaces se proporcionan únicamente para tu conveniencia y no implican el respaldo o afiliación de UltimoWoW con dichos sitios web. UltimoWoW no se hace responsable del contenido o las prácticas de privacidad de estos sitios web de terceros.

+

{t('legalNotice.p2')}


-

Privacidad y Cookies: La recopilación y uso de tus datos personales se rigen por nuestra Política de Privacidad y el uso de cookies se rige por nuestra Declaración de Cookies. Al utilizar el sitio web, aceptas nuestras prácticas descritas en dichas políticas.

+

{t('legalNotice.p3')}


-

Derechos de autor: Los usuarios del sitio web deben respetar los derechos de autor y no publicar contenido que infrinja los derechos de propiedad intelectual de terceros. UltimoWoW se compromete a proteger los derechos de autor y cumplir con las leyes aplicables. Si encuentras contenido infractor, contáctanos utilizando el mecanismo de reclamación de infracción descrito a continuación.

+

{t('legalNotice.p4')}


-

Mecanismo de reclamación de infracción: Si crees que tu trabajo ha sido utilizado de manera no autorizada en el sitio web, puedes presentar una reclamación por infracción de derechos de autor proporcionando la información requerida. Contáctanos utilizando los datos de contacto a continuación.

+

{t('legalNotice.p5')}


-

Contacto

+

{t('legalNotice.contactTitle')}

ultimowow.com

info@ultimowow.com

diff --git a/web-next/app/[locale]/level-up-character/page.tsx b/web-next/app/[locale]/level-up-character/page.tsx index 04f1156..aaf814f 100644 --- a/web-next/app/[locale]/level-up-character/page.tsx +++ b/web-next/app/[locale]/level-up-character/page.tsx @@ -1,5 +1,5 @@ import type { Metadata } from 'next' -import { setRequestLocale } from 'next-intl/server' +import { getTranslations, setRequestLocale } from 'next-intl/server' import { redirect } from '@/i18n/navigation' import { getSession } from '@/lib/session' import { getGameCharacters } from '@/lib/characters' @@ -22,44 +22,39 @@ export default async function LevelUpCharacterPage({ params }: { params: Promise const [chars, price] = await Promise.all([getGameCharacters(session.accountId!), getLevelUpPrice()]) + const t = await getTranslations('CharServiceB.levelUp') + return (
-

- La herramienta Subir a nivel 80 te permite subir cualquier personaje al nivel 80. -

-

Sólo subirá de nivel al personaje. Esta opción no incluye ítems/oro/etc.

+

{t.rich('intro', { s: (c) => {c} })}

+

{t('onlyLevel')}


-

- Al usar el botón SUBIR A NIVEL 80 del personaje que hayas escogido, se enviará el nivel 80 al personaje. -

-

Cuando ingreses a la lista de personajes de tu cuenta, verás que tu personaje escogido ya es nivel 80.

+

{t('instructions')}

+

{t('levelInfo')}


- NOTA + {t('noteLegend')}
-

Se requiere que el personaje esté desconectado.

-

- Por favor, asegúrate de haber escogido al personaje correcto ya que esta acción no es reversible una vez - realizada. -

+

{t('noteOffline')}

+

{t('noteConfirm')}



-

Requiere {price} (SumUp)

+

{t.rich('requires', { price, s: (c) => {c}, y: (c) => {c} })}

({ name: c.name, classCss: c.classCss }))} checkoutEndpoint="/api/character/level-up/checkout" - payLabel="SUBIR A NIVEL 80" + payLabel={t('payLabel')} buttonClass="level-up-button" provider="sumup" - confirmText={`¿Estás seguro de subir a nivel 80 al personaje seleccionado por ${price} € (SumUp)?`} + confirmText={t('confirm', { price })} />
diff --git a/web-next/app/[locale]/page.tsx b/web-next/app/[locale]/page.tsx index 2d87945..fbada07 100644 --- a/web-next/app/[locale]/page.tsx +++ b/web-next/app/[locale]/page.tsx @@ -1,4 +1,4 @@ -import { setRequestLocale } from 'next-intl/server' +import { getTranslations, setRequestLocale } from 'next-intl/server' import { Link } from '@/i18n/navigation' import { ServerClock } from '@/components/ServerClock' import { getNoticias, getServerStatus, type Noticia, type ServerStatus } from '@/lib/home' @@ -38,6 +38,7 @@ function formatFecha(iso: string | Date | null): string { export default async function HomePage({ params }: { params: Promise<{ locale: string }> }) { const { locale } = await params setRequestLocale(locale) + const t = await getTranslations('Misc') const { noticias, status } = await getData() const realmName = await getRealmName() @@ -72,7 +73,7 @@ export default async function HomePage({ params }: { params: Promise<{ locale: s
- + @@ -93,42 +94,32 @@ export default async function HomePage({ params }: { params: Promise<{ locale: s
{loginStatus}
Hora{t('home.labelTime')}
- ¡RECLUTA A UN AMIGO! + {t('home.recruitFriend')}
- ¡RECLUTA A UN AMIGO! + {t('home.recruitFriend')}
-

- {realmName} es una comunidad enfocada en usuarios de habla hispana, - especialmente dirigida al público español y latino. -

-

- Atraemos a usuarios apasionados tanto por el PvE como por el PvP, y ofrecemos una - amplia variedad de contenido. -

+

{t('home.introP1', { realm: realmName })}

+

{t('home.introP2')}


-

- Nuestro objetivo principal es mantener una comunidad de alto nivel, brindando un - ambiente agradable para que todos los miembros, nuevos y veteranos, encuentren aquí - un lugar donde puedan vivir momentos inigualables. -

-

¡Únete y disfruta de una experiencia única con miles de usuarios!

+

{t('home.introP3')}

+

{t('home.introP4')}


-

NOTICIAS

+

{t('home.newsHeading')}

{noticias.length === 0 ? ( -

No hay noticias disponibles en este momento.

+

{t('home.noNews')}

) : ( <> {noticias.map((n) => ( @@ -141,9 +132,9 @@ export default async function HomePage({ params }: { params: Promise<{ locale: s /> {n.enlace && (

- Enlace:{' '} + {t('home.newsLinkLabel')}{' '} - aquí + {t('home.here')}

)} @@ -153,7 +144,7 @@ export default async function HomePage({ params }: { params: Promise<{ locale: s
))}

- * Mostrando las últimas 50 noticias + {t('home.showingLatest')}


diff --git a/web-next/app/[locale]/points-history/page.tsx b/web-next/app/[locale]/points-history/page.tsx index 8739918..fb94dd9 100644 --- a/web-next/app/[locale]/points-history/page.tsx +++ b/web-next/app/[locale]/points-history/page.tsx @@ -1,5 +1,5 @@ import type { Metadata } from 'next' -import { setRequestLocale } from 'next-intl/server' +import { setRequestLocale, getTranslations } from 'next-intl/server' import { redirect } from '@/i18n/navigation' import { getSession } from '@/lib/session' import { getPointsHistory, getPointsBalances, type PointsMovement } from '@/lib/points-history' @@ -25,6 +25,7 @@ function methodClass(method: PointsMovement['method']): string { export default async function PointsHistoryPage({ params }: { params: Promise<{ locale: string }> }) { const { locale } = await params setRequestLocale(locale) + const t = await getTranslations('History') const session = await getSession() if (!session.bnetId) redirect({ href: '/login', locale }) @@ -36,25 +37,24 @@ export default async function PointsHistoryPage({ params }: { params: Promise<{ ]) return ( - +
-

Aquí verás los consumos de PD y PV más recientes que ha tenido la cuenta.

+

{t('points.intro1')}

- Con esta información podrás tener control de todo lo que has adquirido así como también chequear que toda la - actividad sea normal. + {t('points.intro2')}

-

Si observas algún movimiento sospechoso, puedes contactar con el equipo de Nova WoW.

+

{t('points.intro3')}


-

Historial de PD y PV

+

{t('points.boxTitle')}

- Saldo actual: {balances.dp} PD ·{' '} + {t('points.currentBalance')} {balances.dp} PD ·{' '} {balances.pv} PV


@@ -63,7 +63,7 @@ export default async function PointsHistoryPage({ params }: { params: Promise<{ - No hay movimientos + {t('points.noMovements')} @@ -72,13 +72,13 @@ export default async function PointsHistoryPage({ params }: { params: Promise<{ - - - + + + - - + + diff --git a/web-next/app/[locale]/privacy-policy/page.tsx b/web-next/app/[locale]/privacy-policy/page.tsx index 50f0a45..2ea6b3b 100644 --- a/web-next/app/[locale]/privacy-policy/page.tsx +++ b/web-next/app/[locale]/privacy-policy/page.tsx @@ -1,76 +1,78 @@ import type { Metadata } from 'next' +import { getTranslations } from 'next-intl/server' export const metadata: Metadata = { title: 'Política de privacidad', } -export default function PrivacyPolicyPage() { +export default async function PrivacyPolicyPage() { + const t = await getTranslations('Legal') return (
-

Política de privacidad

+

{t('privacy.title')}

-

Esta Política de Privacidad describe cómo recopilamos, utilizamos, almacenamos y protegemos la información personal de los usuarios ("usted" o "usuario") de nuestro sitio web. Al utilizar nuestro sitio web, usted acepta las prácticas descritas en esta política.

+

{t('privacy.p1')}




-

Recopilación de Información Personal

-

Recopilamos la siguiente información personal cuando usted utiliza nuestro sitio web:

-

1. Cookies: Utilizamos cookies para recopilar información sobre su actividad en nuestro sitio web. Las cookies son pequeños archivos de texto que se almacenan en su dispositivo y nos permiten reconocer su navegador o dispositivo y recordar cierta información. Estas cookies pueden ser cookies de sesión o cookies persistentes. Puede ajustar la configuración de su navegador para rechazar todas las cookies o para indicar cuándo se envía una cookie. Sin embargo, si desactiva las cookies, es posible que algunas funciones de nuestro sitio web no funcionen correctamente.

-

2. Direcciones IP: Recopilamos direcciones IP de los usuarios que visitan nuestro sitio web. Las direcciones IP se utilizan para analizar tendencias, administrar el sitio web, rastrear el movimiento del usuario y recopilar información demográfica. No vinculamos las direcciones IP con ninguna información de identificación personal.

-

3. Direcciones de correo electrónico: Recopilamos las direcciones de correo electrónico que usted proporciona al registrarse en nuestro sitio web o al actualizar su información de registro. Utilizamos estas direcciones de correo electrónico para enviarle información relacionada con su cuenta, como confirmaciones de registro, notificaciones de cambios en los términos o políticas, y actualizaciones de seguridad.

-

4. Nombres de usuario y contraseñas: Recopilamos los nombres de usuario y las contraseñas que usted elige al registrar una cuenta en nuestro sitio web. Estas credenciales se utilizan para autenticar su acceso a su cuenta y para proteger su información personal.

+

{t('privacy.h1')}

+

{t('privacy.p2')}

+

{t('privacy.p3')}

+

{t('privacy.p4')}

+

{t('privacy.p5')}

+

{t('privacy.p6')}




-

Uso de la Información Personal

-

Utilizamos la información personal que recopilamos para los siguientes fines:

-

1. Brindar y mejorar nuestros servicios: Utilizamos su información personal para brindarle los servicios solicitados y mejorar su experiencia en nuestro sitio web. Esto incluye personalizar el contenido y las recomendaciones, proporcionar soporte técnico, y analizar el rendimiento y la eficacia de nuestro sitio web.

-

2. Comunicaciones: Podemos utilizar su dirección de correo electrónico para enviarle comunicaciones relacionadas con su cuenta, como confirmaciones de registro, notificaciones de cambios en los términos o políticas, actualizaciones de seguridad y otras actualizaciones importantes.

+

{t('privacy.h2')}

+

{t('privacy.p7')}

+

{t('privacy.p8')}

+

{t('privacy.p9')}




-

Protección de la Información Personal

-

Tomamos medidas razonables para proteger la información personal que recopilamos y almacenamos. Utilizamos medidas de seguridad técnicas, administrativas y físicas para proteger su información contra el acceso no autorizado, la divulgación, la alteración o la destrucción.

+

{t('privacy.h3')}

+

{t('privacy.p10')}




-

Divulgación de la Información Personal a Terceros

-

No vendemos, intercambiamos ni transferimos su información personal a terceros sin su consentimiento, excepto en los siguientes casos:

-

- Proveedores de servicios: Podemos compartir su información personal con proveedores de servicios que realizan funciones en nuestro nombre, como el alojamiento del sitio web, el procesamiento de pagos y el análisis de datos. Estos proveedores de servicios tienen acceso a su información personal solo en la medida necesaria para realizar sus funciones y están obligados a no divulgar ni utilizar la información con ningún otro fin.

-

- Cumplimiento legal: Podemos divulgar su información personal si creemos de buena fe que dicha divulgación es necesaria para cumplir con una obligación legal, proteger sus derechos o seguridad, investigar fraudes o responder a una solicitud legal.

+

{t('privacy.h4')}

+

{t('privacy.p11')}

+

{t('privacy.p12')}

+

{t('privacy.p13')}




-

Sus Derechos y Opciones

-

Usted tiene ciertos derechos y opciones con respecto a su información personal:

-

- Acceso y actualización: Usted puede acceder y actualizar cierta información personal proporcionada a través de su cuenta en nuestro sitio web.

-

- Eliminación de datos: Usted puede solicitar la eliminación de su información personal de nuestros registros, sujeto a cualquier requisito legal o contractual que podamos tener.

-

- Cookies: Puede ajustar la configuración de su navegador para rechazar cookies o para indicar cuándo se envía una cookie. Sin embargo, tenga en cuenta que deshabilitar las cookies puede afectar el funcionamiento de nuestro sitio web.

+

{t('privacy.h5')}

+

{t('privacy.p14')}

+

{t('privacy.p15')}

+

{t('privacy.p16')}

+

{t('privacy.p17')}




-

Uso incorrecto de plataformas de terceros con el fin de violar nuestra política de devolución

-

Este tipo de acciones conllevará a la expulsión del usuario de nuestro sitio sin ningún tipo de devolución.

+

{t('privacy.h6')}

+

{t('privacy.p18')}




-

Cambios a esta Política de Privacidad

-

Nos reservamos el derecho de actualizar esta Política de Privacidad en cualquier momento. Le recomendamos que revise periódicamente esta página para conocer los cambios. La fecha de entrada en vigencia de la política se indicará en la parte superior de la página.

+

{t('privacy.h7')}

+

{t('privacy.p19')}




-

Contáctanos

-

Si tiene alguna pregunta o inquietud sobre esta Política de Privacidad, puede contactarnos a través de la siguiente información de contacto:

+

{t('privacy.h8')}

+

{t('privacy.p20')}

Error 404

ultimowow.com

info@ultimowow.com


-

Fecha de actualización: 23-05-2023

+

{t('privacy.updated')}

diff --git a/web-next/app/[locale]/promo-code/page.tsx b/web-next/app/[locale]/promo-code/page.tsx index 915c6e0..e4ec037 100644 --- a/web-next/app/[locale]/promo-code/page.tsx +++ b/web-next/app/[locale]/promo-code/page.tsx @@ -1,5 +1,5 @@ import type { Metadata } from 'next' -import { setRequestLocale } from 'next-intl/server' +import { getTranslations, setRequestLocale } from 'next-intl/server' import { redirect } from '@/i18n/navigation' import { getSession } from '@/lib/session' import { getRealmName } from '@/lib/realm' @@ -14,6 +14,7 @@ export const metadata: Metadata = { title: 'Código de promoción' } export default async function PromoCodePage({ params }: { params: Promise<{ locale: string }> }) { const { locale } = await params setRequestLocale(locale) + const t = await getTranslations('Points') const session = await getSession() if (!session.bnetId) redirect({ href: '/login', locale }) @@ -22,25 +23,22 @@ export default async function PromoCodePage({ params }: { params: Promise<{ loca const realm = await getRealmName() return ( - +

- Los Códigos de promoción son palabras con letras y números que se canjean en el formulario de - abajo por PD o PV y tienen usos limitados. Cada uno puede dar diferente cantidad de PD/PV. + {t.rich('promo.intro1', { s: (c) => {c} })}

- Estos códigos son generados por el Equipo de {realm} y pueden aparecer en la página web, Discord, las redes - sociales o el servidor. + {t('promo.intro2', { realm })}

-

Aconsejamos poner atención a las redes sociales y los anuncios del servidor para saber cuándo hay un código disponible.

+

{t('promo.intro3')}


- NOTA + {t('promo.note')}

- Los códigos son sensibles a mayúsculas y minúsculas por lo que siempre debes escribirlos igual a como - aparecen publicados. + {t('promo.noteText')}

diff --git a/web-next/app/[locale]/quest-character/page.tsx b/web-next/app/[locale]/quest-character/page.tsx index 6094579..d60edb5 100644 --- a/web-next/app/[locale]/quest-character/page.tsx +++ b/web-next/app/[locale]/quest-character/page.tsx @@ -1,5 +1,6 @@ import type { Metadata } from 'next' -import { setRequestLocale } from 'next-intl/server' +import { NoteLegend } from '@/components/NoteLegend' +import { getTranslations, setRequestLocale } from 'next-intl/server' import { redirect } from '@/i18n/navigation' import { getSession } from '@/lib/session' import { getGameCharacters } from '@/lib/characters' @@ -25,6 +26,7 @@ const CLASS_GROUPS: { css: string; name: string }[] = [ export default async function QuestCharacterPage({ params }: { params: Promise<{ locale: string }> }) { const { locale } = await params setRequestLocale(locale) + const t = await getTranslations('CharService') const session = await getSession() if (!session.bnetId) redirect({ href: '/login', locale }) @@ -40,21 +42,20 @@ export default async function QuestCharacterPage({ params }: { params: Promise<{ })) return ( - +

- La herramienta Rastreador de misiones te permite ver el estado de misiones o cadenas de misiones - importantes en tus personajes. + {t.rich('quest.intro', { s: (c) => {c} })}


-

Opciones disponibles:

+

{t('quest.optionsAvailable')}

{CLASS_GROUPS.map((g) => { const opts = QUEST_OPTIONS.filter((o) => o.classCss === g.css) if (opts.length === 0) return null return (
-

{g.name}

+

{t(`quest.className.${g.css}`)}

    {opts.map((o) => (
  • @@ -78,7 +79,7 @@ export default async function QuestCharacterPage({ params }: { params: Promise<{ ) : ( o.label )}{' '} - a partir del nivel {o.minLevel} + {t('quest.fromLevel', { level: o.minLevel })}
  • ))}
@@ -86,35 +87,36 @@ export default async function QuestCharacterPage({ params }: { params: Promise<{
) })} -

Por reputación

+

{t('quest.byReputation')}

  • - Los Hijos de Hodir: Cadena - de misiones principal hasta interactuar con el intendente{' '} - Lillehoff + {t.rich('quest.hodir', { + hodir: (c) => {c}, + lille: (c) => {c}, + })}

-

Por misión específica

+

{t('quest.bySpecific')}

    -
  • A partir del nivel 10
  • +
  • {t('quest.fromLevel10')}

-

Cómo buscar por misión específica:

-

1) Visita nuestra base de datos.

-

2) Busca allí el nombre de la misión.

-

3) Una vez que la hayas encontrado, su enlace se verá cómo "{QUEST_DB}/?quest=12843"

-

4) Usa el número final del enlace en el campo ID de misión (Ejemplo del enlace anterior: 12843).

+

{t('quest.howToSearch')}

+

{t.rich('quest.step1', { link: (c) => {c} })}

+

{t('quest.step2')}

+

{t.rich('quest.step3', { url: QUEST_DB, s: (c) => {c} })}

+

{t('quest.step4')}


-

Al usar el botón BUSCAR MISIONES, podrás ver el estado de las misiones del personaje.

+

{t('quest.searchButtonExplain')}


- NOTA +
-

Se requiere que el personaje esté desconectado y cumpla con el mínimo de nivel de cada opción.

-

Se puede repetir búsqueda de cadenas de misiones en un mismo personaje cada 1 hora.

-

Se puede repetir búsqueda de cadenas de misiones de clase en un mismo personaje cada 30 minutos.

-

Se puede repetir búsqueda de misión específica en un mismo personaje cada 10 minutos.

+

{t('quest.noteOffline')}

+

{t('quest.noteChain1h')}

+

{t('quest.noteClass30')}

+

{t('quest.noteSpecific10')}

diff --git a/web-next/app/[locale]/refund-policy/page.tsx b/web-next/app/[locale]/refund-policy/page.tsx index d62d672..370a2ae 100644 --- a/web-next/app/[locale]/refund-policy/page.tsx +++ b/web-next/app/[locale]/refund-policy/page.tsx @@ -1,104 +1,106 @@ import type { Metadata } from 'next' +import { getTranslations } from 'next-intl/server' export const metadata: Metadata = { title: 'Política de reembolso', } -export default function RefundPolicyPage() { +export default async function RefundPolicyPage() { + const t = await getTranslations('Legal') return (
-

Política de reembolso

+

{t('refund.title')}

-

NUESTRO SERVICIO

-

Todos nuestros servicios son de entrega inmediata y se reciben tal cual se encuentran descritos.

+

{t('refund.h1')}

+

{t('refund.p1')}




-

NUESTRA RESPONSABILIDAD

-

Garantizamos el funcionamiento, tiempo de entrega y descripción de los servicios brindados por nuestro sitio.

-

Es importante que el usuario comprenda que lo que adquiere en el sitio son servicios que se reciben de forma inmediata.

-

No adquiere tiempo de uso de los servicios, ni beneficio alguno, ni inmunidad.

-

Todo caso avalado por nuestra política de devolución será tratado con el reinicio o corrección del servicio y posterior revisión garantizando el funcionamiento correcto del servicio reiniciado o corregido.

+

{t('refund.h2')}

+

{t('refund.p2')}

+

{t('refund.p3')}

+

{t('refund.p4')}

+

{t('refund.p5')}




-

TIEMPO DE NOTIFICACIÓN

-

Cualquier error o problema de nuestros servicios debe ser notificado a la administración en un período máximo de 48 horas desde la entrega del servicio.

-

Pasado este período de tiempo, el usuario ya no puede solicitar ningún tipo de devolución.

-

Contacto: contacto@ultimowow.com.

+

{t('refund.h3')}

+

{t('refund.p6')}

+

{t('refund.p7')}

+

{t.rich('refund.p8', { link: (c) => {c} })}




-

COBERTURA

-

Esta política de devolución cubre:

-

- Adquisición del servicio incorrecto por una mala selección del usuario.

-

- Errores ocasionados por el sitio web que hayan impedido la entrega del servicio.

-

- Errores ocasionados por plataformas de terceros que hayan impedido la entrega del servicio.

+

{t('refund.h4')}

+

{t('refund.p9')}

+

{t('refund.p10')}

+

{t('refund.p11')}

+

{t('refund.p12')}


-

Esta política de devolución NO cubre, bajo ninguna circunstancia:

-

- Arrepentimientos.

-

- Errores en el uso del servicio realizados por el usuario.

-

- Desconocimiento de nuestra política de devolución.

-

- Uso incorrecto de plataformas de terceros con el fin de violar nuestra política de devolución.

-

- Expulsión de nuestro sitio por incumplimiento de nuestros términos y normas.

+

{t('refund.p13')}

+

{t('refund.p14')}

+

{t('refund.p15')}

+

{t('refund.p16')}

+

{t('refund.p17')}

+

{t('refund.p18')}


-

Solicitud de reembolso hecha a través de la plataforma de pago.

-

Pedir un reembolso por razones avaladas en esta política de devolución procederá a un reembolso de nuestra parte con la correspondiente cancelación del servicio adquirido.

+

{t('refund.h5')}

+

{t('refund.p19')}


-

Pedir un reembolso por razones no avaladas en esta política de devolución como:

-

- La cuenta ha sido sancionada.

-

- La persona ya no usa el servicio e intenta solicitar un reembolso posterior a las 48 hs del momento de la adquisición.

-

- Abuso de herramientas disponibles alegando razones que falten a la verdad respecto del servicio entregado.

-

No aplican para devolución y puede conllevar a la expulsión permanente del sitio por falta a nuestros términos y un uso inadecuado de las plataformas de pago disponibles.

+

{t('refund.p20')}

+

{t('refund.p21')}

+

{t('refund.p22')}

+

{t('refund.p23')}

+

{t('refund.p24')}




-

Arrepentimientos

-

Ningún tipo de arrepentimiento posterior a la entrega de un servicio aplica para devolución.

+

{t('refund.h6')}

+

{t('refund.p25')}




-

Errores en el uso del servicio realizados por el usuario

-

Errores en el uso de los servicios, ocasionados por el usuario, que no tienen relación con ningún tipo de falla en el servicio entregado no aplica para devolución.

-

Cualquier error de usuario ocasionado por no leer la descripción de un servicio no aplica para devolución.

-

Una vez que el servicio se encuentra entregado, el uso del mismo queda a responsabilidad del usuario.

+

{t('refund.h7')}

+

{t('refund.p26')}

+

{t('refund.p27')}

+

{t('refund.p28')}




-

Desconocimiento de nuestra política de devolución

-

El desconocimiento por parte del usuario de nuestra política de devolución no exime al usuario de su cumplimiento.

+

{t('refund.h8')}

+

{t('refund.p29')}




-

Uso incorrecto de plataformas de terceros con el fin de violar nuestra política de devolución

-

Este tipo de acciones conllevará a la expulsión del usuario de nuestro sitio sin ningún tipo de devolución.

+

{t('refund.h9')}

+

{t('refund.p30')}




-

Expulsión de nuestro sitio por incumplimiento de nuestros términos y normas

-

Ninguna adquisición de nuestros servicios otorga ningún tipo de inmunidad.

-

La expulsión de un usuario de nuestro sitio no aplica a ningún tipo de devolución.

-

El cumplimiento de nuestros términos y normas queda a exclusiva responsabilidad del usuario y cualquier expulsión que resulte del incumplimiento de los mismos no califica a solicitar devolución de los servicios ya entregados y disfrutados.

+

{t('refund.h10')}

+

{t('refund.p31')}

+

{t('refund.p32')}

+

{t('refund.p33')}




-

Cambios a esta Política de Reembolso

-

Nos reservamos el derecho de actualizar esta Política de Reembolso en cualquier momento. Le recomendamos que revise periódicamente esta página para conocer los cambios.

+

{t('refund.h11')}

+

{t('refund.p34')}




-

Contáctanos

-

Si tiene alguna pregunta o inquietud sobre esta Política de Reembolso, puede contactarnos a través de la siguiente información de contacto:

+

{t('refund.h12')}

+

{t('refund.p35')}

Error 404

ultimowow.com

info@ultimowow.com


-

Fecha de actualización: 25-05-2023

+

{t('refund.updated')}

diff --git a/web-next/app/[locale]/rename-character/page.tsx b/web-next/app/[locale]/rename-character/page.tsx index 2eb3b74..6f2acc4 100644 --- a/web-next/app/[locale]/rename-character/page.tsx +++ b/web-next/app/[locale]/rename-character/page.tsx @@ -1,5 +1,5 @@ import type { Metadata } from 'next' -import { setRequestLocale } from 'next-intl/server' +import { getTranslations, setRequestLocale } from 'next-intl/server' import { redirect } from '@/i18n/navigation' import { getSession } from '@/lib/session' import { getGameCharacters } from '@/lib/characters' @@ -22,43 +22,37 @@ export default async function RenameCharacterPage({ params }: { params: Promise< const [chars, price] = await Promise.all([getGameCharacters(session.accountId!), getRenamePrice()]) + const t = await getTranslations('CharServiceB.rename') + return (
-

- La herramienta Renombrar personaje te permite cambiar de nombre a un personaje. -

+

{t.rich('intro', { s: (c) => {c} })}


-

- Al usar el botón RENOMBRAR del personaje que hayas escogido, se enviará una petición de cambio de nombre de - dicho personaje. -

-

Cuando intentes entrar al reino con ese personaje, te pedirá que escojas un nuevo nombre.

+

{t('instructions')}

+

{t('newNameInfo')}


- NOTA + {t('noteLegend')}
-

- Por favor, asegúrate de haber escogido al personaje correcto ya que esta acción no es reversible una vez - realizada. -

+

{t('noteConfirm')}



-

Requiere {price} (SumUp)

+

{t.rich('requires', { price, s: (c) => {c}, y: (c) => {c} })}

({ name: c.name, classCss: c.classCss }))} checkoutEndpoint="/api/character/rename/checkout" - payLabel="RENOMBRAR" + payLabel={t('payLabel')} buttonClass="rename-button" provider="sumup" - confirmText={`¿Estás seguro de renombrar al personaje seleccionado por ${price} € (SumUp)?`} + confirmText={t('confirm', { price })} />
diff --git a/web-next/app/[locale]/rename-guild/page.tsx b/web-next/app/[locale]/rename-guild/page.tsx index 8dc6245..07cc44b 100644 --- a/web-next/app/[locale]/rename-guild/page.tsx +++ b/web-next/app/[locale]/rename-guild/page.tsx @@ -1,5 +1,5 @@ import type { Metadata } from 'next' -import { setRequestLocale } from 'next-intl/server' +import { getTranslations, setRequestLocale } from 'next-intl/server' import { redirect } from '@/i18n/navigation' import { getSession } from '@/lib/session' import { getGuildMasterGuilds, GUILD_RENAME_PD } from '@/lib/guild' @@ -14,6 +14,7 @@ export const metadata: Metadata = { title: 'Renombrar hermandad' } export default async function RenameGuildPage({ params }: { params: Promise<{ locale: string }> }) { const { locale } = await params setRequestLocale(locale) + const t = await getTranslations('Points') const session = await getSession() if (!session.bnetId) redirect({ href: '/login', locale }) @@ -22,33 +23,29 @@ export default async function RenameGuildPage({ params }: { params: Promise<{ lo const guilds = await getGuildMasterGuilds(session.accountId!) return ( - +

- La herramienta Renombrar hermandad te permite cambiar de nombre a una hermandad de la cual seas - Maestro de Hermandad. + {t.rich('renameGuild.intro1', { s: (c) => {c} })}


-

A la hora de escoger un nuevo nombre, ten en cuenta:

-

- La longitud máxima es de 24 caracteres.

-

- Los caracteres permitidos son A-Za-z y el espacio.

+

{t('renameGuild.rules')}

+

{t('renameGuild.rule1')}

+

{t('renameGuild.rule2')}


- Al usar el botón RENOMBRAR HERMANDAD de la hermandad que hayas escogido, se cambiará su nombre al nuevo nombre - que hayas ingresado. + {t('renameGuild.intro2')}

- El cambio de nombre de hermandad es instantáneo. Puede ser necesario que los miembros de la hermandad - conectados deban volver a conectar para finalmente ver el nuevo nombre. + {t('renameGuild.intro3')}


- NOTA + {t('renameGuild.note')}

- Por favor, asegúrate de haber elegido el nombre correcto ya que esta acción no es reversible una vez - realizada. + {t('renameGuild.noteText')}

@@ -56,7 +53,13 @@ export default async function RenameGuildPage({ params }: { params: Promise<{ lo


-

Requiere {GUILD_RENAME_PD} PD

+

+ {t.rich('renameGuild.requires', { + pd: GUILD_RENAME_PD, + s: (c) => {c}, + y: (c) => {c}, + })} +


diff --git a/web-next/app/[locale]/restore-character/page.tsx b/web-next/app/[locale]/restore-character/page.tsx index 6e223f4..fbde81f 100644 --- a/web-next/app/[locale]/restore-character/page.tsx +++ b/web-next/app/[locale]/restore-character/page.tsx @@ -1,5 +1,6 @@ import type { Metadata } from 'next' -import { setRequestLocale } from 'next-intl/server' +import { NoteLegend } from '@/components/NoteLegend' +import { getTranslations, setRequestLocale } from 'next-intl/server' import { redirect } from '@/i18n/navigation' import { getSession } from '@/lib/session' import { getRestorableCharacters } from '@/lib/restore-character' @@ -14,6 +15,7 @@ export const metadata: Metadata = { title: 'Recuperar personaje' } export default async function RestoreCharacterPage({ params }: { params: Promise<{ locale: string }> }) { const { locale } = await params setRequestLocale(locale) + const t = await getTranslations('CharService') const session = await getSession() if (!session.bnetId) redirect({ href: '/login', locale }) @@ -22,26 +24,26 @@ export default async function RestoreCharacterPage({ params }: { params: Promise const chars = await getRestorableCharacters(session.accountId!) return ( - +

- La herramienta Recuperar personaje te permite restaurar un personaje que haya sido borrado. + {t.rich('restoreChar.intro', { s: (c) => {c} })}


-

Sólo disponible para personajes que cumplan las siguientes dos condiciones:

-

- Nivel superior a 60.

-

- Borrado en un período menor a 30 días.

-

Para personajes Caballeros de la Muerte:

-

- No es posible recuperar un personaje Caballero de la Muerte si ya hay otro activo en la cuenta.

+

{t('restoreChar.conditions')}

+

{t('restoreChar.cond1')}

+

{t('restoreChar.cond2')}

+

{t.rich('restoreChar.dkHeading', { dk: (c) => {c} })}

+

{t('restoreChar.dkCond')}


-

Cuando ingreses a la lista de personajes de tu cuenta, verás al personaje recuperado.

+

{t('restoreChar.afterRestore')}


- NOTA +
-

Personajes borrados que no cumplan dichas condiciones ya no son recuperables.

-

Se puede repetir la acción en un mismo personaje cada 12 horas.

+

{t('restoreChar.noteConditions')}

+

{t('restoreChar.noteCooldown')}

diff --git a/web-next/app/[locale]/restore-items/page.tsx b/web-next/app/[locale]/restore-items/page.tsx index ea357c6..e7b7b0b 100644 --- a/web-next/app/[locale]/restore-items/page.tsx +++ b/web-next/app/[locale]/restore-items/page.tsx @@ -1,5 +1,6 @@ import type { Metadata } from 'next' -import { setRequestLocale } from 'next-intl/server' +import { NoteLegend } from '@/components/NoteLegend' +import { getTranslations, setRequestLocale } from 'next-intl/server' import { redirect } from '@/i18n/navigation' import { getSession } from '@/lib/session' import { getGameCharacters } from '@/lib/characters' @@ -15,6 +16,7 @@ export const metadata: Metadata = { title: 'Recuperar ítems' } export default async function RestoreItemsPage({ params }: { params: Promise<{ locale: string }> }) { const { locale } = await params setRequestLocale(locale) + const t = await getTranslations('CharService') const session = await getSession() if (!session.bnetId) redirect({ href: '/login', locale }) @@ -23,34 +25,39 @@ export default async function RestoreItemsPage({ params }: { params: Promise<{ l const [chars, price] = await Promise.all([getGameCharacters(session.accountId!), getRestoreItemPrice()]) return ( - +

- La herramienta Recuperar ítems te permite recuperar ítems que hayan sido borrados. + {t.rich('restoreItems.intro', { s: (c) => {c} })}


-

Sólo disponible para ítems que cumplan las siguientes condiciones:

+

{t('restoreItems.conditions')}

- - De calidad: Raro | Épico |{' '} - Legendaria | Artefacto | Reliquia. + {t.rich('restoreItems.quality', { + q3: (c) => {c}, + q4: (c) => {c}, + q5: (c) => {c}, + q6: (c) => {c}, + q6b: (c) => {c}, + })}

-

- Equipable.

-

- Se liga al recogerlo.

-

- Borrado en un período menor a 7 días.

+

{t('restoreItems.condEquip')}

+

{t('restoreItems.condBound')}

+

{t('restoreItems.condDeleted')}


- NOTA +
-

Ítems borrados que no cumplan dichas condiciones ya no son recuperables.

-

Se pueden consultar ítems borrados en un mismo personaje cada 8 horas.

+

{t('restoreItems.noteConditions')}

+

{t('restoreItems.noteCooldown')}



-

Cada ítem requiere {price} (SumUp)

+

{t.rich('restoreItems.requires', { price, s: (c) => {c}, e: (c) => {c} })}


({ name: c.name, classCss: c.classCss }))} price={price} />
diff --git a/web-next/app/[locale]/security-2falogin/page.tsx b/web-next/app/[locale]/security-2falogin/page.tsx index b6de089..d807ca9 100644 --- a/web-next/app/[locale]/security-2falogin/page.tsx +++ b/web-next/app/[locale]/security-2falogin/page.tsx @@ -1,5 +1,5 @@ import type { Metadata } from 'next' -import { setRequestLocale } from 'next-intl/server' +import { getTranslations, setRequestLocale } from 'next-intl/server' import { redirect, Link } from '@/i18n/navigation' import { getSession } from '@/lib/session' import { is2faEnabled } from '@/lib/two-factor' @@ -15,6 +15,7 @@ const IMG = '/nw-themes/nw-ryu/nw-images' export default async function Security2faLoginPage({ params }: { params: Promise<{ locale: string }> }) { const { locale } = await params setRequestLocale(locale) + const t = await getTranslations('Misc') const session = await getSession() if (!session.bnetId) redirect({ href: '/login', locale }) @@ -23,12 +24,12 @@ export default async function Security2faLoginPage({ params }: { params: Promise const enabled = session.accountId ? await is2faEnabled(session.accountId) : false return ( - +
-

Información

- Regresar a mi cuenta - Regresar +

{t('twofaLogin.info')}

+ {t('twofaLogin.backToAccount')} + {t('twofaLogin.back')}

@@ -36,30 +37,30 @@ export default async function Security2faLoginPage({ params }: { params: Promise Vista previa autenticador
-

2FA son las siglas de "Two Factor Authentication", o verificación en dos pasos.

+

{t.rich('twofaLogin.p1', { s: (c) => {c} })}


-

Es un método que añade una capa adicional de seguridad al proceso de inicio de sesión.

-

En lugar de simplemente ingresar tu nombre de usuario y contraseña, 2FA requiere un segundo paso de verificación, aumentando así la protección de tu cuenta.

+

{t('twofaLogin.p2')}

+

{t('twofaLogin.p3')}


-

Una vez activado, luego de ingresar usuario y contraseña, aparecerá una ventana (Imagen derecha) que te pedirá el código de autenticación generado por la aplicación.

+

{t('twofaLogin.p4')}


-

Códigos de respaldo

-

Al activar 2FA, se te proporcionarán códigos de respaldo únicos.

-

Estos códigos son útiles en caso de que pierdas acceso a tu aplicación de autenticación.

-

Cada código de respaldo puede usarse una sola vez.

-

Guárdalos en un lugar seguro, ya que te permitirán acceder a tu cuenta en el sitio web si no puedes usar la aplicación de autenticación.

+

{t('twofaLogin.backupCodes')}

+

{t('twofaLogin.p5')}

+

{t('twofaLogin.p6')}

+

{t('twofaLogin.p7')}

+

{t('twofaLogin.p8')}


-

Si aún no tienes Token de seguridad, puedes solicitarlo aquí.

+

{t.rich('twofaLogin.requestToken', { link: (c) => {c} })}


- NOTA + {t('twofaLogin.note')}
-

Utiliza una aplicación de autenticación para iniciar sesión en el juego una vez que lo tengas activado.

+

{t('twofaLogin.noteText')}

diff --git a/web-next/app/[locale]/security-history/page.tsx b/web-next/app/[locale]/security-history/page.tsx index a87d5d7..b1e0509 100644 --- a/web-next/app/[locale]/security-history/page.tsx +++ b/web-next/app/[locale]/security-history/page.tsx @@ -1,5 +1,5 @@ import type { Metadata } from 'next' -import { setRequestLocale } from 'next-intl/server' +import { setRequestLocale, getTranslations } from 'next-intl/server' import { redirect } from '@/i18n/navigation' import { getSession } from '@/lib/session' import { getSecurityHistory } from '@/lib/security-history' @@ -35,6 +35,7 @@ function UserCell({ label, bnet }: { label: string; bnet: string }) { export default async function SecurityHistoryPage({ params }: { params: Promise<{ locale: string }> }) { const { locale } = await params setRequestLocale(locale) + const t = await getTranslations('History') const session = await getSession() if (!session.bnetId) redirect({ href: '/login', locale }) @@ -45,39 +46,37 @@ export default async function SecurityHistoryPage({ params }: { params: Promise< const { activity, realm, web } = await getSecurityHistory(session.accountId!, displayUser, bnetEmail) return ( - +
-

Aquí verás información de actividad y conexiones de tu cuenta.

-

Cada tabla tiene una explicación detallada de la información provista.

+

{t('security.intro1')}

+

{t('security.intro2')}

- Si desconoces algún tipo de actividad te recomendamos cambiar la contraseña de tu cuenta y del correo ligado a - la misma. + {t('security.intro3')}


- Historial de actividad + {t('security.activityTitle')}

-

Muestra actividad de seguridad de la cuenta, como por ejemplo cambios de contraseña.

+

{t('security.activityDesc')}


- Historial de conexiones (Reino) + {t('security.realmTitle')}

- Muestra un historial de conexiones al reino sólo cuando la IP ha cambiado. No es un historial de cada - conexión. + {t.rich('security.realmDesc', { u: (c) => {c} })}


- Historial de conexiones (Web) + {t('security.webTitle')}

-

Muestra un historial de cada conexión al sitio web.

+

{t('security.webDesc')}

{/* Historial de actividad */}
-

Historial de actividad

+

{t('security.activityTitle')}

{activity.length === 0 ? ( @@ -85,7 +84,7 @@ export default async function SecurityHistoryPage({ params }: { params: Promise<
@@ -94,10 +93,10 @@ export default async function SecurityHistoryPage({ params }: { params: Promise<
FechaConceptoMétodo{t('points.thDate')}{t('points.thConcept')}{t('points.thMethod')} PD PVImporteEstado{t('points.thAmount')}{t('points.thStatus')}
- No hay actividad + {t('security.noActivity')}
- - + + - + {activity.map((a, i) => ( @@ -122,7 +121,7 @@ export default async function SecurityHistoryPage({ params }: { params: Promise< {/* Historial de conexiones (Reino) */}
-

Historial de conexiones (Reino)

+

{t('security.realmTitle')}

{realm.length === 0 ? ( @@ -130,7 +129,7 @@ export default async function SecurityHistoryPage({ params }: { params: Promise<
@@ -140,7 +139,7 @@ export default async function SecurityHistoryPage({ params }: { params: Promise< - + {realm.map((c, i) => ( @@ -161,7 +160,7 @@ export default async function SecurityHistoryPage({ params }: { params: Promise< {/* Historial de conexiones (Web) */}
-

Historial de conexiones (Web)

+

{t('security.webTitle')}

{web.length === 0 ? ( @@ -169,7 +168,7 @@ export default async function SecurityHistoryPage({ params }: { params: Promise<
@@ -178,10 +177,10 @@ export default async function SecurityHistoryPage({ params }: { params: Promise<
UsuarioAcción{t('security.thUser')}{t('security.thAction')} IPFecha{t('security.thDate')}
- No hay conexiones + {t('security.noConnections')}
IPFecha{t('security.thDate')}
- No hay conexiones + {t('security.noConnections')}
- - + + - + {web.map((c, i) => ( diff --git a/web-next/app/[locale]/security-token/page.tsx b/web-next/app/[locale]/security-token/page.tsx index 70ec475..445d6c0 100644 --- a/web-next/app/[locale]/security-token/page.tsx +++ b/web-next/app/[locale]/security-token/page.tsx @@ -1,4 +1,5 @@ import type { RowDataPacket } from 'mysql2' +import { NoteLegend } from '@/components/NoteLegend' import { getTranslations, setRequestLocale } from 'next-intl/server' import { redirect } from '@/i18n/navigation' import { getSession } from '@/lib/session' @@ -41,7 +42,7 @@ export default async function SecurityTokenPage({ params }: { params: Promise<{

{t('warning')}


- NOTA +

{t('note')}

diff --git a/web-next/app/[locale]/send-gift/page.tsx b/web-next/app/[locale]/send-gift/page.tsx index b5cdf4c..99a0cc5 100644 --- a/web-next/app/[locale]/send-gift/page.tsx +++ b/web-next/app/[locale]/send-gift/page.tsx @@ -1,5 +1,6 @@ import type { Metadata } from 'next' -import { setRequestLocale } from 'next-intl/server' +import { NoteLegend } from '@/components/NoteLegend' +import { getTranslations, setRequestLocale } from 'next-intl/server' import { redirect, Link } from '@/i18n/navigation' import { getSession } from '@/lib/session' import { getGameCharacters } from '@/lib/characters' @@ -15,6 +16,7 @@ export const metadata: Metadata = { title: 'Enviar regalo' } export default async function SendGiftPage({ params }: { params: Promise<{ locale: string }> }) { const { locale } = await params setRequestLocale(locale) + const t = await getTranslations('CharService') const session = await getSession() if (!session.bnetId) redirect({ href: '/login', locale }) @@ -24,38 +26,31 @@ export default async function SendGiftPage({ params }: { params: Promise<{ local const currency = process.env.SUMUP_CURRENCY === 'EUR' ? '€' : process.env.SUMUP_CURRENCY || '€' return ( - +

- La herramienta Enviar regalo te permite enviar regalos a tus amigos. + {t.rich('sendGift.intro', { s: (c) => {c} })}


- Al elegir desde qué personaje se enviará el regalo y el personaje que lo recibirá, podrás ver la lista de - objetos disponibles para enviar como regalo. + {t('sendGift.explain1')}

-

Los objetos disponibles son los mismos de la tienda y puedes enviar varios objetos a la vez.

+

{t('sendGift.explain2')}


- Al usar el botón ENVIAR REGALO se enviará un correo al personaje destino con los ítems seleccionados, - indicando quién lo ha regalado. El pago se realiza mediante SumUp. + {t.rich('sendGift.explain3', { s: (c) => {c} })}


- Si aún no tienes Token de seguridad, puedes solicitarlo{' '} - - aquí - - . + {t.rich('sendGift.securityTokenHint', { link: (c) => {c} })}


- NOTA +

- Por favor, asegúrate de haber escrito el nombre del personaje correcto ya que esta acción no es - reversible una vez realizada. + {t('sendGift.noteIrreversible')}

diff --git a/web-next/app/[locale]/terms-and-conditions/page.tsx b/web-next/app/[locale]/terms-and-conditions/page.tsx index c57dce1..e3c9751 100644 --- a/web-next/app/[locale]/terms-and-conditions/page.tsx +++ b/web-next/app/[locale]/terms-and-conditions/page.tsx @@ -1,112 +1,114 @@ import type { Metadata } from 'next' +import { getTranslations } from 'next-intl/server' export const metadata: Metadata = { title: 'Términos y condiciones', } -export default function TermsAndConditionsPage() { +export default async function TermsAndConditionsPage() { + const t = await getTranslations('Legal') return (
-

Términos y condiciones

+

{t('terms.title')}

- IMPORTANTE -

Por favor, tómese un momento para leer los términos y condiciones detallados debajo. Si está de acuerdo con ellos, entonces podrá ingresar en nuestro sitio.

+ {t('terms.h1')} +

{t('terms.p1')}




- ACEPTACIÓN DE LOS TÉRMINOS DE USO Y CONDICIONES -

UltimoWoW es un proyecto sin ánimo de lucro desarrollado con la finalidad de simular versiones desactualizadas del servidor con fines únicamente educativos. Los Servicios ofrecidos por UltimoWoW no apoyan ni proveerán modificación de ningún tipo para con el servidor o sus ficheros, dicho esto, el usuario al hacer uso de este sitio o cualquier servicio perteneciente o derivado de la Administración, acepta hacerse responsable de seguir y cumplir con el contrato de licencia para usuarios finales (EULA) del servidor.

+ {t('terms.h2')} +

{t('terms.p2')}


-

UltimoWoW no provee ni se responsabiliza por la distribución de ningún cliente del servidor o fuente externa que lo contenga. Los enlaces de descarga para el cliente ofrecidos por este sitio o cualquier medio bajo su responsabilidad, apuntarán siempre a dichas fuentes externas, las cuales, a la fecha no pertenecen ni poseen relación alguna con esta administración. No haciéndose UltimoWoW de esta manera, y bajo ningún concepto, responsable sobre aspecto alguno sobre dicha fuente, dígase: calidad, rendimiento, garantías o cualquiera fuese o no, característica determinante a su fin.

+

{t('terms.p3')}


-

Al acceder, navegar o usar este sitio de Internet y en adelante (el “Sitio”), propiedad de la administración UltimoWoW en adelante (la “Administración”), el usuario admite haber leído y entendido los presentes términos y condiciones de uso, en adelante (“Términos y Condiciones”) y está de acuerdo en acatar los mismos y cumplir con todas las normas, leyes y reglamentos aplicables que hagan parte de la legislación vigente en su lugar de residencia, o a las que se sujete indistintamente. Además, cuando el usuario utilice cualquier servicio suministrado o referenciado en el Sitio, (siempre y cuando éste resida bajo responsabilidad o propiedad de la Administración) estará sujeto a las reglas, guías, políticas, términos y condiciones aplicables a dichos servicios.

+

{t('terms.p4')}


-

Este Sitio es controlado y desarrollado por la Administración, localizable a través de sus plataformas de Discord.

+

{t('terms.p5')}


-

La Administración no es responsable de que el material en este Sitio sea apropiado o esté disponible para su uso en otros lugares, estando prohibido su acceso desde territorios donde su contenido sea ilegal. Aquellos que decidan acceder a este Sitio desde otros lugares lo harán bajo su propia iniciativa, y es su responsabilidad el sujetarse a las leyes locales que sean aplicables.

+

{t('terms.p6')}


-

Estos Términos y Condiciones están sujetos a cambios a discreción, sin previo aviso y en cualquier momento, bajo la sola voluntad de UltimoWoW, y partiendo de la fecha de publicación de la modificación de los mismos en este Sitio, todas las operaciones celebradas entre la Administración y el usuario se regirán por el documento modificado.

+

{t('terms.p7')}




- NUESTRO SERVICIO: USO, DISTRIBUCIÓN Y DESCARGO DE RESPONSABILIDADES -

De conformidad con las legislaciones bajo las cuales la Administración se acate, el material contenido en este Sitio o cualquier otro que se encontrase bajo su responsabilidad o tutela y en adelante, (los “Servicios” o el “Servicio”), incluyendo sin limitación, toda imagen, links, logotipo, diseño, insignia, marca, fotografía, sonido, texto, mensaje, herramienta, software, tecnología, producto, archivo, información, dato, demostración, muestra, material promocional, obra audiovisual u obra multimedia, y cualquiera sea otro elemento o forma de expresión (de forma colectiva y en adelante, (los "Materiales"), son suministrados según nuestro leal saber y entender, sin embargo, no es posible descartar errores de contenido o del material, razón por la cual la Administración no asume responsabilidad por la calidad, veracidad o exactitud, de la información publicada ni por las omisiones, errores o discrepancias que pudiesen encontrarse en la información publicada o servicio brindado.

+ {t('terms.h3')} +

{t('terms.p8')}


-

Respecto a la información publicada en los Servicios, la Administración no confiere garantías de ningún tipo, expresas ni implícitas, excluyendo, más no limitado a:

-

- Garantías de comerciabilidad o adecuación para un propósito particular.

-

- Estabilidad ininterrumpida del Servicio.

-

- Existencia de errores o virus, así como sobre su seguridad.

-

- Exactitud, confiabilidad, calificación o certificación para su descarga.

+

{t('terms.p9')}

+

{t('terms.p10')}

+

{t('terms.p11')}

+

{t('terms.p12')}

+

{t('terms.p13')}


-

La Administración no se hace responsable sobre el uso que el usuario haga de los contenidos incluidos en los Servicios, ni de las decisiones que tome respecto a éstos. La información respecto a los productos y servicios de UltimoWoW, incluida en sus Servicios es brindada con fines edcuativos no comerciales y no constituye oferta de venta para sus usuarios.

+

{t('terms.p14')}


-

UltimoWoW se reserva el derecho de a discreción:

-

- Corregir cualquier error, omisión o inexactitud en los datos brindados.

-

- Cambiar o actualizar, descontinuar o eliminar la información contenida en los Servicios en cualquier momento y sin previo aviso.

-

- Así como también se exime de responsabilidad sobre lo que refiere a la puntualidad, falta de almacenamiento, inexactitud o entrega incorrecta de cualquier información o dato de los que “normalmente” proporcione, ya sea temporal o permanentemente.

+

{t('terms.p15')}

+

{t('terms.p16')}

+

{t('terms.p17')}

+

{t('terms.p18')}




- RESPONSABILIDADES Y OBLIGACIONES DE REGISTRO Y CONTRASEÑAS -

El usufructo de las principales funciones fundamentales y objetivas del Servicio estará siempre determinado y sujeto a la existencia de un registro personal e intransferible (dígase cuenta de usuario). La Administración le exhorta a proporcionar información veraz y comprobable según fuese la misma solicitada. Más allá de un carácter intrusivo, dicha información se haría utilizar estricta y discretamente en aras de posibilitar a futuro, una resolución por parte de la Administración, de alguna situación extraordinaria que surgiese por descuidos de parte del usuario, intentando así dictar la misma en la forma menos perjudicial posible para con este.

+ {t('terms.h4')} +

{t('terms.p19')}


-

Pertenece completa y estrictamente, y recae sobre el usuario la responsabilidad de mantener confidenciales y de forma segura las contraseñas establecidas para con el Servicio. Así como de las acciones a través del uso de su registro que pudiesen estar estas bajo autorización o no indistintamente por parte del usuario. Queda así también bajo responsabilidad del usuario, la notificación inmediata a la Administración si éste notase alguna actividad sospechosa, uso no autorizado o registro no concebido en el que figurase su propia cuenta como objeto de manipulación, o violación.

+

{t('terms.p20')}


-

Queda terminantemente prohibido el intercambio, comercio, compra-venta y cualquier actividad similar de cualquier forma y bajo cualquier concepto donde figurase e involucrase el conocimiento por parte de cualquiera persona ajena al usuario; de sus credenciales de acceso al Servicio. Violar dichas prohibiciones podría hacer incurrir al usuario en una falta grave, la cual podría sancionarse con penalizaciones de magnitud determinada por la Administración a su juicio y a discreción, la cual en ningún caso quedaría exenta de dicha penalización mediante alegato de uso por parte de terceros y en general bajo ninguna justificación.

+

{t('terms.p21')}


-

Los personajes del reino que hubiesen sido borrados y alcanzados estos, el límite máximo de tiempo (on-hold) para recuperación, establecido por la Administración, desaparecerán permanentemente, claudicando con ellos la posibilidad de restauración o asistencia por parte de la Administración en estos casos, independientemente y descartando por completo la voluntad del usuario para con tal acción en dicho momento.

+

{t('terms.p22')}




- HACER TRAMPA -

Se entiende como trampa cualquier acto fuera y dentro del servidor, que intente alterar o de hecho altere e interfiera con las reglas o con el comportamiento normal del servidor. Así como intentar o de hecho aventajarse sobre otros jugadores. Entre ello, a título meramente enunciativo y sin ánimo limitativo, cualquiera de los siguientes comportamientos, ya sea en su propio nombre o por cuenta de terceros será considerado como tal:

-

- Acceder a los Servicios de manera no autorizada (incluyendo el uso de software modificado o malicioso).

-

- Utilizar varias cuentas a la vez en un mismo reino de una forma en la que controlar varios personajes al unísono y sobre el mismo reino, suponga una desventaja de cualquier índole para otros usuarios con respecto infractor.

-

- Utilizar cualquier técnica o software para alterar o manipular las variables preestablecidas por el servidor y la Administración.

+ {t('terms.h5')} +

{t('terms.p23')}

+

{t('terms.p24')}

+

{t('terms.p25')}

+

{t('terms.p26')}


-

Se prohíbe terminantemente hacer trampas y la Administración se reserva el derecho de denegar a cualquier usuario el acceso al Servicio, siempre y cuando hubiere incurrido o fuese objeto de una falta de este tipo ya fuese directa e indirectamente.

+

{t('terms.p27')}




- COMPRAS, RECLAMACIONES, REEMBOLSOS Y GARANTÍAS -

UltimoWoW no representa ni constituye entidad remesadora ni de servicios financieros de ninguna índole y en consecuencia no posee control o responsabilidad alguna sobre el origen de aquellos fondos utilizados para realizar compras hacia su comunidad. Así como tampoco se responsabiliza por los riesgos que el usuario tomase bajo su propia voluntad, a la hora de ejecutar operaciones financieras de cualquier tipo.

+ {t('terms.h6')} +

{t('terms.p28')}


-

Las compras: serán consideradas siempre de fe voluntaria y en ningún caso, obligación de ningún tipo para ningún usuario. Nótese además que quedan terminantemente prohibidos las compras por parte de personas naturales menores de 18 años o dígase en cualquier caso aquellas personas que no alcanzaran aún al amparo de las entidades legales locales y pertinentes que le competan, su mayoría de edad.

+

{t('terms.p29')}


-

El Servicio: en cualquier caso, no requiere ningún tipo de compra para un uso y disfrute total y a plenitud. Dicho esto, el usuario contará con un canal de comunicación oficial vía email contacto@ultimowow.com con el objetivo de notificar a la Administración de cualquier error cometido por cualquiera de las partes, en aras de emitir y hacer efectiva justa resolución

+

{t('terms.p30')}


-

La Administración: garantiza y se compromete en brindar al comprador toda información que requiriese sobre las formas o métodos de compra vigentes para con la comunidad. Así como aclarar cualquier duda que pudiese surgir sobre los pasos o procesos establecidos de las mismas, siempre y cuando dicha información resida dentro de los límites que competan al comprador y posea un propósito únicamente informativo.

+

{t('terms.p31')}


-

Tomado en cuenta lo anterior, el comprador cuenta con garantías de reembolso monetario y de servicios, atendiendo a aspectos y condiciones expuestos a continuación.

-

Monetarios:

-

Tomando en cuenta el carácter que posee cualquier transacción monetaria hacia las arcas de la comunidad, la Administración se compromete a reembolsar (libre de costos por transacción, a consideración de la misma), de forma total o parcial, en definitiva, colegiada conjuntamente entre ambas partes, aquellas compras donde no intencionalmente, el usuario quedase bajo la inconveniencia a la hora de realizar la misma, de errores por su parte en la cuantía del monto total a transferir. Siendo dicho error en todos los casos veraz y de comprobable naturaleza a consideración de la administración.

+

{t('terms.p32')}

+

{t('terms.h7')}

+

{t('terms.p33')}


-

Tomando en cuenta que los servicios adquiridos se reciben de forma inmediata y no constituyen, determinan, pactan ni modifican plazo alguno para su uso. Así como tampoco para el usufructo del servicio y sus funcionalidades los cuales, recalcado sea de paso, se consideran completamente gratuitos, de carácter educativo y carecen de plazos de admisión y vencimiento.

+

{t('terms.p34')}


-

La Administración no garantiza ni proporcionará en ningún caso ni bajo ningún concepto o circunstancia, reembolso alguno sobre compras o cualquier bien en general transferido a la comunidad. Nótense y háganse aclaratorios lo siguientes casos:

-

- A usuarios cuyas cuentas hayan sido sancionadas temporal o permanentemente por incurrir en alguna falta expuesta en cualquiera de sus Términos y Condiciones.

-

- A usuarios que hubiesen tomado la decisión de no continuar (parcial o temporalmente) haciendo uso de cualquiera de los servicios prestados por La Administración.

+

{t('terms.p35')}

+

{t('terms.p36')}

+

{t('terms.p37')}


-

En ninguno de estos casos la Administración presentará completa ni parcialmente traza alguna de ninguno de sus registros monetarios o de cualquier tipo para fines resolutorios.

+

{t('terms.p38')}


-

Igualmente, el usuario dispone de las respectivas vías y canales, dígase dentro de los foros del Servicio, o servidor de Discord para presentar una apelación formal ante un administrador y ser así evaluado el caso para posterior resolución. La Administración se reserva el derecho de evaluar más no garantizar y a discreción, reembolsos en aquellos casos donde después de estudiado y conciliado, fuese considerado por la misma, justo y extraordinario.

+

{t('terms.p39')}


-

De servicios:

-

La Administración le garantiza la integridad y funcionalidad de todos los artículos comprados en su tienda. En todo caso, ésta le proveerá un término de 48 horas posterior a su compra para solicitar reemplazos por artículos o servicios de igual valor, o también y a solicitud, la devolución íntegra de los servicios utilizados en aquellos casos donde se encontrarse dicho artículo o servicio roto o inutilizable, o hubiere sido comprado o elegido por error, todo esto siempre y después de efectuado un análisis pertinente por parte de un administrador, y de demostradas pruebas auténticas y concluyentes por parte del usuario a fines con el caso.

+

{t('terms.h8')}

+

{t('terms.p40')}


-

Así como también la Administración garantizará la restauración del servicio por problemas técnicos y puntuales, entre el Servicio y las plataformas de pago siempre ajenos al comprador, no fuesen entregados dichos servicios de forma automática e inmediata a nombre del mismo.

+

{t('terms.p41')}




- POLÍTICA DE PRIVACIDAD -

El Servicio y la Administración recopilan información referente al usuario tales como dirección de correo electrónico, nombre, contraseña, idioma y zona horaria, con el fin de brindarle una mejor optimización cada vez a sus servicios, utilizando esta información para acomodar las funcionalidades a un mejor rendimiento a fin con el usuario y sus requerimientos. Dicha información también podrá ser usada para mantener al usuario mediante canales de comunicaciones independientes y no referentes al Servicio, informando sobre noticias importantes, actualizaciones, problemas técnicos o cualquier otra información de tal índole que considerase la Administración relevante a los intereses del usuario.

+ {t('terms.h9')} +

{t('terms.p42')}


-

La Administración y el Servicio se comprometen a salvaguardar la confidencialidad sobre tales datos, así como a garantizar la NO divulgación de estos, exceptuando los casos donde las leyes vigentes que rigiesen sobre la Administración lo consideraran necesario y mandatorio por motivos no referentes a UltimoWoW.

+

{t('terms.p43')}


Error 404

info@ultimowow.com

diff --git a/web-next/app/[locale]/trade-points/page.tsx b/web-next/app/[locale]/trade-points/page.tsx index dca76da..7f12b31 100644 --- a/web-next/app/[locale]/trade-points/page.tsx +++ b/web-next/app/[locale]/trade-points/page.tsx @@ -1,5 +1,5 @@ import type { Metadata } from 'next' -import { setRequestLocale } from 'next-intl/server' +import { getTranslations, setRequestLocale } from 'next-intl/server' import { redirect, Link } from '@/i18n/navigation' import { getSession } from '@/lib/session' import { getGameCharacters } from '@/lib/characters' @@ -14,6 +14,7 @@ export const metadata: Metadata = { title: 'Comercio de PD' } export default async function TradePointsPage({ params }: { params: Promise<{ locale: string }> }) { const { locale } = await params setRequestLocale(locale) + const t = await getTranslations('Points') const session = await getSession() if (!session.bnetId) redirect({ href: '/login', locale }) @@ -22,59 +23,62 @@ export default async function TradePointsPage({ params }: { params: Promise<{ lo const chars = await getGameCharacters(session.accountId!) return ( - +

- La herramienta Comercio de PD permite comprar o vender PD a cambio de oro de una forma segura. + {t.rich('trade.intro1', { s: (c) => {c} })}


-

El sistema permite crear códigos de 1 solo uso que valdrán X cantidad de PD a cambio de X cantidad de oro.

+

{t('trade.intro2')}

- Los vendedores disponen de la sección VENTA para crear el código y los compradores disponen de la sección - COMPRA para canjear dicho código. + {t('trade.intro3')}


-

Venta

-

1) Decide cuánto valdrá el código en PD.

-

2) Decide por cuánto oro se podrá canjear.

-

3) Escoge a qué personaje de la cuenta se enviará el oro cuando el código sea canjeado.

-

4) Completa los datos con la contraseña y Token de Seguridad.

-

5) Usa el botón CREAR CÓDIGO.

-

6) Un recuadro aparecerá con los datos del Código creado con el ID que se debe usar para enviar a otro jugador.

+

{t('trade.sellTitle')}

+

{t('trade.sell1')}

+

{t('trade.sell2')}

+

{t('trade.sell3')}

+

{t('trade.sell4')}

+

{t('trade.sell5')}

+

{t('trade.sell6')}


-

Compra

-

1) Ingresa ID del código que te ha dado otro jugador.

-

2) Chequea el valor en PD y costo en oro con el botón CHEQUEAR CÓDIGO.

-

3) Escoge de qué personaje de la cuenta se descontará el oro cuando el código sea canjeado.

-

4) Completa los datos con la contraseña y Token de Seguridad.

-

5) Usa el botón CANJEAR CÓDIGO.

-

6) Un recuadro aparecerá con los datos del Código canjeado, PD recibidos y oro retirado del personaje seleccionado.

+

{t('trade.buyTitle')}

+

{t('trade.buy1')}

+

{t('trade.buy2')}

+

{t('trade.buy3')}

+

{t('trade.buy4')}

+

{t('trade.buy5')}

+

{t('trade.buy6')}



-

Cada código tiene una duración de 1 hora.

-

Una vez canjeado el código:

-

- Los PD serán retirados de la cuenta del creador del código y enviados a quien lo haya canjeado.

-

- El oro será retirado y enviado por correo al creador.

-

- La transacción quedará registrada en el Historial de PD y PV.

+

{t('trade.duration')}

+

{t('trade.onceRedeemed')}

+

{t('trade.redeemed1')}

+

{t('trade.redeemed2')}

+

{t('trade.redeemed3')}


-

La cuenta de quien canjee el código será bloqueada por 5s como medida de seguridad si el trámite es exitoso.

+

{t('trade.lockNote')}


- Si aún no tienes Token de seguridad, puedes solicitarlo{' '} - aquí. + {t.rich('trade.tokenHelp', { + link: (c) => ( + + {c} + + ), + })}


- NOTA + {t('trade.note')}

- Por favor, asegúrate de haber escrito todos los datos correctos ya que esta acción no es reversible una - vez realizada. + {t('trade.noteText')}

diff --git a/web-next/app/[locale]/trans-history/page.tsx b/web-next/app/[locale]/trans-history/page.tsx index 4a729b1..5618843 100644 --- a/web-next/app/[locale]/trans-history/page.tsx +++ b/web-next/app/[locale]/trans-history/page.tsx @@ -1,5 +1,5 @@ import type { Metadata } from 'next' -import { setRequestLocale } from 'next-intl/server' +import { setRequestLocale, getTranslations } from 'next-intl/server' import { redirect } from '@/i18n/navigation' import { getSession } from '@/lib/session' import { getPaymentTransactions, type PaymentTx } from '@/lib/trans-history' @@ -21,7 +21,7 @@ function StatusBadge({ status }: { status: PaymentTx['status'] }) { } /** Caja de una pasarela con su tabla de transacciones (o "No hay movimientos"). */ -function PlatformBox({ +async function PlatformBox({ name, logo, note, @@ -32,6 +32,7 @@ function PlatformBox({ note: string txs: PaymentTx[] }) { + const t = await getTranslations('History') return (
@@ -41,12 +42,11 @@ function PlatformBox({

- Recibirás los PD correspondientes a cada transacción sólo cuando esté aprobada y el estado sea{' '} - PAID (Pagado). + {t.rich('trans.paidNote', { s: (c) => {c} })}


- Importante: {note} + {t('trans.important')} {note}


{txs.length === 0 ? ( @@ -54,7 +54,7 @@ function PlatformBox({
@@ -63,11 +63,11 @@ function PlatformBox({
UsuarioEstado{t('security.thUser')}{t('security.thStatus')} IPFecha{t('security.thDate')}
- No hay movimientos + {t('trans.noMovements')}
- - - - - + + + + + {txs.map((t) => ( @@ -101,6 +101,7 @@ const LOGO_BASE = '/nw-themes/nw-ryu/nw-images/nw-logos' export default async function TransHistoryPage({ params }: { params: Promise<{ locale: string }> }) { const { locale } = await params setRequestLocale(locale) + const t = await getTranslations('History') const session = await getSession() if (!session.bnetId) redirect({ href: '/login', locale }) @@ -111,23 +112,23 @@ export default async function TransHistoryPage({ params }: { params: Promise<{ l const sumup = txs.filter((t) => t.platform === 'SumUp') return ( - +
-

Aquí verás la información que recibimos de nuestras diferentes plataformas de pago automáticas.

+

{t('trans.intro1')}


-

¿Has tenido algún problema con alguna transacción?

+

{t('trans.intro2')}

- Si has tenido un problema con una de las transacciones o no has recibido tus PD, puedes contactarnos en - nuestro Discord o a través del correo{' '} - contacto@ultimowow.com. + {t.rich('trans.intro3', { + mail: (c) => {c}, + })}



@@ -136,7 +137,7 @@ export default async function TransHistoryPage({ params }: { params: Promise<{ l
diff --git a/web-next/app/[locale]/transfer-character/page.tsx b/web-next/app/[locale]/transfer-character/page.tsx index 8a6fec7..0ef0a01 100644 --- a/web-next/app/[locale]/transfer-character/page.tsx +++ b/web-next/app/[locale]/transfer-character/page.tsx @@ -1,5 +1,6 @@ import type { Metadata } from 'next' -import { setRequestLocale } from 'next-intl/server' +import { NoteLegend } from '@/components/NoteLegend' +import { getTranslations, setRequestLocale } from 'next-intl/server' import { redirect, Link } from '@/i18n/navigation' import { getSession } from '@/lib/session' import { getGameCharacters } from '@/lib/characters' @@ -15,6 +16,7 @@ export const metadata: Metadata = { title: 'Transferir personaje' } export default async function TransferCharacterPage({ params }: { params: Promise<{ locale: string }> }) { const { locale } = await params setRequestLocale(locale) + const t = await getTranslations('CharService') const session = await getSession() if (!session.bnetId) redirect({ href: '/login', locale }) @@ -23,35 +25,33 @@ export default async function TransferCharacterPage({ params }: { params: Promis const [chars, price] = await Promise.all([getGameCharacters(session.accountId!), getTransferPrice()]) return ( - +

- La herramienta Transferir personaje te permite mover un personaje a otra cuenta. + {t.rich('transfer.intro', { s: (c) => {c} })}


-

Para personajes Caballeros de la Muerte:

-

- La cuenta destino debe tener aunque sea un personaje con nivel 55 o superior.

-

- La cuenta destino no puede tener un personaje Caballero de la Muerte.

+

{t.rich('transfer.dkHeading', { dk: (c) => {c} })}

+

{t('transfer.dkCond1')}

+

{t('transfer.dkCond2')}


-

Tu cuenta será bloqueada por 5s como medida de seguridad si el trámite es exitoso.

+

{t('transfer.securityLock')}


- Al usar el botón TRANSFERIR PERSONAJE del personaje que hayas escogido, se transferirá desde tu cuenta a la - cuenta que hayas indicado. + {t('transfer.buttonExplain')}

-

Cuando ingreses a la lista de personajes de la cuenta destino, verás al personaje transferido.

+

{t('transfer.afterTransfer')}


-

Si aún no tienes Token de seguridad, puedes solicitarlo aquí.

-

Si aún no tienes 2FA, puedes solicitarlo aquí.

+

{t.rich('transfer.securityTokenHint', { link: (c) => {c} })}

+

{t.rich('transfer.twoFaHint', { link: (c) => {c} })}


- NOTA +
-

Se requiere que el personaje esté desconectado.

+

{t('transfer.noteOffline')}

- Por favor, asegúrate de haber escogido al personaje correcto ya que esta acción no es reversible una vez - realizada. + {t('transfer.noteIrreversible')}

@@ -59,7 +59,7 @@ export default async function TransferCharacterPage({ params }: { params: Promis


-

Requiere {price} (SumUp)

+

{t.rich('transfer.requires', { price, s: (c) => {c}, e: (c) => {c} })}

({ name: c.name, classCss: c.classCss }))} price={price} /> diff --git a/web-next/app/[locale]/transfer-d-points/page.tsx b/web-next/app/[locale]/transfer-d-points/page.tsx index c298d79..872b4dc 100644 --- a/web-next/app/[locale]/transfer-d-points/page.tsx +++ b/web-next/app/[locale]/transfer-d-points/page.tsx @@ -1,5 +1,5 @@ import type { Metadata } from 'next' -import { setRequestLocale } from 'next-intl/server' +import { getTranslations, setRequestLocale } from 'next-intl/server' import { redirect, Link } from '@/i18n/navigation' import { getSession } from '@/lib/session' import { getDPointsBalance } from '@/lib/dpoints' @@ -14,6 +14,7 @@ export const metadata: Metadata = { title: 'Transferir PD' } export default async function TransferDPointsPage({ params }: { params: Promise<{ locale: string }> }) { const { locale } = await params setRequestLocale(locale) + const t = await getTranslations('Points') const session = await getSession() if (!session.bnetId) redirect({ href: '/login', locale }) @@ -22,29 +23,32 @@ export default async function TransferDPointsPage({ params }: { params: Promise< const balance = await getDPointsBalance(session.accountId!) return ( - +

- La herramienta Transferir PD permite transferir PD desde tu cuenta a cualquier otra cuenta. + {t.rich('transferDp.intro1', { s: (c) => {c} })}


- Al usar el botón TRANSFERIR PD se transferirá la cantidad que hayas escogido desde tu cuenta a la cuenta del - personaje que hayas indicado. + {t('transferDp.intro2')}


- Si aún no tienes Token de seguridad, puedes solicitarlo{' '} - aquí. + {t.rich('transferDp.tokenHelp', { + link: (c) => ( + + {c} + + ), + })}


- NOTA + {t('transferDp.note')}

- Por favor, asegúrate de haber escrito el nombre del personaje correcto ya que esta acción no es reversible - una vez realizada. + {t('transferDp.noteText')}

diff --git a/web-next/app/[locale]/unstuck-character/page.tsx b/web-next/app/[locale]/unstuck-character/page.tsx index 6f21173..628edb8 100644 --- a/web-next/app/[locale]/unstuck-character/page.tsx +++ b/web-next/app/[locale]/unstuck-character/page.tsx @@ -1,4 +1,5 @@ import { getTranslations, setRequestLocale } from 'next-intl/server' +import { NoteLegend } from '@/components/NoteLegend' import { redirect } from '@/i18n/navigation' import { getSession } from '@/lib/session' import { getGameCharacters } from '@/lib/characters' @@ -25,7 +26,7 @@ export default async function UnstuckPage({ params }: { params: Promise<{ locale

{t('unstuckInfo2')}


- NOTA +

{t('unstuckNote1')}

{t('unstuckNote2')}

diff --git a/web-next/components/ClientDownload.tsx b/web-next/components/ClientDownload.tsx index 055d029..b313427 100644 --- a/web-next/components/ClientDownload.tsx +++ b/web-next/components/ClientDownload.tsx @@ -1,6 +1,7 @@ 'use client' import { useRef, useState } from 'react' +import { useTranslations } from 'next-intl' // Lista de trackers común a todos los magnet (idéntica en el original). const TRACKERS = @@ -17,14 +18,15 @@ function magnetFor(lang: string): string { return `magnet:?xt=urn:btih:${BTIH[lang]}${TRACKERS}` } -const LANG_INFO: Record = { - wotlkeses: 'Idioma esES: Español de España.', - wotlkesmx: 'Idioma esMX: Español de Latinoamérica.', - wotlkenus: 'Idioma enUS: Inglés de EEUU.', - wotlkengb: 'Idioma enGB: Inglés británico.', +const LANG_INFO_KEY: Record = { + wotlkeses: 'clientDownload.langEses', + wotlkesmx: 'clientDownload.langEsmx', + wotlkenus: 'clientDownload.langEnus', + wotlkengb: 'clientDownload.langEngb', } export function ClientDownload() { + const t = useTranslations('UI') const [lang, setLang] = useState('') const [os, setOs] = useState('') const [error, setError] = useState(false) @@ -45,45 +47,45 @@ export function ClientDownload() { <>
-

Descarga por Torrent

+

{t('clientDownload.torrentTitle')}

-

Información

-

- No requiere instalación.

-

- El realmlist ya está configurado.

-

- La descarga se gestiona a través de magnet link. Si ya conoces cómo realizar descargas de este tipo, los pasos a seguir son opcionales.

+

{t('clientDownload.infoLabel')}

+

{t('clientDownload.info1')}

+

{t('clientDownload.info2')}

+

{t('clientDownload.info3')}


-

Requisitos para la descarga

-

Se necesitará un programa que gestione descargas por Torrent y un programa que gestione archivos .rar.

+

{t('clientDownload.requirementsLabel')}

+

{t('clientDownload.requirementsText')}

-

Adicionalmente, necesitarás que esta página pueda abrir ventanas emergentes.

+

{t('clientDownload.popupNote')}


-

Paso a paso:

-

Opcional: Si no tienes Winrar, haz clic en WinRAR e instala el programa.

-

1) Haz clic en qBittorrent.

-

2) Descarga la versión adecuada para tu sistema operativo.

-

3) Ejecuta el archivo descargado y realiza la instalacion del programa.

-

4) Ejecuta qBitTorrent.

-

5) Ve a la parte final de esta página y escoge el idioma de tu preferencia.

-

6) Debajo del idioma, escoge el sistema operativo.

-

7) Haz clic en Descargar.

-

8) En la ventana emergente, acepta Abrir qBitTorrent.

-

9) Espera a que qBitTorrent cargue el archivo correspondiente en la ventana de Enlace magnet.

-

10) Haz clic en Aceptar.

-

11) En la ventana de qBitTorrent espera a que la descarga se haya completado.

-

12) Ingresa en la carpeta de descargas de qBitTorrent (Por defecto Descargas).

-

13) Haz clic derecho en el archivo .rar y usa la opción Extraer aquí.

-

14) Ingresa en la carpeta extraída y allí encontrarás el ejecutable para comenzar a jugar.

-

15) Conecta usando tu cuenta de la web, en el campo email no pongas tu email sino tu nombre de cuenta.

+

{t('clientDownload.stepByStep')}

+

{t.rich('clientDownload.stepOptional', { winrar: (c) => {c} })}

+

{t.rich('clientDownload.step1', { qbit: (c) => {c} })}

+

{t('clientDownload.step2')}

+

{t('clientDownload.step3')}

+

{t('clientDownload.step4')}

+

{t('clientDownload.step5')}

+

{t('clientDownload.step6')}

+

{t('clientDownload.step7')}

+

{t('clientDownload.step8')}

+

{t('clientDownload.step9')}

+

{t('clientDownload.step10')}

+

{t('clientDownload.step11')}

+

{t('clientDownload.step12')}

+

{t('clientDownload.step13')}

+

{t('clientDownload.step14')}

+

{t('clientDownload.step15')}




-

Idioma

+

{t('clientDownload.languageLabel')}


{lang && (

-

{LANG_INFO[lang] ?? ' '}

+

{lang ? t(LANG_INFO_KEY[lang]) :' '}


-

Sistema operativo

+

{t('clientDownload.osLabel')}



- +
)}

- {error ? 'Debes escoger un cliente y un sistema operativo.' : ''} + {error ? t('clientDownload.errorChoose') : ''}

@@ -134,24 +136,24 @@ export function ClientDownload() { {os === 'macosc' && (
-

Guía para ejecutar el cliente en mac OS Catalina

+

{t('clientDownload.macGuideTitle')}

-

macOS Catalina ya no soporta aplicaciones que trabajan en 32bits, y el cliente se ejecuta en 32bits.

-

Siguiendo los pasos a continuación podrás disfrutar UltimoWoW sin problemas en macOS Catalina.

+

{t('clientDownload.mac1')}

+

{t('clientDownload.mac2')}


- Instrucciones -

1 - Descarga e instala CrossOver.

-

2 - Una vez que tengas descargado el cliente, ejecuta CrossOver y haz clic en "Instalar una aplicación para Windows".

-

3 - En el campo "Seleccionar una aplicación para instalar", busca la descarga, selecciónalo y haz clic en continuar. (No hagas clic en instalar aún).

-

4 - Ve a la pestaña donde dice "Seleccionar instalador", haz clic en "Elegir archivo de instalador", y ahora busca WoW.exe y selecciónalo.

-

5 - En la pestaña Botella, puedes seleccionar Windows 7 64bits.

-

6 - Ve a la pestaña "Instalar y finalizar", haz clic en Instalar, se instalarán todas las fuentes, archivos y Visual Redistributables necesarios que WoW usa en un sistema operativo Windows estándar.

-

7 - Te pedirá instalar y aceptar los FONTS, Microsoft Visual C ++, haz clic en Sí para cada solicitud que aparezca.

-

8 - El cliente se iniciará automáticamente.

-

9 - Una vez que termines y salgas del cliente, haz clic en "Listo" en la aplicación CrossOver.

-

10 - La próxima vez que desees volver, abre la aplicación CrossOver, mira el panel izquierdo y selecciona en Botella el WoW que se creó anteriormente, y haz clic en RUN COMMAND, selecciona WoW.exe y haz clic en ¨Guardar comando como iniciador¨, luego haz clic en Abrir.

-

11 - Finalmente, verás el ícono de WoW debajo de la pestaña Botella de WoW, ahora puedes arrastrar el lanzador de WoW al Dock, de esta manera, la próxima vez que quieras entrar, simplemente ejecuta WoW desde el Dock.

+ {t('clientDownload.macInstructions')} +

{t.rich('clientDownload.macStep1', { crossover: (c) => {c} })}

+

{t('clientDownload.macStep2')}

+

{t('clientDownload.macStep3')}

+

{t('clientDownload.macStep4')}

+

{t('clientDownload.macStep5')}

+

{t('clientDownload.macStep6')}

+

{t('clientDownload.macStep7')}

+

{t('clientDownload.macStep8')}

+

{t('clientDownload.macStep9')}

+

{t('clientDownload.macStep10')}

+

{t('clientDownload.macStep11')}

)} diff --git a/web-next/components/CookieConsent.tsx b/web-next/components/CookieConsent.tsx index 016e1b1..5592071 100644 --- a/web-next/components/CookieConsent.tsx +++ b/web-next/components/CookieConsent.tsx @@ -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 ( -
+
-

Utilizamos cookies

-

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.

- Política de Cookies +

{t('cookie.title')}

+

{t('cookie.description')}

+ {t('cookie.policyLink')} {details && (
-

Esenciales para el funcionamiento del sitio. No se pueden desactivar.

+

{t('cookie.descNecessary')}

-

Nos ayudan a entender cómo usas el sitio para mejorarlo.

+

{t('cookie.descAnalytics')}

-

Se utilizan para mostrarte anuncios relevantes.

+

{t('cookie.descMarketing')}

- +
)}
- - - + + +
) @@ -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 (
) @@ -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 = { + necessary: t('cookie.catNecessary'), + analytics: t('cookie.catAnalytics'), + marketing: t('cookie.catMarketing'), + } return (

{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')}

    {zarazData ? ( @@ -241,7 +250,7 @@ export function ConsentStatus() {
  • {purpose} - {granted ? 'Aceptada' : 'Rechazada'} + {granted ? t('cookie.accepted') : t('cookie.rejected')}
  • )) @@ -251,9 +260,9 @@ export function ConsentStatus() { const on = cat.always || Boolean(values?.[cat.key]) return (
  • - {cat.label} + {catLabel[cat.key] ?? cat.label} - {cat.always ? 'Siempre activas' : values ? (on ? 'Aceptada' : 'Rechazada') : '—'} + {cat.always ? t('cookie.alwaysOn') : values ? (on ? t('cookie.accepted') : t('cookie.rejected')) : '—'}
  • ) diff --git a/web-next/components/DPointsTabs.tsx b/web-next/components/DPointsTabs.tsx index c19fecf..ba5e408 100644 --- a/web-next/components/DPointsTabs.tsx +++ b/web-next/components/DPointsTabs.tsx @@ -1,6 +1,7 @@ 'use client' import { useState } from 'react' +import { useTranslations } from 'next-intl' import { Link } from '@/i18n/navigation' const LOGOS = '/nw-themes/nw-ryu/nw-images/nw-logos' @@ -8,24 +9,25 @@ const RANKS = '/nw-themes/nw-ryu/nw-images/nw-ranks' type TabId = 'Info' | 'Stripe' | 'SumUp' -const RANK_ROWS = [ - ['1_Newbie', 'Nivel 1', 'Desde 0 PD'], - ['2_Rookie', 'Nivel 2', 'Hasta 100 PD'], - ['3_Apprentice', 'Nivel 3', 'Hasta 200 PD'], - ['4_Explorer', 'Nivel 4', 'Hasta 300 PD'], - ['5_Contributor', 'Nivel 5', 'Hasta 400 PD'], - ['6_Enthusiast', 'Nivel 6', 'Hasta 500 PD'], - ['7_Collaborator', 'Nivel 7', 'Hasta 600 PD'], - ['8_Regular', 'Nivel 8', 'Hasta 700 PD'], - ['9_RisingStar', 'Nivel 9', 'Hasta 800 PD'], - ['10_Proficient', 'Nivel 10', 'Hasta 900 PD'], - ['11_Experienced', 'Nivel 11', 'Hasta 1000 PD'], - ['12_Mentor', 'Nivel 12', 'Hasta 5000 PD'], - ['13_Veteran', 'Nivel 13', 'Hasta 10000 PD'], - ['14_GrandMaster', 'Nivel 14', 'Más de 10000 PD'], +const RANK_ROWS: [string, number, string][] = [ + ['1_Newbie', 1, 'range1'], + ['2_Rookie', 2, 'range2'], + ['3_Apprentice', 3, 'range3'], + ['4_Explorer', 4, 'range4'], + ['5_Contributor', 5, 'range5'], + ['6_Enthusiast', 6, 'range6'], + ['7_Collaborator', 7, 'range7'], + ['8_Regular', 8, 'range8'], + ['9_RisingStar', 9, 'range9'], + ['10_Proficient', 10, 'range10'], + ['11_Experienced', 11, 'range11'], + ['12_Mentor', 12, 'range12'], + ['13_Veteran', 13, 'range13'], + ['14_GrandMaster', 14, 'range14'], ] export function DPointsTabs({ realm, currency }: { realm: string; currency: string }) { + const t = useTranslations('Points') const [active, setActive] = useState('Info') const [showRanks, setShowRanks] = useState(false) const sym = currency === 'usd' ? '$' : '€' @@ -38,10 +40,10 @@ export function DPointsTabs({ realm, currency }: { realm: string; currency: stri className={`dnt-button-2 tablink${active === 'Info' ? ' dnt-selected' : ''}`} onClick={() => setActive('Info')} > - Información + {t('tabs.info')} - Regresar a mi cuenta - Regresar + {t('tabs.backToAccount')} + {t('tabs.back')}
ID de transacciónEstadoConceptoFecha creaciónCantidad{t('trans.thTxId')}{t('trans.thStatus')}{t('trans.thConcept')}{t('trans.thCreatedAt')}{t('trans.thAmount')}
- {RANK_ROWS.map(([file, nivel, desde]) => ( + {RANK_ROWS.map(([file, level, rangeKey]) => ( - - - + + + ))} @@ -87,21 +89,21 @@ export function DPointsTabs({ realm, currency }: { realm: string; currency: stri


- ¿Cuáles son los métodos de compra de PD? -

Los métodos de compra disponibles actualmente son:

-

- Stripe Stripe (tarjeta de crédito/débito, para todos los países).

-

- SumUp SumUp (tarjeta de crédito/débito).

+ {t('tabs.purchaseMethods')} +

{t('tabs.purchaseMethodsText')}

+

- Stripe {t('tabs.stripeMethod')}

+

- SumUp {t('tabs.sumupMethod')}




- ¿Cuántos PD se reciben? -

Por cada {sym}1 recibes 100 PD. La cantidad final se indica antes de confirmar el pago.

+ {t('tabs.howManyPd')} +

{t('tabs.howManyPdText', { sym })}




- ¿Tienes dudas o problemas con una compra? -

No realices una compra hasta estar completamente seguro de que has leído esta información y sabes cómo es el proceso que vayas a escoger.

-

Si a pesar de leer este instructivo aún tienes dudas, el equipo de {realm} podrá asesorarte en cualquier momento. Puedes colocar un ticket en el servidor, o contactarnos mediante nuestra plataforma de Discord.

+ {t('tabs.doubts')} +

{t('tabs.doubtsText1')}

+

{t('tabs.doubtsText2', { realm })}

)} @@ -114,20 +116,22 @@ export function DPointsTabs({ realm, currency }: { realm: string; currency: stri } /* --------------------------- Lógica de pago común --------------------------- */ -function checkoutError(error?: string): string { +function checkoutErrorKey(error?: string): string { switch (error) { case 'notConfigured': - return 'Este método de pago aún no está disponible. Por favor, utiliza otro método o inténtalo más tarde.' + return 'notConfigured' case 'invalidAmount': - return 'La cantidad debe ser un número entero entre 1 y 200.' + return 'invalidAmount' case 'notAuthenticated': - return 'Tu sesión ha expirado. Inicia sesión de nuevo.' + return 'notAuthenticated' default: - return 'No se pudo iniciar el pago. Inténtalo de nuevo.' + return 'generic' } } function usePayment(provider: 'stripe' | 'sumup') { + const t = useTranslations('Points') + const checkoutError = (error?: string) => t(`tabs.checkoutErrors.${checkoutErrorKey(error)}`) const [amount, setAmount] = useState('') const [accepted, setAccepted] = useState(false) const [busy, setBusy] = useState(false) @@ -136,7 +140,7 @@ function usePayment(provider: 'stripe' | 'sumup') { async function pay(e: React.FormEvent, sym: string) { e.preventDefault() if (!accepted) { - alert('Debes aceptar los Términos y Condiciones y la Política de Reembolso') + alert(t('tabs.mustAccept')) return } const n = Number(amount) @@ -144,7 +148,7 @@ function usePayment(provider: 'stripe' | 'sumup') { setErr(checkoutError('invalidAmount')) return } - if (!window.confirm(`Vas a adquirir ${n * 100} PD por ${sym}${n}.\n¿Deseas continuar al pago?`)) return + if (!window.confirm(t('tabs.confirmPurchase', { points: n * 100, sym, amount: n }))) return setBusy(true) setErr(null) try { @@ -180,26 +184,28 @@ function AmountForm({ sym: string buttonLabel: string }) { + const t = useTranslations('Points') const st = usePayment(provider) const points = Number(st.amount) > 0 ? Number(st.amount) * 100 : 0 + const currency = sym === '$' ? 'USD' : 'EUR' return ( <> -

{sym}1 = 100 PD

-

Valor mínimo: {sym}1 · Valor máximo por transacción: {sym}200

+

{t('tabs.rate', { sym })}

+

{t('tabs.minMax', { sym })}


-

¡Importante!

-

Introduce sólo valores enteros (sin decimales).

-

Ejemplo: para 200 PD escribe 2.

+

{t('tabs.important')}

+

{t('tabs.integersOnly')}

+

{t('tabs.example')}


-

Cantidad en {sym === '$' ? 'USD' : 'EUR'} a adquirir

+

{t('tabs.amountLabel', { currency })}

st.pay(e, sym)}> st.setAmount(e.target.value)} required />{' '} - {sym === '$' ? 'USD' : 'EUR'} - {points > 0 &&

Recibirás {points} PD

} + {currency} + {points > 0 &&

{t('tabs.willReceive', { points })}

}

st.setAccepted(e.target.checked)} required /> - +

{st.err &&

{st.err}

} @@ -231,28 +240,33 @@ function AmountForm({ /* ---------------------------------- Stripe ---------------------------------- */ function StripeTab({ realm, sym }: { realm: string; sym: string }) { + const t = useTranslations('Points') return (
- ¿Qué es Stripe?Stripe -

Stripe es una plataforma de pagos en línea segura que procesa tarjetas de crédito y débito de todo el mundo. Tus datos de pago se gestionan directamente en Stripe; {realm} nunca los almacena.
Más información sobre Stripe aquí.

+ {t('tabs.whatIsStripe')}Stripe +

{t.rich('tabs.stripeAboutText', { + realm, + br: () =>
, + link: (c) => {c}, + })}




- ¿Cómo adquirir PD a través de Stripe? -

Al ser un sistema auto-gestionado, las adquisiciones son automáticas y en cuestión de minutos tras completar el pago recibirás los PD en tu cuenta.

+ {t('tabs.howStripe')} +

{t('tabs.stripeHowText')}




-

- Introduce en el campo de más abajo la cantidad que deseas adquirir.

-

- Al presionar ADQUIRIR PD, serás redirigido a la pasarela segura de Stripe para completar el pago con tu tarjeta.

-

- Una vez que Stripe valide tu pago, tendrás los PD en tu cuenta de forma automática.

+

{t('tabs.step1')}

+

{t.rich('tabs.stripeStep2', { s: (c) => {c} })}

+

{t('tabs.stripeStep3')}


-

Recuerda que la cantidad sólo acepta números enteros y el mínimo posible es {sym}1.

-

Ejemplos de valor incorrecto: {sym}5,90 | {sym}22,30 | {sym}53,10

-

Ejemplos de valor correcto: {sym}6 | {sym}22 | {sym}53

+

{t('tabs.reminderMin', { sym })}

+

{t.rich('tabs.wrongExamples', { sym, s: (c) => {c} })}

+

{t.rich('tabs.rightExamples', { sym, s: (c) => {c} })}




- +
) @@ -260,28 +274,33 @@ function StripeTab({ realm, sym }: { realm: string; sym: string }) { /* ---------------------------------- SumUp ----------------------------------- */ function SumUpTab({ realm, sym }: { realm: string; sym: string }) { + const t = useTranslations('Points') return (
- ¿Qué es SumUp?SumUp -

SumUp es una plataforma de pagos europea que permite pagar de forma rápida y segura con tarjeta de crédito o débito. Tus datos de pago se gestionan directamente en SumUp; {realm} nunca los almacena.
Más información sobre SumUp aquí.

+ {t('tabs.whatIsSumup')}SumUp +

{t.rich('tabs.sumupAboutText', { + realm, + br: () =>
, + link: (c) => {c}, + })}




- ¿Cómo adquirir PD a través de SumUp? -

Al ser un sistema auto-gestionado, las adquisiciones son automáticas y tras completar el pago recibirás los PD en tu cuenta.

+ {t('tabs.howSumup')} +

{t('tabs.sumupHowText')}




-

- Introduce en el campo de más abajo la cantidad que deseas adquirir.

-

- Al presionar ADQUIRIR PD, serás redirigido a la pasarela segura de SumUp para completar el pago con tu tarjeta.

-

- Una vez que SumUp valide tu pago, tendrás los PD en tu cuenta de forma automática.

+

{t('tabs.step1')}

+

{t.rich('tabs.sumupStep2', { s: (c) => {c} })}

+

{t('tabs.sumupStep3')}


-

Recuerda que la cantidad sólo acepta números enteros y el mínimo posible es {sym}1.

-

Ejemplos de valor incorrecto: {sym}5,90 | {sym}22,30 | {sym}53,10

-

Ejemplos de valor correcto: {sym}6 | {sym}22 | {sym}53

+

{t('tabs.reminderMin', { sym })}

+

{t.rich('tabs.wrongExamples', { sym, s: (c) => {c} })}

+

{t.rich('tabs.rightExamples', { sym, s: (c) => {c} })}




- +
) diff --git a/web-next/components/Footer.tsx b/web-next/components/Footer.tsx index 6f56d3d..149b9fa 100644 --- a/web-next/components/Footer.tsx +++ b/web-next/components/Footer.tsx @@ -1,3 +1,4 @@ +import { getTranslations } from 'next-intl/server' import { getRealmName } from '@/lib/realm' /** @@ -5,40 +6,41 @@ import { getRealmName } from '@/lib/realm' * (enlaces legales + copyright + crédito de diseño) con las clases del tema real. */ export async function Footer() { + const t = await getTranslations('UI') const year = new Date().getFullYear() const realmName = await getRealmName() return ( ) diff --git a/web-next/components/NoteLegend.tsx b/web-next/components/NoteLegend.tsx new file mode 100644 index 0000000..4ec5d80 --- /dev/null +++ b/web-next/components/NoteLegend.tsx @@ -0,0 +1,7 @@ +import { getTranslations } from 'next-intl/server' + +/** Leyenda «NOTA» / «NOTE» traducida para los
de aviso. */ +export async function NoteLegend() { + const t = await getTranslations('Common') + return {t('note')} +} diff --git a/web-next/components/PlayersBoard.tsx b/web-next/components/PlayersBoard.tsx index e41e69c..145d920 100644 --- a/web-next/components/PlayersBoard.tsx +++ b/web-next/components/PlayersBoard.tsx @@ -1,3 +1,4 @@ +import { getTranslations } from 'next-intl/server' import { getPlayersData, CLASS_INFO, @@ -11,19 +12,20 @@ import { /* eslint-disable @next/next/no-img-element */ export async function PlayersBoard() { + const t = await getTranslations('UI') const data = await getPlayersData() return ( <>
-

La información de esta página se actualiza 1 vez al día automáticamente

+

{t('players.updateNotice')}

{/* Personajes creados por clase */}
-

Personajes creados por clase

+

{t('players.charsByClass')}

{data.classStats.map((s) => ( @@ -31,10 +33,10 @@ export async function PlayersBoard() {
{nivel}{nivel}{desde}{t('tabs.level',{t('tabs.level', { n: level })}{t(`tabs.${rangeKey}`)}
- + - - + +
{CLASS_INFO[s.id].label}
Total: {s.total}
{t('players.total')} {s.total}

Alianza Alianzas: {s.alliance}
Horda Hordas: {s.horde}
{t('players.allianceAlt')} {t('players.alliances')} {s.alliance}
{t('players.hordeAlt')} {t('players.hordes')} {s.horde}
@@ -42,9 +44,9 @@ export async function PlayersBoard() { - - - + + +
Personajes totales: {data.totals.total}Personajes alianzas: {data.totals.alliance}Personajes hordas: {data.totals.horde}{t('players.totalChars')} {data.totals.total}{t('players.allianceChars')} {data.totals.alliance}{t('players.hordeChars')} {data.totals.horde}
@@ -56,23 +58,23 @@ export async function PlayersBoard() { {/* Primeros del Reino - Nivel 80 */}
-

Primeros del Reino - Nivel 80

+

{t('players.firstsTitle')}

{data.firsts.length === 0 ? ( -

Aún no hay personajes de nivel 80 registrados.

+

{t('players.noLevel80')}

) : ( - - - + + + {data.firsts.map((f, i) => ( @@ -88,16 +90,16 @@ export async function PlayersBoard() { {/* Top de logros */}
-

Top de logros

+

{t('players.topAchTitle')}

-

Los 10 jugadores con más logros

+

{t('players.topAchSub')}

LogroPersonajeFecha{t('players.thAchievement')}{t('players.thCharacter')}{t('players.thDate')}
{' '} - ¡Primero del reino! {f.label} + {t('players.firstOfRealm')} {f.label} {f.name} {f.date}
- - - - + + + + {data.topAch.map((r, i) => ( @@ -116,17 +118,17 @@ export async function PlayersBoard() { {/* Top de muertes con honor */}
-

Top de muertes con honor

+

{t('players.topHonorTitle')}

-

Los 10 jugadores con más muertes con honor

+

{t('players.topHonorSub')}

NombreRazaClasePuntos de logros{t('players.thName')}{t('players.thRace')}{t('players.thClass')}{t('players.thAchPoints')}
- - - - - + + + + + {data.topHonor.map((r, i) => ( diff --git a/web-next/components/PromoCodeForm.tsx b/web-next/components/PromoCodeForm.tsx index 9823abe..7923ca8 100644 --- a/web-next/components/PromoCodeForm.tsx +++ b/web-next/components/PromoCodeForm.tsx @@ -1,28 +1,26 @@ 'use client' import { useState } from 'react' +import { useTranslations } from 'next-intl' import { useRouter } from '@/i18n/navigation' -function promoError(error?: string): string { +function promoErrorKey(error?: string): string { switch (error) { case 'missingCode': - return 'Escribe un código de promoción.' case 'notFound': - return 'El código no existe o ya no está disponible.' case 'expired': - return 'Este código ha caducado.' case 'exhausted': - return 'Este código ya ha alcanzado su límite de usos.' case 'alreadyUsed': - return 'Ya has canjeado este código.' case 'notAuthenticated': - return 'Tu sesión ha expirado. Inicia sesión de nuevo.' + return error default: - return 'No se pudo canjear el código. Inténtalo de nuevo.' + return 'generic' } } export function PromoCodeForm() { + const t = useTranslations('Points') + const promoError = (error?: string) => t(`promo.errors.${promoErrorKey(error)}`) const router = useRouter() const [code, setCode] = useState('') const [busy, setBusy] = useState(false) @@ -43,10 +41,10 @@ export function PromoCodeForm() { const data: { success?: boolean; error?: string; pd?: number; pv?: number } = await res.json() if (data.success) { const parts: string[] = [] - if (data.pd) parts.push(`${data.pd} PD`) - if (data.pv) parts.push(`${data.pv} PV`) - const reward = parts.length ? parts.join(' y ') : 'la recompensa' - setMessage({ ok: true, text: `¡Código canjeado! Has recibido ${reward}.` }) + if (data.pd) parts.push(t('promo.rewardPd', { pd: data.pd })) + if (data.pv) parts.push(t('promo.rewardPv', { pv: data.pv })) + const reward = parts.length ? parts.join(` ${t('promo.and')} `) : t('promo.rewardDefault') + setMessage({ ok: true, text: t('promo.success', { reward }) }) setCode('') router.refresh() } else { @@ -66,14 +64,14 @@ export function PromoCodeForm() { setCode(e.target.value)} required />

diff --git a/web-next/components/QuestTrackerForm.tsx b/web-next/components/QuestTrackerForm.tsx index dd441de..abcae84 100644 --- a/web-next/components/QuestTrackerForm.tsx +++ b/web-next/components/QuestTrackerForm.tsx @@ -1,6 +1,7 @@ 'use client' import { useMemo, useState } from 'react' +import { useTranslations } from 'next-intl' import { CharacterSelect } from '@/components/CharacterSelect' import { Turnstile } from '@/components/Turnstile' @@ -23,35 +24,36 @@ interface QuestStatus { state: 'rewarded' | 'inProgress' | 'none' } -function trackerError(error?: string, minutes?: number): string { +function trackerError(t: ReturnType, error?: string, minutes?: number): string { switch (error) { case 'missingFields': - return 'Selecciona un personaje y una opción.' + return t('quest.errors.missingFields') case 'characterNotOwned': - return 'El personaje seleccionado no es válido.' + return t('quest.errors.characterNotOwned') case 'characterOnline': - return 'El personaje debe estar desconectado.' + return t('quest.errors.characterOnline') case 'wrongClass': - return 'Esa opción no corresponde a la clase del personaje.' + return t('quest.errors.wrongClass') case 'levelTooLow': - return 'El personaje no cumple el nivel mínimo de esa opción.' + return t('quest.errors.levelTooLow') case 'invalidQuestId': - return 'Introduce un ID de misión válido.' + return t('quest.errors.invalidQuestId') case 'invalidOption': case 'noData': - return 'Esa opción no está disponible todavía.' + return t('quest.errors.noData') case 'cooldown': - return `Debes esperar ${minutes ?? 0} min para repetir esta búsqueda en este personaje.` + return t('quest.errors.cooldown', { minutes: minutes ?? 0 }) case 'captcha': - return 'Verifica que no eres un robot.' + return t('quest.errors.captcha') case 'notAuthenticated': - return 'Tu sesión ha expirado. Inicia sesión de nuevo.' + return t('quest.errors.notAuthenticated') default: - return 'No se pudo completar la búsqueda. Inténtalo de nuevo.' + return t('quest.errors.default') } } export function QuestTrackerForm({ characters, options }: { characters: QuestCharacter[]; options: QuestOptionClient[] }) { + const t = useTranslations('CharService') const [character, setCharacter] = useState('') const [option, setOption] = useState('') const [questId, setQuestId] = useState('') @@ -70,9 +72,9 @@ export function QuestTrackerForm({ characters, options }: { characters: QuestCha const list = options .filter((o) => o.hasData && (o.classCss === null || o.classCss === selected.classCss) && selected.level >= o.minLevel) .map((o) => ({ key: o.key, label: o.label })) - if (selected.level >= 10) list.push({ key: 'specific', label: 'Por misión específica' }) + if (selected.level >= 10) list.push({ key: 'specific', label: t('quest.specificLabel') }) return list - }, [selected, options]) + }, [selected, options, t]) function onCharacter(v: string) { setCharacter(v) @@ -100,10 +102,10 @@ export function QuestTrackerForm({ characters, options }: { characters: QuestCha if (data.success && data.statuses) { setResult({ label: data.label ?? '', statuses: data.statuses }) } else { - setMessage({ ok: false, text: trackerError(data.error, data.minutes) }) + setMessage({ ok: false, text: trackerError(t, data.error, data.minutes) }) } } catch { - setMessage({ ok: false, text: trackerError() }) + setMessage({ ok: false, text: trackerError(t) }) } finally { setBusy(false) setCaptcha('') @@ -115,7 +117,7 @@ export function QuestTrackerForm({ characters, options }: { characters: QuestCha return (

- No hay personajes disponibles para esta herramienta + {t('quest.noCharacters')}
) @@ -123,18 +125,18 @@ export function QuestTrackerForm({ characters, options }: { characters: QuestCha const stateText = (s: QuestStatus['state']) => s === 'rewarded' - ? { text: 'Completada', cls: 'green-info2' } + ? { text: t('quest.stateCompleted'), cls: 'green-info2' } : s === 'inProgress' - ? { text: 'En curso', cls: 'yellow-info' } - : { text: 'Sin empezar', cls: 'third-brown' } + ? { text: t('quest.stateInProgress'), cls: 'yellow-info' } + : { text: t('quest.stateNotStarted'), cls: 'third-brown' } return (
- +
setQuestId(e.target.value)} required @@ -155,7 +157,7 @@ export function QuestTrackerForm({ characters, options }: { characters: QuestCha )}
@@ -172,7 +174,7 @@ export function QuestTrackerForm({ characters, options }: { characters: QuestCha
diff --git a/web-next/components/RealmInfo.tsx b/web-next/components/RealmInfo.tsx index 1d004ec..6e2cee3 100644 --- a/web-next/components/RealmInfo.tsx +++ b/web-next/components/RealmInfo.tsx @@ -1,27 +1,30 @@ +import { getTranslations } from 'next-intl/server' + /** Información del reino (Rates + Horarios) — contenido de /-realm. */ -export function RealmInfo() { +export async function RealmInfo() { + const t = await getTranslations('UI') return (
-

Rates

-

Experiencia: x8 modificable con .xp (Con Recluta a un Amigo x16)

-

Drop de objetos verdes y azules: x4

-

Drop de oro en NPCs: x2

-

Drop de oro en misiones: x1

-

Habilidades: x3

-

Profesiones: x3

-

Reputaciones: x3 (Bonus con Recluta a un amigo)

-

Honor: x3

+

{t('realmInfo.ratesTitle')}

+

{t('realmInfo.experience')}: {t('realmInfo.experienceValue')}

+

{t('realmInfo.greenBlueDrop')}: {t('realmInfo.greenBlueDropValue')}

+

{t('realmInfo.goldNpc')}: {t('realmInfo.goldNpcValue')}

+

{t('realmInfo.goldQuest')}: {t('realmInfo.goldQuestValue')}

+

{t('realmInfo.skills')}: {t('realmInfo.skillsValue')}

+

{t('realmInfo.professions')}: {t('realmInfo.professionsValue')}

+

{t('realmInfo.reputations')}: {t('realmInfo.reputationsValue')}

+

{t('realmInfo.honor')}: {t('realmInfo.honorValue')}

-

Horarios

-

Los siguientes horarios son basados en la hora del reino.

+

{t('realmInfo.scheduleTitle')}

+

{t('realmInfo.scheduleNote')}


-

Misiones diarias: 7 am

-

Reinicio de mazmorras diarias: 9 am

-

Reinicio de bandas: 9 am (Miércoles)

-

Campos de Batalla: 10 am

-

Reparto de Puntos de Arena: 11 am (Viernes)

+

{t('realmInfo.dailyQuests')}: {t('realmInfo.dailyQuestsValue')}

+

{t('realmInfo.dailyDungeons')}: {t('realmInfo.dailyDungeonsValue')}

+

{t('realmInfo.raidReset')}: {t('realmInfo.raidResetValue')}

+

{t('realmInfo.battlegrounds')}: {t('realmInfo.battlegroundsValue')}

+

{t('realmInfo.arenaPoints')}: {t('realmInfo.arenaPointsValue')}


diff --git a/web-next/components/RecruitPanel.tsx b/web-next/components/RecruitPanel.tsx index 31f557a..e96bd14 100644 --- a/web-next/components/RecruitPanel.tsx +++ b/web-next/components/RecruitPanel.tsx @@ -1,23 +1,24 @@ 'use client' import { useState } from 'react' +import { useTranslations } from 'next-intl' import type { RecruitRewardView } from '@/lib/recruit-claim' import type { CharOption } from '@/components/CharacterSelect' const ICON_BASE = 'https://wotlk.ultimowow.com/static/images/wow/icons/tiny' -function claimError(message?: string): string { +function claimErrorKey(message?: string): string { switch (message) { case 'requirementsNotMet': - return 'Aún no cumples los requisitos para esta recompensa.' + return 'recruit.errRequirements' case 'alreadyClaimed': - return 'Esta recompensa ya fue reclamada.' + return 'recruit.errAlreadyClaimed' case 'invalidCharacter': - return 'Personaje no válido.' + return 'recruit.errInvalidCharacter' case 'notFound': - return 'Recompensa no encontrada.' + return 'recruit.errNotFound' default: - return 'No se pudo reclamar la recompensa. Inténtalo de nuevo.' + return 'recruit.errGeneric' } } @@ -38,6 +39,7 @@ export function RecruitPanel({ isRecruited: boolean recruitedCount: number }) { + const t = useTranslations('UI') const [character, setCharacter] = useState(characters[0]?.name ?? '') const selectedCss = characters.find((c) => c.name === character)?.classCss const [busyId, setBusyId] = useState(null) @@ -62,10 +64,10 @@ export function RecruitPanel({ window.location.reload() return } - setMsg({ ok: false, text: claimError(d.message) }) + setMsg({ ok: false, text: t(claimErrorKey(d.message)) }) setBusyId(null) } catch { - setMsg({ ok: false, text: claimError() }) + setMsg({ ok: false, text: t(claimErrorKey()) }) setBusyId(null) } } @@ -90,15 +92,15 @@ export function RecruitPanel({ return ( <> -

Cuenta reclutada: {isRecruited ? 'Sí' : 'No'}

-

Amigos reclutados: {recruitedCount}

-

Amigos reclutados al nivel 80: {level80Count}

-

Recompensas reclamadas: {claimedCount}/{rewards.length}

+

{t('recruit.accountRecruited')} {isRecruited ? t('recruit.yes') : t('recruit.no')}

+

{t('recruit.friendsRecruited')} {recruitedCount}

+

{t('recruit.friendsAtLevel80')} {level80Count}

+

{t('recruit.rewardsClaimed')} {claimedCount}/{rewards.length}


{characters.length > 0 && (

- Recibir recompensas en:{' '} + {t('recruit.receiveRewardsOn')}{' '}

NombreRazaClaseTotal de muertesTotal de muertes hoy{t('players.thName')}{t('players.thRace')}{t('players.thClass')}{t('players.thTotalKills')}{t('players.thTodayKills')}
- Misión #{s.quest} + {t('quest.questNumber', { quest: s.quest })} {st.text}
- - - + + + {rewards.map((r) => { const eligible = level80Count >= r.required_friends return ( - + @@ -140,13 +142,13 @@ export function RecruitPanel({

-

RECOMPENSAS DISPONIBLES

+

{t('recruit.availableRewards')}


{available.length === 0 ? ( - Recluta amigos para poder reclamar las recompensas + {t('recruit.recruitToClaim')} ) : ( - Tienes {available.length} recompensa{available.length === 1 ? '' : 's'} lista{available.length === 1 ? '' : 's'} para reclamar + {t('recruit.readyToClaim', { count: available.length })} )} diff --git a/web-next/components/RenameGuildForm.tsx b/web-next/components/RenameGuildForm.tsx index 8d30d3b..aed6862 100644 --- a/web-next/components/RenameGuildForm.tsx +++ b/web-next/components/RenameGuildForm.tsx @@ -1,33 +1,29 @@ 'use client' import { useState } from 'react' +import { useTranslations } from 'next-intl' import { useRouter } from '@/i18n/navigation' import type { GmGuild } from '@/lib/guild' -function renameError(error?: string): string { +function renameErrorKey(error?: string): string { switch (error) { case 'missingFields': - return 'Completa todos los campos.' case 'invalidName': - return 'El nombre debe tener de 1 a 24 caracteres, solo letras (A-Z, a-z) y espacios.' case 'invalidToken': - return 'El token de seguridad no es válido.' case 'notGuildMaster': - return 'No eres Maestro de esa hermandad.' case 'nameTaken': - return 'Ya existe una hermandad con ese nombre.' case 'insufficientPoints': - return 'No tienes suficientes PD (se requieren 1000).' case 'soapError': - return 'No se pudo aplicar el cambio (servidor de juego no disponible). Inténtalo más tarde.' case 'notAuthenticated': - return 'Tu sesión ha expirado. Inicia sesión de nuevo.' + return error default: - return 'No se pudo renombrar la hermandad. Inténtalo de nuevo.' + return 'generic' } } export function RenameGuildForm({ guilds }: { guilds: GmGuild[] }) { + const t = useTranslations('Points') + const renameError = (error?: string) => t(`renameGuild.errors.${renameErrorKey(error)}`) const router = useRouter() const [guildId, setGuildId] = useState('') const [newName, setNewName] = useState('') @@ -41,7 +37,7 @@ export function RenameGuildForm({ guilds }: { guilds: GmGuild[] }) { return (

- No hay personajes Maestros de hermandad + {t('renameGuild.noGuilds')}
) @@ -54,7 +50,7 @@ export function RenameGuildForm({ guilds }: { guilds: GmGuild[] }) { setMessage({ ok: false, text: renameError('missingFields') }) return } - if (!window.confirm('¿Estás seguro de renombrar la hermandad seleccionada?')) return + if (!window.confirm(t('renameGuild.confirm'))) return setBusy(true) setMessage(null) @@ -68,7 +64,7 @@ export function RenameGuildForm({ guilds }: { guilds: GmGuild[] }) { const data: { success?: boolean; error?: string; newName?: string } = await res.json() if (data.success) { setDone(true) - setMessage({ ok: true, text: `¡Hermandad renombrada a "${data.newName}"! Puede que los miembros conectados deban reconectar para verlo.` }) + setMessage({ ok: true, text: t('renameGuild.success', { newName: data.newName ?? '' }) }) setNewName('') setToken('') setTimeout(() => router.refresh(), 3000) @@ -90,7 +86,7 @@ export function RenameGuildForm({ guilds }: { guilds: GmGuild[] }) { diff --git a/web-next/components/RestoreCharacterForm.tsx b/web-next/components/RestoreCharacterForm.tsx index 68c1835..e266b61 100644 --- a/web-next/components/RestoreCharacterForm.tsx +++ b/web-next/components/RestoreCharacterForm.tsx @@ -1,33 +1,35 @@ 'use client' import { useState } from 'react' +import { useTranslations } from 'next-intl' import { useRouter } from '@/i18n/navigation' import type { DeletedCharacter } from '@/lib/restore-character' -function restoreError(error?: string): string { +function restoreError(t: ReturnType, error?: string): string { switch (error) { case 'notFound': - return 'Ese personaje borrado no es de tu cuenta.' + return t('restoreChar.errors.notFound') case 'notDeleted': - return 'Ese personaje no está borrado.' + return t('restoreChar.errors.notDeleted') case 'levelTooLow': - return 'Solo se pueden recuperar personajes de nivel superior a 60.' + return t('restoreChar.errors.levelTooLow') case 'tooOld': - return 'El personaje se borró hace más de 30 días y ya no es recuperable.' + return t('restoreChar.errors.tooOld') case 'dkExists': - return 'No puedes recuperar un Caballero de la Muerte: ya tienes uno activo en la cuenta.' + return t('restoreChar.errors.dkExists') case 'nameTaken': - return 'El nombre original ya está en uso por otro personaje.' + return t('restoreChar.errors.nameTaken') case 'cooldown': - return 'Solo puedes intentar recuperar el mismo personaje una vez cada 12 horas.' + return t('restoreChar.errors.cooldown') case 'notAuthenticated': - return 'Tu sesión ha expirado. Inicia sesión de nuevo.' + return t('restoreChar.errors.notAuthenticated') default: - return 'No se pudo recuperar el personaje. Inténtalo de nuevo.' + return t('restoreChar.errors.default') } } export function RestoreCharacterForm({ characters }: { characters: DeletedCharacter[] }) { + const t = useTranslations('CharService') const router = useRouter() const [guid, setGuid] = useState('') const [busy, setBusy] = useState(false) @@ -41,7 +43,7 @@ export function RestoreCharacterForm({ characters }: { characters: DeletedCharac


- No hay personajes + {t('restoreChar.noCharacters')}
) @@ -62,13 +64,13 @@ export function RestoreCharacterForm({ characters }: { characters: DeletedCharac const data: { success?: boolean; error?: string; name?: string } = await res.json() if (data.success) { setDone(true) - setMessage({ ok: true, text: `¡Personaje "${data.name}" recuperado! Lo verás al entrar al reino.` }) + setMessage({ ok: true, text: t('restoreChar.successMsg', { name: data.name ?? '' }) }) setTimeout(() => router.refresh(), 3000) } else { - setMessage({ ok: false, text: restoreError(data.error) }) + setMessage({ ok: false, text: restoreError(t, data.error) }) } } catch { - setMessage({ ok: false, text: restoreError() }) + setMessage({ ok: false, text: restoreError(t) }) } finally { setBusy(false) } @@ -78,16 +80,16 @@ export function RestoreCharacterForm({ characters }: { characters: DeletedCharac


diff --git a/web-next/components/RestoreItemsForm.tsx b/web-next/components/RestoreItemsForm.tsx index b83e7a7..a7786f2 100644 --- a/web-next/components/RestoreItemsForm.tsx +++ b/web-next/components/RestoreItemsForm.tsx @@ -1,6 +1,7 @@ 'use client' import { useState } from 'react' +import { useTranslations } from 'next-intl' import { CharacterSelect, type CharOption } from '@/components/CharacterSelect' import { Turnstile } from '@/components/Turnstile' @@ -13,26 +14,27 @@ interface DeletedItem { count: number } -function itemsError(error?: string, minutes?: number): string { +function itemsError(t: ReturnType, error?: string, minutes?: number): string { switch (error) { case 'characterNotOwned': - return 'El personaje seleccionado no es válido.' + return t('restoreItems.errors.characterNotOwned') case 'cooldown': - return `Solo puedes consultar los ítems de este personaje cada 8 horas (faltan ${minutes ?? 0} min).` + return t('restoreItems.errors.cooldown', { minutes: minutes ?? 0 }) case 'soapError': - return 'No se pudo conectar con el servidor de juego. Inténtalo más tarde.' + return t('restoreItems.errors.soapError') case 'insufficientPoints': - return 'No tienes suficientes PD (se requieren 100 por ítem).' + return t('restoreItems.errors.insufficientPoints') case 'captcha': - return 'Verifica que no eres un robot.' + return t('restoreItems.errors.captcha') case 'notAuthenticated': - return 'Tu sesión ha expirado. Inicia sesión de nuevo.' + return t('restoreItems.errors.notAuthenticated') default: - return 'Algo ha salido mal. Inténtalo de nuevo.' + return t('restoreItems.errors.default') } } export function RestoreItemsForm({ characters, price }: { characters: CharOption[]; price: number }) { + const t = useTranslations('CharService') const [character, setCharacter] = useState('') const [captcha, setCaptcha] = useState('') const [captchaKey, setCaptchaKey] = useState(0) @@ -55,12 +57,12 @@ export function RestoreItemsForm({ characters, price }: { characters: CharOption const data: { success?: boolean; error?: string; minutes?: number; items?: DeletedItem[] } = await res.json() if (data.success) { setItems(data.items ?? []) - if ((data.items ?? []).length === 0) setMessage({ ok: true, text: 'Este personaje no tiene ítems borrados recuperables.' }) + if ((data.items ?? []).length === 0) setMessage({ ok: true, text: t('restoreItems.noDeletedItemsMsg') }) } else { - setMessage({ ok: false, text: itemsError(data.error, data.minutes) }) + setMessage({ ok: false, text: itemsError(t, data.error, data.minutes) }) } } catch { - setMessage({ ok: false, text: itemsError() }) + setMessage({ ok: false, text: itemsError(t) }) } finally { setBusy(false) setCaptcha('') @@ -70,7 +72,7 @@ export function RestoreItemsForm({ characters, price }: { characters: CharOption async function restore(item: DeletedItem) { if (busy) return - if (!window.confirm(`¿Recuperar "${item.name}" por ${price} € (SumUp)?`)) return + if (!window.confirm(t('restoreItems.confirm', { name: item.name, price }))) return setBusy(true) setMessage(null) try { @@ -85,10 +87,10 @@ export function RestoreItemsForm({ characters, price }: { characters: CharOption window.location.assign(data.url) // checkout de SumUp return } - setMessage({ ok: false, text: data.message || itemsError(data.error) }) + setMessage({ ok: false, text: data.message || itemsError(t, data.error) }) setBusy(false) } catch { - setMessage({ ok: false, text: itemsError() }) + setMessage({ ok: false, text: itemsError(t) }) setBusy(false) } } @@ -106,19 +108,19 @@ export function RestoreItemsForm({ characters, price }: { characters: CharOption {items === null ? (
- +
) : (
-

Ítems borrados de {character}

+

{t('restoreItems.deletedItemsOf', { character })}

{items.length === 0 ? ( -

No hay ítems borrados recuperables.

+

{t('restoreItems.noDeletedItems')}

) : (
Amigos reclutadosRecompensaEstado{t('recruit.thFriends')}{t('recruit.thReward')}{t('recruit.thStatus')}
{r.required_friends} {r.required_friends === 1 ? 'amigo' : 'amigos'} al nivel 80{t('recruit.friendsAtLevel80Row', { count: r.required_friends })} {rewardCell(r)} {r.claimed ? ( - Reclamado + {t('recruit.claimed')} ) : eligible ? ( ) : ( - Sin reclamar + {t('recruit.unclaimed')} )}
@@ -130,7 +132,7 @@ export function RestoreItemsForm({ characters, price }: { characters: CharOption @@ -139,7 +141,7 @@ export function RestoreItemsForm({ characters, price }: { characters: CharOption
)}
-

{ e.preventDefault(); reset() }}>Consultar otro personaje

+

{ e.preventDefault(); reset() }}>{t('restoreItems.queryOther')}

)}
diff --git a/web-next/components/ReviveServiceContent.tsx b/web-next/components/ReviveServiceContent.tsx index 14b34bb..da22ba5 100644 --- a/web-next/components/ReviveServiceContent.tsx +++ b/web-next/components/ReviveServiceContent.tsx @@ -1,4 +1,5 @@ import { getTranslations, setRequestLocale } from 'next-intl/server' +import { NoteLegend } from '@/components/NoteLegend' import { redirect } from '@/i18n/navigation' import { getSession } from '@/lib/session' import { getGameCharacters } from '@/lib/characters' @@ -23,7 +24,7 @@ export async function ReviveServiceContent({ locale }: { locale: string }) {

{t('reviveInfo2')}


- NOTA +

{t('reviveNote1')}

{t('reviveNote2')}

diff --git a/web-next/components/SendGiftForm.tsx b/web-next/components/SendGiftForm.tsx index a29ab67..309d766 100644 --- a/web-next/components/SendGiftForm.tsx +++ b/web-next/components/SendGiftForm.tsx @@ -1,6 +1,7 @@ 'use client' import { useMemo, useState } from 'react' +import { useTranslations } from 'next-intl' import type { GiftCategory, GiftItem } from '@/lib/gift' import { CharacterSelect, type CharOption } from '@/components/CharacterSelect' @@ -53,6 +54,7 @@ export function SendGiftForm({ catalog: GiftCategory[] currency?: string }) { + const t = useTranslations('CharService') const [source, setSource] = useState('') const [destination, setDestination] = useState('') const [token, setToken] = useState('') @@ -106,16 +108,16 @@ export function SendGiftForm({ e.preventDefault() if (busy) return if (!source || !destination.trim() || !token.trim()) { - setError('Completa el personaje de origen, el de destino y el token de seguridad.') + setError(t('sendGift.errMissingFields')) return } if (cart.size === 0) { - setError('Añade al menos un objeto al carrito.') + setError(t('sendGift.errEmptyCart')) return } if ( !window.confirm( - `¿Enviar el regalo a "${destination.trim()}" por ${total} ${currency} (SumUp)? Esta acción no es reversible.`, + t('sendGift.confirm', { destination: destination.trim(), total, currency }), ) ) return @@ -137,40 +139,40 @@ export function SendGiftForm({ const data: { success?: boolean; url?: string; message?: string } = await res.json() if (data.success && data.url) window.location.href = data.url else { - setError(data.message || 'No se pudo iniciar el pago. Inténtalo de nuevo.') + setError(data.message || t('sendGift.errPayment')) setBusy(false) } } catch { - setError('Algo ha salido mal. Inténtalo más tarde.') + setError(t('sendGift.errUnexpected')) setBusy(false) } } - if (characters.length === 0) return

No tienes personajes disponibles.

- if (catalog.length === 0) return

No hay objetos disponibles para regalar por ahora.

+ if (characters.length === 0) return

{t('sendGift.noCharacters')}

+ if (catalog.length === 0) return

{t('sendGift.noItems')}

return (
-

Escoge desde qué personaje se envía el regalo:

- +

{t('sendGift.sourcePrompt')}

+
-

Nombre del personaje que recibirá el regalo:

+

{t('sendGift.destPrompt')}

setDestination(e.target.value)} required />
-

Token de seguridad:

- +

{t('sendGift.tokenPrompt')}

+
{/* Catálogo de objetos: cuadrícula centrada de 4 por fila + paginación */} -

Objetos disponibles

+

{t('sendGift.availableItems')}

{pageItems.map((it) => (
@@ -183,7 +185,7 @@ export function SendGiftForm({ {it.price} {currency}
))} @@ -191,7 +193,7 @@ export function SendGiftForm({ {totalPages > 1 && (
{Array.from({ length: totalPages }, (_, i) => i + 1).map((n) => (
)}
{/* Carrito */} -

Carrito

+

{t('sendGift.cart')}

{cart.size === 0 ? ( -

Aún no has añadido objetos.

+

{t('sendGift.cartEmpty')}

) : ( @@ -248,7 +250,7 @@ export function SendGiftForm({

- Total: {total} {currency} (SumUp) + {t.rich('sendGift.total', { total, currency, s: (c) => {c} })}


diff --git a/web-next/components/SiteHeader.tsx b/web-next/components/SiteHeader.tsx index eac6157..84b2190 100644 --- a/web-next/components/SiteHeader.tsx +++ b/web-next/components/SiteHeader.tsx @@ -1,7 +1,7 @@ 'use client' import { useState } from 'react' -import { useLocale } from 'next-intl' +import { useLocale, useTranslations } from 'next-intl' import { Link } from '@/i18n/navigation' const SERVER_NAME = 'NovaWoW' @@ -27,6 +27,7 @@ export function SiteHeader({ playersHref: string }) { const locale = useLocale() + const t = useTranslations('UI') const [open, setOpen] = useState(false) return ( @@ -46,21 +47,21 @@ export function SiteHeader({ {loggedIn ? ( - INICIO + {t('header.home')} ) : ( - CREAR CUENTA + {t('header.register')} )}
- DESCARGAS + {t('header.downloads')}

- CLIENTE + {t('header.client')}

- ADDONS + {t('header.addons')}

@@ -71,14 +72,14 @@ export function SiteHeader({

- CHANGELOG + {t('header.changelog')}

- REINO + {t('header.realm')}

{loggedIn && (

- JUGADORES + {t('header.players')}

)}
@@ -86,23 +87,23 @@ export function SiteHeader({
- COMUNIDAD + {t('header.community')}

- FOROS + {t('header.forums')}

- WOTLK DB + {t('header.wotlkDb')}

- VIDEOS + {t('header.videos')}

{loggedIn && (

- AYUDA + {t('header.help')}

)}
@@ -115,16 +116,16 @@ export function SiteHeader({

- MI CUENTA + {t('header.myAccount')}

- DESCONECTAR + {t('header.logout')}

) : ( - CONECTAR + {t('header.login')} )} diff --git a/web-next/components/Social.tsx b/web-next/components/Social.tsx index c94d345..de32eb6 100644 --- a/web-next/components/Social.tsx +++ b/web-next/components/Social.tsx @@ -1,11 +1,14 @@ +import { getTranslations } from 'next-intl/server' + /** * Barra de redes sociales — réplica del partial Django `partials/social.html` * con las clases del tema real (social-media, social-button + marca). */ -export function Social() { +export async function Social() { + const t = await getTranslations('UI') return (
- - - - - + + + + + - - + + - +
¿Cuánto valdrá el código en PD?
setPoints(e.target.value)} placeholder="Valor del código en PD" required />
¿Cuánto costará el código en oro?
setGold(e.target.value)} placeholder="Valor del código en oro" required />
¿A qué personaje se enviará el oro?
{t('trade.sellPointsLabel')}
setPoints(e.target.value)} placeholder={t('trade.sellPointsPlaceholder')} required />
{t('trade.sellGoldLabel')}
setGold(e.target.value)} placeholder={t('trade.sellGoldPlaceholder')} required />
{t('trade.sellCharLabel')}
- +

setToken(e.target.value)} placeholder="Token de seguridad" required />

setToken(e.target.value)} placeholder={t('trade.tokenPlaceholder')} required />
@@ -153,11 +156,11 @@ function SellForm({ characters, visible }: { characters: CharOption[]; visible: {message && {message.text}} {created && (
- Código creado + {t('trade.createdLegend')}
-

ID del código: {created.code}

-

Valor: {created.points} PD por {created.gold} de oro

-

Envía este ID al comprador. El código caduca en 1 hora.

+

{t('trade.codeIdLabel')} {created.code}

+

{t.rich('trade.createdValue', { points: created.points, gold: created.gold, s: (c) => {c} })}

+

{t('trade.createdHint')}

)} @@ -168,6 +171,8 @@ function SellForm({ characters, visible }: { characters: CharOption[]; visible: /* ---------------------------------- COMPRA --------------------------------- */ function BuyForm({ characters, visible }: { characters: CharOption[]; visible: boolean }) { + const t = useTranslations('Points') + const tradeError = (error?: string) => t(`trade.errors.${tradeErrorKey(error)}`) const [code, setCode] = useState('') const [character, setCharacter] = useState('') const [password, setPassword] = useState('') @@ -192,7 +197,7 @@ function BuyForm({ characters, visible }: { characters: CharOption[]; visible: b const data: { success?: boolean; error?: string; points?: number; gold?: number } = await res.json() if (data.success && data.points != null && data.gold != null) { setCheckInfo({ points: data.points, gold: data.gold }) - setMessage({ ok: true, text: `Este código vale ${data.points} PD y cuesta ${data.gold} de oro.` }) + setMessage({ ok: true, text: t('trade.checkResult', { points: data.points, gold: data.gold }) }) } else { setMessage({ ok: false, text: tradeError(data.error) }) } @@ -206,7 +211,7 @@ function BuyForm({ characters, visible }: { characters: CharOption[]; visible: b async function handleRedeem(e: React.FormEvent) { e.preventDefault() if (busy) return - if (!window.confirm('Vas a canjear este código. Esta acción no es reversible. ¿Deseas continuar?')) return + if (!window.confirm(t('trade.redeemConfirm'))) return setBusy(true) setMessage(null) try { @@ -218,7 +223,7 @@ function BuyForm({ characters, visible }: { characters: CharOption[]; visible: b }) const data: { success?: boolean; error?: string; points?: number; gold?: number } = await res.json() if (data.success) { - setMessage({ ok: true, text: `¡Canje correcto! Recibiste ${data.points} PD y se retiraron ${data.gold} de oro de ${character}.` }) + setMessage({ ok: true, text: t('trade.redeemSuccess', { points: data.points ?? 0, gold: data.gold ?? 0, character }) }) setCode('') setPassword('') setToken('') @@ -238,20 +243,20 @@ function BuyForm({ characters, visible }: { characters: CharOption[]; visible: b
- - + + {checkInfo && ( - + )} - + - - + + - - + +
Ingresa el ID del código de PD
setCode(e.target.value)} placeholder="Código de PD" required />
{t('trade.buyCodeLabel')}
setCode(e.target.value)} placeholder={t('trade.buyCodePlaceholder')} required />

Vale {checkInfo.points} PD · Cuesta {checkInfo.gold} de oro

{t('trade.checkInfo', { points: checkInfo.points, gold: checkInfo.gold })}

¿De qué personaje se cobrará el oro?
{t('trade.buyCharLabel')}
- +

setToken(e.target.value)} placeholder="Token de seguridad" required />

setToken(e.target.value)} placeholder={t('trade.tokenPlaceholder')} required />
@@ -264,6 +269,7 @@ function BuyForm({ characters, visible }: { characters: CharOption[]; visible: b } export function TradePointsForm({ characters }: { characters: CharOption[] }) { + const t = useTranslations('Points') // Como el original: al cargar no se muestra ningún formulario; se revela al // pulsar VENTA o COMPRA. const [active, setActive] = useState<'sell' | 'buy' | null>(null) @@ -272,7 +278,7 @@ export function TradePointsForm({ characters }: { characters: CharOption[] }) { return (

- No tienes personajes en esta cuenta. + {t('trade.noCharacters')}
) } @@ -287,7 +293,7 @@ export function TradePointsForm({ characters }: { characters: CharOption[] }) { className={`trade-option-button${active === 'sell' ? ' dnt-selected' : ''}`} onClick={() => setActive('sell')} > - VENTA + {t('trade.sellTab')}
diff --git a/web-next/components/TransferDPointsForm.tsx b/web-next/components/TransferDPointsForm.tsx index 147bcd8..5cd6f6c 100644 --- a/web-next/components/TransferDPointsForm.tsx +++ b/web-next/components/TransferDPointsForm.tsx @@ -1,30 +1,27 @@ 'use client' import { useState } from 'react' +import { useTranslations } from 'next-intl' import { useRouter } from '@/i18n/navigation' -function transferError(error?: string): string { +function transferErrorKey(error?: string): string { switch (error) { case 'missingFields': - return 'Rellena el personaje de destino, la cantidad y el token de seguridad.' case 'invalidAmount': - return 'La cantidad debe ser un número entero mayor que 0.' case 'invalidToken': - return 'El token de seguridad no es válido.' case 'characterNotFound': - return 'No existe ningún personaje con ese nombre.' case 'sameAccount': - return 'No puedes transferirte PD a tu propia cuenta.' case 'insufficientFunds': - return 'No tienes suficientes PD para realizar esta transferencia.' case 'notAuthenticated': - return 'Tu sesión ha expirado. Inicia sesión de nuevo.' + return error default: - return 'No se pudo completar la transferencia. Inténtalo de nuevo.' + return 'generic' } } export function TransferDPointsForm({ balance }: { balance: number }) { + const t = useTranslations('Points') + const transferError = (error?: string) => t(`transferDp.errors.${transferErrorKey(error)}`) const router = useRouter() const [character, setCharacter] = useState('') const [amount, setAmount] = useState('') @@ -37,7 +34,7 @@ export function TransferDPointsForm({ balance }: { balance: number }) {


- No tienes PD + {t('transferDp.noPd')}
) @@ -59,7 +56,7 @@ export function TransferDPointsForm({ balance }: { balance: number }) { setMessage({ ok: false, text: transferError('insufficientFunds') }) return } - if (!window.confirm(`Vas a transferir ${n} PD al personaje "${character.trim()}".\nEsta acción no es reversible. ¿Deseas continuar?`)) return + if (!window.confirm(t('transferDp.confirm', { n, character: character.trim() }))) return setBusy(true) setMessage(null) @@ -72,7 +69,7 @@ export function TransferDPointsForm({ balance }: { balance: number }) { }) const data: { success?: boolean; error?: string } = await res.json() if (data.success) { - setMessage({ ok: true, text: `Has transferido ${n} PD al personaje "${character.trim()}".` }) + setMessage({ ok: true, text: t('transferDp.success', { n, character: character.trim() }) }) setCharacter('') setAmount('') setToken('') @@ -90,12 +87,12 @@ export function TransferDPointsForm({ balance }: { balance: number }) { return (

-

Tienes {balance} PD disponibles

+

{t('transferDp.available', { balance })}


setCharacter(e.target.value)} required @@ -103,7 +100,7 @@ export function TransferDPointsForm({ balance }: { balance: number }) {
setToken(e.target.value)} @@ -122,7 +119,7 @@ export function TransferDPointsForm({ balance }: { balance: number }) { />

diff --git a/web-next/components/TransferForm.tsx b/web-next/components/TransferForm.tsx index 4a0636d..61b9974 100644 --- a/web-next/components/TransferForm.tsx +++ b/web-next/components/TransferForm.tsx @@ -1,6 +1,7 @@ 'use client' import { useState } from 'react' +import { useTranslations } from 'next-intl' import { CharacterSelect, type CharOption } from '@/components/CharacterSelect' /** Campo con ojo para mostrar/ocultar (contraseña / token). */ @@ -42,6 +43,7 @@ function SecretInput({ } export function TransferForm({ characters, price }: { characters: CharOption[]; price: number }) { + const t = useTranslations('CharService') const [character, setCharacter] = useState('') const [destination, setDestination] = useState('') const [password, setPassword] = useState('') @@ -52,7 +54,7 @@ export function TransferForm({ characters, price }: { characters: CharOption[]; async function handleSubmit(e: React.FormEvent) { e.preventDefault() if (busy || !character || !destination.trim() || !password || !token.trim()) return - if (!window.confirm(`¿Estás seguro de transferir el personaje "${character}" a la cuenta ${destination.trim()} por ${price} € (SumUp)?`)) return + if (!window.confirm(t('transfer.confirm', { character, destination: destination.trim(), price }))) return setBusy(true) setError(null) try { @@ -71,30 +73,30 @@ export function TransferForm({ characters, price }: { characters: CharOption[]; const data: { success?: boolean; url?: string; message?: string } = await res.json() if (data.success && data.url) window.location.href = data.url else { - setError(data.message || 'No se pudo iniciar la transferencia. Inténtalo de nuevo.') + setError(data.message || t('transfer.errorGeneric')) setBusy(false) } } catch { - setError('Algo ha salido mal. Inténtalo más tarde.') + setError(t('transfer.errorUnexpected')) setBusy(false) } } - if (characters.length === 0) return

No tienes personajes disponibles.

+ if (characters.length === 0) return

{t('transfer.noCharacters')}

return (
- +
- setDestination(e.target.value)} required /> + setDestination(e.target.value)} required />
- +
- +

diff --git a/web-next/components/TwoFactorLogin.tsx b/web-next/components/TwoFactorLogin.tsx index c2fb10e..2cb08a2 100644 --- a/web-next/components/TwoFactorLogin.tsx +++ b/web-next/components/TwoFactorLogin.tsx @@ -1,6 +1,7 @@ 'use client' import { useState } from 'react' +import { useTranslations } from 'next-intl' const LOGOS = '/nw-themes/nw-ryu/nw-images/nw-logos' @@ -18,13 +19,14 @@ async function post(action: string, extra: Record): Promise<{ su /** Ojo para mostrar/ocultar un campo de contraseña/token. */ function EyeToggle({ shown, onToggle }: { shown: boolean; onToggle: () => void }) { + const t = useTranslations('UI') return ( ) } @@ -41,6 +43,7 @@ export function TwoFactorLogin({ enabled }: { enabled: boolean }) { /* ------------------------------ Activar + QR ------------------------------- */ function ActivateFlow() { + const t = useTranslations('UI') const [password, setPassword] = useState('') const [showPassword, setShowPassword] = useState(false) const [token, setToken] = useState('') @@ -66,7 +69,7 @@ function ActivateFlow() { setMsg({ success: !!d.success, text: d.message }) if (d.success && d.qrCodeUrl && d.secretKey) setQr({ qrCodeUrl: d.qrCodeUrl, secretKey: d.secretKey }) } catch { - setMsg({ success: false, text: 'Algo ha salido mal. Por favor intente más tarde.' }) + setMsg({ success: false, text: t('twofa.errGeneric') }) } finally { setBusy(false) } @@ -82,7 +85,7 @@ function ActivateFlow() { setVMsg({ success: !!d.success, text: d.message }) if (d.success) setDone(true) } catch { - setVMsg({ success: false, text: 'Algo ha salido mal. Por favor intente más tarde.' }) + setVMsg({ success: false, text: t('twofa.errGeneric') }) } finally { setVBusy(false) } @@ -108,7 +111,7 @@ function ActivateFlow() { maxLength={16} name="password" id="password" - placeholder="Contraseña" + placeholder={t('twofa.passwordPlaceholder')} value={password} onChange={(e) => setPassword(e.target.value)} disabled={!!qr} @@ -123,7 +126,7 @@ function ActivateFlow() { maxLength={6} name="security-token" id="security-token" - placeholder="Token de seguridad" + placeholder={t('twofa.tokenPlaceholder')} value={token} onChange={(e) => setToken(e.target.value)} disabled={!!qr} @@ -135,7 +138,7 @@ function ActivateFlow() { @@ -152,7 +155,7 @@ function ActivateFlow() { {qr && (
-

Paso 1) Descarga la aplicación de autenticación:

+

{t('twofa.step1')}

Google Play @@ -161,16 +164,16 @@ function ActivateFlow() {

-

Paso 2) Escanea este código QR con tu aplicación de autenticación:

+

{t('twofa.step2')}

QR Code

-

Si no puedes escanear el código QR copia y pega esta clave en tu aplicación de autenticación:

+

{t('twofa.copyKeyNote')}



-

Paso 3) Ingresa el código generado por tu aplicación de autenticación:

+

{t('twofa.step3')}

@@ -189,7 +192,7 @@ function ActivateFlow() { maxLength={6} name="authenticator-code" id="authenticator-code" - placeholder="Código de 6 dígitos" + placeholder={t('twofa.codePlaceholder')} required className="centered" inputMode="numeric" @@ -203,7 +206,7 @@ function ActivateFlow() { @@ -225,6 +228,7 @@ function ActivateFlow() { /* ------------------------------- Desactivar -------------------------------- */ function DisableForm() { + const t = useTranslations('UI') const [code, setCode] = useState('') const [busy, setBusy] = useState(false) const [msg, setMsg] = useState(null) @@ -240,7 +244,7 @@ function DisableForm() { setMsg({ success: !!d.success, text: d.message }) if (d.success) setDone(true) } catch { - setMsg({ success: false, text: 'Algo ha salido mal. Por favor intente más tarde.' }) + setMsg({ success: false, text: t('twofa.errGeneric') }) } finally { setBusy(false) } @@ -248,8 +252,8 @@ function DisableForm() { return ( <> -

La verificación en 2 pasos está activada en esta cuenta.

-

Para desactivarla, introduce un código actual de tu aplicación de autenticación.

+

{t('twofa.enabledNotice')}

+

{t('twofa.disableInstruction')}


@@ -260,7 +264,7 @@ function DisableForm() { type="text" maxLength={6} name="authenticator-code" - placeholder="Código de 6 dígitos" + placeholder={t('twofa.codePlaceholder')} required className="centered" inputMode="numeric" @@ -274,7 +278,7 @@ function DisableForm() { diff --git a/web-next/messages/en.json b/web-next/messages/en.json index 91c59f3..906d269 100644 --- a/web-next/messages/en.json +++ b/web-next/messages/en.json @@ -563,7 +563,10 @@ "promoRedemptions": "Redemptions", "noPromo": "No promo codes.", "promoDuplicate": "A code with that text already exists.", - "promoEmptyError": "Enter the code and at least PD or PV (with max uses ≥ 1)." + "promoEmptyError": "Enter the code and at least PD or PV (with max uses ≥ 1).", + "forum": "Forums", + "search": "Search", + "promoConfirmDelete": "Delete this promo code?" }, "Vote": { "title": "Vote for us", @@ -637,7 +640,8 @@ "Common": { "prev": "Previous", "next": "Next", - "page": "Page" + "page": "Page", + "note": "NOTE" }, "RecruitClaim": { "title": "Recruit a friend", @@ -693,5 +697,1143 @@ "NotFound": { "title": "Page not found", "message": "It looks like the page you are looking for doesn't exist or isn't available." + }, + "CharService": { + "transfer": { + "pageTitle": "Transfer character", + "intro": "The Transfer character tool lets you move a character to another account.", + "dkHeading": "For Death Knight characters:", + "dkCond1": "- The destination account must have at least one character of level 55 or higher.", + "dkCond2": "- The destination account cannot have a Death Knight character.", + "securityLock": "Your account will be locked for 5s as a security measure if the operation succeeds.", + "buttonExplain": "When you use the TRANSFER CHARACTER button for the character you have chosen, it will be transferred from your account to the account you have specified.", + "afterTransfer": "When you enter the character list of the destination account, you will see the transferred character.", + "securityTokenHint": "If you don't have a Security Token yet, you can request it here.", + "twoFaHint": "If you don't have 2FA yet, you can request it here.", + "noteOffline": "The character is required to be offline.", + "noteIrreversible": "Please make sure you have chosen the correct character, as this action cannot be reversed once performed.", + "requires": "Requires {price} (SumUp)", + "noCharacters": "You don't have any characters available.", + "selectPlaceholder": "Select a character", + "destinationPlaceholder": "Destination account", + "passwordPlaceholder": "Your account password", + "tokenPlaceholder": "Security Token", + "submit": "TRANSFER CHARACTER", + "submitting": "Transferring character", + "confirm": "Are you sure you want to transfer the character \"{character}\" to the account {destination} for {price} € (SumUp)?", + "errorGeneric": "The transfer could not be started. Please try again.", + "errorUnexpected": "Something went wrong. Please try again later." + }, + "sendGift": { + "pageTitle": "Send gift", + "intro": "The Send gift tool lets you send gifts to your friends.", + "explain1": "When you choose which character sends the gift and the character that will receive it, you will be able to see the list of items available to send as a gift.", + "explain2": "The available items are the same as in the store, and you can send several items at once.", + "explain3": "When you use the SEND GIFT button, a mail will be sent to the destination character with the selected items, indicating who gave it. Payment is made through SumUp.", + "securityTokenHint": "If you don't have a Security Token yet, you can request it here.", + "noteIrreversible": "Please make sure you have entered the correct character name, as this action cannot be reversed once performed.", + "noCharacters": "You don't have any characters available.", + "noItems": "There are no items available to gift right now.", + "errMissingFields": "Fill in the source character, the destination character and the security token.", + "errEmptyCart": "Add at least one item to the cart.", + "confirm": "Send the gift to \"{destination}\" for {total} {currency} (SumUp)? This action cannot be reversed.", + "errPayment": "The payment could not be started. Please try again.", + "errUnexpected": "Something went wrong. Please try again later.", + "sourcePrompt": "Choose which character sends the gift:", + "sourcePlaceholder": "Source character", + "destPrompt": "Name of the character that will receive the gift:", + "destPlaceholder": "Destination character", + "tokenPrompt": "Security Token:", + "tokenPlaceholder": "Security Token", + "availableItems": "Available items", + "add": "Add", + "back": "Back", + "next": "Next", + "cart": "Cart", + "cartEmpty": "You haven't added any items yet.", + "total": "Total: {total} {currency} (SumUp)", + "submit": "SEND GIFT", + "submitting": "Sending gift" + }, + "quest": { + "pageTitle": "Quest tracker", + "intro": "The Quest tracker tool lets you see the status of important quests or quest chains on your characters.", + "optionsAvailable": "Available options:", + "className": { + "warlock": "Warlock", + "hunter": "Hunter", + "shaman": "Shaman", + "druid": "Druid", + "warrior": "Warrior", + "paladin": "Paladin" + }, + "fromLevel": "starting at level {level}", + "byReputation": "By reputation", + "hodir": "The Sons of Hodir: Main quest chain up to interacting with the quartermaster Lillehoff", + "bySpecific": "By specific quest", + "fromLevel10": "Starting at level 10", + "howToSearch": "How to search by specific quest:", + "step1": "1) Visit our database.", + "step2": "2) Search there for the name of the quest.", + "step3": "3) Once you have found it, its link will look like \"{url}/?quest=12843\"", + "step4": "4) Use the final number of the link in the Quest ID field (Example from the previous link: 12843).", + "searchButtonExplain": "When you use the SEARCH QUESTS button, you will be able to see the status of the character's quests.", + "noteOffline": "The character is required to be offline and to meet the minimum level of each option.", + "noteChain1h": "The quest chain search can be repeated on the same character every 1 hour.", + "noteClass30": "The class quest chain search can be repeated on the same character every 30 minutes.", + "noteSpecific10": "The specific quest search can be repeated on the same character every 10 minutes.", + "specificLabel": "By specific quest", + "selectPlaceholder": "Select a character", + "selectOption": "Select an option", + "questIdPlaceholder": "Quest ID", + "submit": "SEARCH QUESTS", + "submitting": "Searching quests", + "noCharacters": "There are no characters available for this tool", + "stateCompleted": "Completed", + "stateInProgress": "In progress", + "stateNotStarted": "Not started", + "questNumber": "Quest #{quest}", + "errors": { + "missingFields": "Select a character and an option.", + "characterNotOwned": "The selected character is not valid.", + "characterOnline": "The character must be offline.", + "wrongClass": "That option does not match the character's class.", + "levelTooLow": "The character does not meet the minimum level for that option.", + "invalidQuestId": "Enter a valid quest ID.", + "noData": "That option is not available yet.", + "cooldown": "You must wait {minutes} min to repeat this search on this character.", + "captcha": "Verify that you are not a robot.", + "notAuthenticated": "Your session has expired. Please sign in again.", + "default": "The search could not be completed. Please try again." + } + }, + "restoreChar": { + "pageTitle": "Restore character", + "intro": "The Restore character tool lets you restore a character that has been deleted.", + "conditions": "Only available for characters that meet the following two conditions:", + "cond1": "- Level higher than 60.", + "cond2": "- Deleted within a period of less than 30 days.", + "dkHeading": "For Death Knight characters:", + "dkCond": "- It is not possible to restore a Death Knight character if there is already another active one on the account.", + "afterRestore": "When you enter the character list of your account, you will see the restored character.", + "noteConditions": "Deleted characters that do not meet those conditions are no longer restorable.", + "noteCooldown": "The action can be repeated on the same character every 12 hours.", + "noCharacters": "There are no characters", + "selectPlaceholder": "Select a character", + "optionLabel": "{name} (level {level})", + "restored": "RESTORED", + "recovering": "Restoring", + "recover": "RESTORE", + "successMsg": "Character \"{name}\" restored! You'll see it when you enter the realm.", + "errors": { + "notFound": "That deleted character does not belong to your account.", + "notDeleted": "That character is not deleted.", + "levelTooLow": "Only characters higher than level 60 can be restored.", + "tooOld": "The character was deleted more than 30 days ago and is no longer restorable.", + "dkExists": "You cannot restore a Death Knight: you already have an active one on the account.", + "nameTaken": "The original name is already in use by another character.", + "cooldown": "You can only attempt to restore the same character once every 12 hours.", + "notAuthenticated": "Your session has expired. Please sign in again.", + "default": "The character could not be restored. Please try again." + } + }, + "restoreItems": { + "pageTitle": "Restore items", + "intro": "The Restore items tool lets you restore items that have been deleted.", + "conditions": "Only available for items that meet the following conditions:", + "quality": "- Of quality: Rare | Epic | Legendary | Artifact | Relic.", + "condEquip": "- Equippable.", + "condBound": "- Binds when picked up.", + "condDeleted": "- Deleted within a period of less than 7 days.", + "noteConditions": "Deleted items that do not meet those conditions are no longer restorable.", + "noteCooldown": "Deleted items can be checked on the same character every 8 hours.", + "requires": "Each item requires {price} (SumUp)", + "selectPlaceholder": "Select a character", + "search": "SEARCH ITEMS", + "searching": "Searching", + "deletedItemsOf": "Deleted items of {character}", + "noDeletedItems": "There are no restorable deleted items.", + "noDeletedItemsMsg": "This character has no restorable deleted items.", + "restoreItem": "Restore ({price} €)", + "confirm": "Restore \"{name}\" for {price} € (SumUp)?", + "queryOther": "Check another character", + "errors": { + "characterNotOwned": "The selected character is not valid.", + "cooldown": "You can only check this character's items every 8 hours ({minutes} min left).", + "soapError": "Could not connect to the game server. Please try again later.", + "insufficientPoints": "You don't have enough DP (100 are required per item).", + "captcha": "Verify that you are not a robot.", + "notAuthenticated": "Your session has expired. Please sign in again.", + "default": "Something went wrong. Please try again." + } + } + }, + "CharServiceB": { + "changeFaction": { + "intro": "The Change character faction tool lets you switch from the Alliance to the Horde and vice versa.", + "alsoRename": "If you also want to change the character's name, you must use the Rename character tool.", + "onChange": "When making a Faction change:", + "change1": "- Items, spells, titles, reputations, mounts and achievements will be changed to the new faction", + "change2": "- Active quests in the Quest Log will be abandoned", + "change3": "- Arena teams will be deleted", + "change4": "- Friends in the Friends List will be removed", + "restrictionsTitle": "Character restrictions:", + "restriction1": "- Must not have active auctions", + "restriction2": "- Must not have mail in the mailbox", + "restriction3": "- Must not be the captain of an arena team", + "restriction4": "- Must not be a member of a guild", + "restriction5": "- Must not have too much gold", + "tableLevel": "Level", + "tableMaxGold": "Max. Gold", + "instructions": "By using the CHANGE FACTION button on the character you have chosen, a faction change request will be sent for that character.", + "iconInfo": "When you enter your account's character list, you will see an icon to the left of your chosen character.", + "iconClick": "By clicking that icon you will enter the character edit menu that will let you switch to the opposite faction.", + "noteLegend": "NOTE", + "noteConfirm": "Please make sure you have chosen the correct character, as this action cannot be undone once performed.", + "requires": "Requires {price} (SumUp)", + "payLabel": "CHANGE FACTION", + "confirm": "Are you sure you want to change the selected character’s faction for {price} € (SumUp)?" + }, + "changeRace": { + "warning": "THIS CHANGE DOES NOT ALLOW SWITCHING TO THE OPPOSITE FACTION", + "intro": "The Change character race tool lets you change the character's race to others of the SAME faction.", + "alsoRename": "If you also want to change the character's name, you must use the Rename character tool.", + "instructions": "By using the CHANGE RACE button on the character you have chosen, a race change request will be sent for that character.", + "iconInfo": "When you enter your account's character list, you will see an icon to the left of your chosen character.", + "iconClick": "By clicking that icon you will enter the character edit menu that will let you choose among the races of the same faction.", + "noteLegend": "NOTE", + "noteConfirm": "Please make sure you have chosen the correct character, as this action cannot be undone once performed.", + "requires": "Requires {price} (SumUp)", + "payLabel": "CHANGE RACE", + "confirm": "Are you sure you want to change the selected character’s race for {price} € (SumUp)?" + }, + "customize": { + "intro": "The Customize character tool lets you change the following aspects of a character:", + "aspect1": "- Skin color", + "aspect2": "- Face", + "aspect3": "- Hair", + "aspect4": "- Sex", + "aspect5": "- Race-specific features such as horns, earrings, markings, facial hair", + "alsoRename": "If you also want to change the character's name, you must use the Rename character tool.", + "instructions": "By using the CUSTOMIZE button on the character you have chosen, a customization request will be sent for that character.", + "iconInfo": "When you enter your account's character list, you will see an icon to the left of your chosen character.", + "iconClick": "By clicking that icon you will enter the character edit menu that will let you choose different features.", + "noteLegend": "NOTE", + "noteConfirm": "Please make sure you have chosen the correct character, as this action cannot be undone once performed.", + "requires": "Requires {price} (SumUp)", + "payLabel": "CUSTOMIZE", + "confirm": "Are you sure you want to customize the selected character for {price} € (SumUp)?" + }, + "levelUp": { + "intro": "The Level up to 80 tool lets you raise any character to level 80.", + "onlyLevel": "It will only level up the character. This option does not include items/gold/etc.", + "instructions": "By using the LEVEL UP TO 80 button on the character you have chosen, level 80 will be sent to the character.", + "levelInfo": "When you enter your account's character list, you will see that your chosen character is already level 80.", + "noteLegend": "NOTE", + "noteOffline": "The character is required to be offline.", + "noteConfirm": "Please make sure you have chosen the correct character, as this action cannot be undone once performed.", + "requires": "Requires {price} (SumUp)", + "payLabel": "LEVEL UP TO 80", + "confirm": "Are you sure you want to level the selected character up to 80 for {price} € (SumUp)?" + }, + "gold": { + "intro": "The Acquire gold tool lets you send gold to a character.", + "instructions": "By using the SEND GOLD button on the character you have chosen, a mail with the chosen amount of gold will be sent to the character.", + "mailInfo": "When you log into the realm with that character, you will have the message with the selected amount of gold in your mailbox.", + "noteLegend": "NOTE", + "noteConfirm": "Please make sure you have chosen the correct character, as this action cannot be undone once performed.", + "requiresLabel": "Requires" + }, + "rename": { + "intro": "The Rename character tool lets you change a character's name.", + "instructions": "By using the RENAME button on the character you have chosen, a name change request will be sent for that character.", + "newNameInfo": "When you try to enter the realm with that character, it will ask you to choose a new name.", + "noteLegend": "NOTE", + "noteConfirm": "Please make sure you have chosen the correct character, as this action cannot be undone once performed.", + "requires": "Requires {price} (SumUp)", + "payLabel": "RENAME", + "confirm": "Are you sure you want to rename the selected character for {price} € (SumUp)?" + } + }, + "History": { + "points": { + "pageTitle": "PD and PV history", + "intro1": "Here you will see the most recent PD and PV usage on the account.", + "intro2": "With this information you can keep track of everything you have acquired as well as check that all activity is normal.", + "intro3": "If you notice any suspicious movement, you can contact the Nova WoW team.", + "boxTitle": "PD and PV history", + "currentBalance": "Current balance:", + "noMovements": "No movements", + "thDate": "Date", + "thConcept": "Concept", + "thMethod": "Method", + "thAmount": "Amount", + "thStatus": "Status" + }, + "trans": { + "pageTitle": "Transaction history", + "intro1": "Here you will see the information we receive from our different automatic payment platforms.", + "intro2": "Have you had a problem with any transaction?", + "intro3": "If you have had a problem with one of the transactions or you have not received your PD, you can contact us on our Discord or through the email contacto@ultimowow.com.", + "noteStripe": "Card payments are normally approved within a few seconds.", + "noteSumup": "SumUp may take a few minutes to confirm the payment after completing the checkout.", + "paidNote": "You will receive the PD corresponding to each transaction only when it is approved and the status is PAID (Paid).", + "important": "Important:", + "noMovements": "No movements", + "thTxId": "Transaction ID", + "thStatus": "Status", + "thConcept": "Concept", + "thCreatedAt": "Created date", + "thAmount": "Amount" + }, + "ban": { + "pageTitle": "Sanctions history", + "intro1": "Here you can see all the sanctions the account has had.", + "intro2": "If you have an active sanction, you will see that its status shows Active.", + "intro3": "To prevent your account from being sanctioned, remember to respect our server's rules.", + "important": "Important:", + "autoBlock1": "If your account appears as sanctioned or closed when trying to log in to the realm, but your history does not have any active sanction, it means you have had a temporary automatic block due to too many failed login attempts.", + "autoBlock2": "Wait at least 10 minutes before trying again and make sure to use the correct account name and password.", + "claim": "To file a sanction appeal, please go to our forum and visit the Appeals section.", + "bansTitle": "Bans history", + "noBans": "No bans", + "mutesTitle": "Mutes history", + "noMutes": "No mutes", + "thScope": "Scope", + "thReason": "Reason", + "thBy": "Sanctioned by", + "thDate": "Date", + "thExpires": "Expires", + "thStatus": "Status", + "permanent": "Permanent" + }, + "security": { + "pageTitle": "Security history", + "intro1": "Here you will see activity and connection information for your account.", + "intro2": "Each table has a detailed explanation of the information provided.", + "intro3": "If you don't recognize any type of activity, we recommend changing the password of your account and of the email linked to it.", + "activityTitle": "Activity history", + "activityDesc": "Shows account security activity, such as password changes.", + "realmTitle": "Connection history (Realm)", + "realmDesc": "Shows a history of connections to the realm only when the IP has changed. It is not a history of every connection.", + "webTitle": "Connection history (Web)", + "webDesc": "Shows a history of every connection to the website.", + "noActivity": "No activity", + "noConnections": "No connections", + "thUser": "User", + "thAction": "Action", + "thStatus": "Status", + "thDate": "Date" + } + }, + "Legal": { + "cookies": { + "title": "Cookie Declaration", + "p1": "This website uses cookies. The cookies on this website are used to personalize content and ads, offer social media features and analyze traffic. In addition, we share information about your use of the website with our social media, advertising and web analytics partners, who may combine it with other information that you have provided to them or that they have collected from your use of their services.", + "p2": "Cookies are small text files that websites can use to make the user experience more efficient.", + "p3": "The law states that we can store cookies on your device if they are strictly necessary for the operation of this page. For all other types of cookies we need your permission.", + "p4": "This page uses different types of cookies. Some cookies are placed by third-party services that appear on our pages.", + "p5": "At any time you can change or withdraw your consent from this Cookie Declaration on our website.", + "p6": "Learn more about who we are, how you can contact us and how we process personal data in our Privacy Policy.", + "h1cat": "Types of cookies we use", + "necessaryTitle": "Necessary Cookies", + "necessaryDesc": "Necessary cookies help make a website usable by enabling basic functions like page navigation and access to secure areas of the website. The website cannot function properly without these cookies.", + "thCookie": "Cookie", + "thProvider": "Provider", + "thPurpose": "Purpose", + "thDuration": "Duration", + "thContentType": "Content type", + "thMoreInfo": "More information", + "durSession": "Session", + "dur1Year": "1 year", + "dur30Min": "30 minutes", + "dur30Days": "30 days", + "durVariable": "Variable", + "durPersistent": "Persistent", + "dur2Years": "2 years", + "dur24Hours": "24 hours", + "dur1Minute": "1 minute", + "dur90Days": "90 days", + "dur3Months": "3 months", + "providerVarious": "Various", + "nPurpose1": "Maintains the user's session state across pages. Present on ultimowow.com and wotlk.ultimowow.com.", + "nPurpose2": "Stores your cookie consent preferences. Shared between ultimowow.com and wotlk.ultimowow.com.", + "nPurpose3": "Identifies legitimate traffic and protects against bots.", + "nPurpose4": "Bot management and protection against DDoS attacks.", + "nPurpose5": "Session identifier for traffic management.", + "nPurpose6": "Device verification for security.", + "nPurpose7": "Indicates authentication status in Cloudflare services.", + "nPurpose8": "Cookies for the Turnstile captcha verification system.", + "nPurpose9": "Distinguishes between humans and bots in the verification system.", + "nPurpose10": "Consent management for the Zaraz system.", + "nPurpose11": "Technical cookies for the Zaraz tag management system.", + "cfNote": "Note about Cloudflare: We use Cloudflare as a security and performance provider. Cloudflare may dynamically set additional cookies to protect the site against threats, manage traffic and optimize performance. These cookies are strictly necessary for the secure operation of the site. For more information, see the Cloudflare Cookie Policy.", + "prefTitle": "Preference Cookies", + "prefDesc": "Preference cookies enable the website to remember information that changes the way the page behaves or looks, such as your preferred language or the region you are in.", + "prefPurpose1": "Saves your comment sorting preference.", + "prefPurpose2": "Saves your comment sorting preference.", + "prefPurpose3": "Saves the settings of the 3D model viewer.", + "analyticsTitle": "Analytics Cookies", + "analyticsDesc": "Analytics cookies allow us to count visits and traffic sources so we can measure and improve the performance of our site. They help us know which pages are the most and least popular, and to see how visitors move around the site. All the information these cookies collect is aggregated and therefore anonymous.", + "aPurpose1": "Distinguishes unique users by assigning a random number.", + "aPurpose2": "Maintains the session state.", + "aPurpose3": "Distinguishes users for statistical analysis.", + "aPurpose4": "Limits the request rate.", + "aPurpose5": "Identifier for web performance analysis.", + "marketingTitle": "Marketing Cookies", + "marketingDesc": "Marketing cookies are used to track visitors across websites. The intention is to display ads that are relevant and engaging for the individual user, and therefore more valuable for publishers and third-party advertisers.", + "mPurpose1": "Google Ads conversions.", + "mPurpose2": "Personalized advertising.", + "mPurpose3": "Identifies browsers to provide advertising and analytics services.", + "mPurpose4": "Stores the last click on Facebook ads.", + "mPurpose5": "Enables the delivery and measurement of ads.", + "mPurpose6": "Visitor identification for Adobe services.", + "mPurpose7": "State management for advertising services.", + "thirdPartyNote": "Note about third-party services: We use Cloudflare Zaraz as a tag management system. Marketing services (Google Ads, Facebook, Adobe, etc.) may set additional cookies when you accept marketing cookies. For more information about each service, see their respective privacy policies.", + "embeddedTitle": "Embedded Content Cookies", + "embeddedDesc": "Some pages on our site include embedded third-party content (YouTube videos, Discord widgets, social media posts, etc.). These services may set their own cookies when you view such content.", + "embType1": "Embedded videos", + "embType2": "Server widgets", + "embType3": "Embedded streams", + "embType4": "Videos and posts", + "privacyPolicyLink": "Privacy Policy", + "embeddedNote": "We use youtube-nocookie.com whenever possible to minimize tracking. However, third-party services may set cookies such as: YSC, VISITOR_INFO1_LIVE, yt-remote-*, __Secure-*, and others related to content playback.", + "h2cat": "How to delete cookies from your browser", + "deleteP": "In addition to using our settings panel, you can delete cookies directly from your browser:", + "deleteLi1": "Chrome: Settings → Privacy and security → Cookies and other site data", + "deleteLi2": "Firefox: Options → Privacy & Security → Cookies and Site Data", + "deleteLi3": "Safari: Preferences → Privacy → Manage Website Data", + "deleteLi4": "Edge: Settings → Cookies and site permissions → Cookies", + "h3cat": "Your consent status", + "consentP": "You can change or withdraw your consent at any time. When contacting us regarding your consent, please indicate the date of your consent.", + "h4cat": "More information", + "moreInfoP": "If you have any questions about our cookie policy, you can contact us through our Contact page.", + "updated": "Last updated: March 2026" + }, + "privacy": { + "title": "Privacy Policy", + "p1": "This Privacy Policy describes how we collect, use, store and protect the personal information of the users (\"you\" or \"user\") of our website. By using our website, you accept the practices described in this policy.", + "h1": "Collection of Personal Information", + "p2": "We collect the following personal information when you use our website:", + "p3": "1. Cookies: We use cookies to collect information about your activity on our website. Cookies are small text files that are stored on your device and allow us to recognize your browser or device and remember certain information. These cookies may be session cookies or persistent cookies. You can adjust your browser settings to refuse all cookies or to indicate when a cookie is being sent. However, if you disable cookies, some features of our website may not work properly.", + "p4": "2. IP addresses: We collect the IP addresses of the users who visit our website. IP addresses are used to analyze trends, administer the website, track user movement and gather demographic information. We do not link IP addresses to any personally identifiable information.", + "p5": "3. Email addresses: We collect the email addresses that you provide when registering on our website or when updating your registration information. We use these email addresses to send you information related to your account, such as registration confirmations, notifications of changes to the terms or policies, and security updates.", + "p6": "4. Usernames and passwords: We collect the usernames and passwords that you choose when registering an account on our website. These credentials are used to authenticate your access to your account and to protect your personal information.", + "h2": "Use of Personal Information", + "p7": "We use the personal information we collect for the following purposes:", + "p8": "1. Provide and improve our services: We use your personal information to provide you with the requested services and improve your experience on our website. This includes personalizing content and recommendations, providing technical support, and analyzing the performance and effectiveness of our website.", + "p9": "2. Communications: We may use your email address to send you communications related to your account, such as registration confirmations, notifications of changes to the terms or policies, security updates and other important updates.", + "h3": "Protection of Personal Information", + "p10": "We take reasonable measures to protect the personal information we collect and store. We use technical, administrative and physical security measures to protect your information against unauthorized access, disclosure, alteration or destruction.", + "h4": "Disclosure of Personal Information to Third Parties", + "p11": "We do not sell, trade or transfer your personal information to third parties without your consent, except in the following cases:", + "p12": "- Service providers: We may share your personal information with service providers who perform functions on our behalf, such as website hosting, payment processing and data analysis. These service providers have access to your personal information only to the extent necessary to perform their functions and are obligated not to disclose or use the information for any other purpose.", + "p13": "- Legal compliance: We may disclose your personal information if we believe in good faith that such disclosure is necessary to comply with a legal obligation, protect your rights or safety, investigate fraud or respond to a legal request.", + "h5": "Your Rights and Choices", + "p14": "You have certain rights and choices regarding your personal information:", + "p15": "- Access and update: You can access and update certain personal information provided through your account on our website.", + "p16": "- Deletion of data: You may request the deletion of your personal information from our records, subject to any legal or contractual requirement we may have.", + "p17": "- Cookies: You can adjust your browser settings to refuse cookies or to indicate when a cookie is being sent. However, please note that disabling cookies may affect the functioning of our website.", + "h6": "Improper use of third-party platforms in order to violate our refund policy", + "p18": "This type of action will result in the expulsion of the user from our site without any refund.", + "h7": "Changes to this Privacy Policy", + "p19": "We reserve the right to update this Privacy Policy at any time. We recommend that you periodically review this page to be aware of any changes. The effective date of the policy will be indicated at the top of the page.", + "h8": "Contact us", + "p20": "If you have any questions or concerns about this Privacy Policy, you can contact us through the following contact information:", + "updated": "Update date: 23-05-2023" + }, + "terms": { + "title": "Terms and conditions", + "h1": "IMPORTANT", + "p1": "Please take a moment to read the terms and conditions detailed below. If you agree with them, then you may enter our site.", + "h2": "ACCEPTANCE OF THE TERMS OF USE AND CONDITIONS", + "p2": "UltimoWoW is a non-profit project developed with the purpose of simulating outdated versions of the server for educational purposes only. The Services offered by UltimoWoW do not support nor will they provide any kind of modification for the server or its files; that said, by using this site or any service belonging to or derived from the Administration, the user accepts responsibility for following and complying with the server's end-user license agreement (EULA).", + "p3": "UltimoWoW does not provide nor take responsibility for the distribution of any server client or external source that contains it. The client download links offered by this site or any medium under its responsibility will always point to said external sources, which, as of this date, do not belong to nor have any relationship with this administration. UltimoWoW is therefore, and under no circumstances, responsible for any aspect regarding said source, namely: quality, performance, warranties or any other characteristic determinant to its purpose, whether or not it is one.", + "p4": "By accessing, browsing or using this Internet site, hereinafter (the “Site”), owned by the UltimoWoW administration, hereinafter (the “Administration”), the user acknowledges having read and understood these terms and conditions of use, hereinafter (“Terms and Conditions”) and agrees to abide by them and comply with all applicable rules, laws and regulations that form part of the legislation in force in their place of residence, or to which they are otherwise subject. In addition, when the user uses any service supplied or referenced on the Site (provided it resides under the responsibility or ownership of the Administration), they will be subject to the rules, guides, policies, terms and conditions applicable to said services.", + "p5": "This Site is controlled and developed by the Administration, reachable through its Discord platforms.", + "p6": "The Administration is not responsible for the material on this Site being appropriate or available for use in other places, its access being prohibited from territories where its content is illegal. Those who choose to access this Site from other places do so on their own initiative, and it is their responsibility to comply with the applicable local laws.", + "p7": "These Terms and Conditions are subject to change at discretion, without prior notice and at any time, under the sole will of UltimoWoW, and starting from the date of publication of their modification on this Site, all operations carried out between the Administration and the user shall be governed by the modified document.", + "h3": "OUR SERVICE: USE, DISTRIBUTION AND DISCLAIMER OF LIABILITY", + "p8": "In accordance with the legislation to which the Administration is subject, the material contained on this Site or any other that may be under its responsibility or care, hereinafter (the “Services” or the “Service”), including without limitation, every image, links, logo, design, insignia, brand, photograph, sound, text, message, tool, software, technology, product, file, information, data, demonstration, sample, promotional material, audiovisual work or multimedia work, and any other element or form of expression (collectively and hereinafter, (the \"Materials\"), are supplied to the best of our knowledge and understanding; however, it is not possible to rule out errors of content or of the material, which is why the Administration assumes no responsibility for the quality, veracity or accuracy of the published information nor for the omissions, errors or discrepancies that may be found in the published information or service provided. ", + "p9": "Regarding the information published in the Services, the Administration confers no warranties of any kind, express or implied, excluding, but not limited to:", + "p10": "- Warranties of merchantability or fitness for a particular purpose.", + "p11": "- Uninterrupted stability of the Service.", + "p12": "- Existence of errors or viruses, as well as its security.", + "p13": "- Accuracy, reliability, qualification or certification for its download.", + "p14": "The Administration is not responsible for the use the user makes of the contents included in the Services, nor for the decisions they make regarding them. The information regarding the products and services of UltimoWoW, included in its Services, is provided for non-commercial educational purposes and does not constitute an offer of sale to its users.", + "p15": "UltimoWoW reserves the right, at its discretion, to:", + "p16": "- Correct any error, omission or inaccuracy in the data provided.", + "p17": "- Change or update, discontinue or delete the information contained in the Services at any time and without prior notice.", + "p18": "- As well as disclaim liability regarding the timeliness, lack of storage, inaccuracy or incorrect delivery of any information or data that it \"normally\" provides, whether temporarily or permanently.", + "h4": "RESPONSIBILITIES AND OBLIGATIONS OF REGISTRATION AND PASSWORDS", + "p19": "The enjoyment of the main fundamental and objective functions of the Service will always be determined by and subject to the existence of a personal and non-transferable registration (namely, a user account). The Administration urges you to provide truthful and verifiable information as requested. Beyond an intrusive nature, said information would be used strictly and discreetly in order to make possible in the future a resolution by the Administration of any extraordinary situation that may arise due to the user's carelessness, thus attempting to settle it in the least harmful way possible for the user. ", + "p20": "It belongs completely and strictly to, and falls upon, the user the responsibility of keeping confidential and secure the passwords established for the Service. As well as the actions taken through the use of their registration, whether or not these are authorized by the user. It also remains the user's responsibility to immediately notify the Administration if they notice any suspicious activity, unauthorized use or unrecognized registration in which their own account appears as the object of manipulation or breach.", + "p21": "The exchange, trade, buying and selling and any similar activity of any form and under any concept in which the knowledge by any person other than the user of their access credentials to the Service appears and is involved is strictly prohibited. Violating said prohibitions could cause the user to incur a serious offense, which could be sanctioned with penalties of a magnitude determined by the Administration at its judgment and discretion, from which in no case would they be exempt from said penalty by claiming use by third parties and in general under no justification.", + "p22": "The characters of the realm that have been deleted and have reached the maximum time limit (on-hold) for recovery, established by the Administration, will disappear permanently, forfeiting with them the possibility of restoration or assistance by the Administration in these cases, independently of and completely disregarding the user's will regarding such action at that time.", + "h5": "CHEATING", + "p23": "Cheating is understood as any act outside and inside the server that attempts to alter or in fact alters and interferes with the rules or with the normal behavior of the server. As well as attempting to or in fact gaining an advantage over other players. Among these, by way of example only and without any limiting intent, any of the following behaviors, whether in one's own name or on behalf of third parties, will be considered as such:", + "p24": "- Accessing the Services in an unauthorized manner (including the use of modified or malicious software).", + "p25": "- Using several accounts at once on the same realm in a way in which controlling several characters simultaneously on the same realm represents a disadvantage of any kind for other users with respect to the offender.", + "p26": "- Using any technique or software to alter or manipulate the variables preset by the server and the Administration.", + "p27": "Cheating is strictly prohibited and the Administration reserves the right to deny any user access to the Service, provided that they have incurred or been the object of an offense of this type, whether directly or indirectly.", + "h6": "PURCHASES, CLAIMS, REFUNDS AND WARRANTIES", + "p28": "UltimoWoW does not represent nor constitute a remittance entity nor a financial services entity of any kind and consequently has no control or responsibility whatsoever over the origin of the funds used to make purchases toward its community. Nor is it responsible for the risks that the user takes on their own will when carrying out financial operations of any type.", + "p29": "Purchases: will always be considered of voluntary good faith and in no case an obligation of any kind for any user. Note also that purchases by natural persons under 18 years of age, or in any case those persons who have not yet reached, under the relevant local legal entities that apply to them, their legal age of majority, are strictly prohibited.", + "p30": "The Service: in any case, does not require any kind of purchase for full and complete use and enjoyment. That said, the user will have an official communication channel via email contacto@ultimowow.com in order to notify the Administration of any error made by either party, in order to issue and make effective a fair resolution.", + "p31": "The Administration: guarantees and commits to providing the buyer with all the information they may require about the current forms or methods of purchase for the community. As well as clarifying any doubt that may arise about the established steps or processes of the same, provided that said information resides within the limits that concern the buyer and has a purely informational purpose.", + "p32": "Taking the above into account, the buyer has monetary and service refund guarantees, subject to the aspects and conditions set out below.", + "h7": "Monetary:", + "p33": "Taking into account the nature of any monetary transaction toward the community's coffers, the Administration commits to refunding (free of transaction costs, at its consideration), in full or in part, ultimately agreed jointly between both parties, those purchases where the user, unintentionally, ended up under the inconvenience, when carrying it out, of errors on their part in the amount of the total sum to be transferred. Said error being in all cases truthful and of a verifiable nature at the Administration's consideration.", + "p34": "Taking into account that the acquired services are received immediately and do not constitute, determine, agree upon nor modify any deadline for their use. Nor for the enjoyment of the service and its functionalities, which, it should be stressed, are considered completely free, of an educational nature and lack admission and expiration deadlines.", + "p35": "The Administration does not guarantee nor will it provide in any case nor under any concept or circumstance any refund on purchases or any goods in general transferred to the community. Note and let the following cases be clarified:", + "p36": "- To users whose accounts have been temporarily or permanently sanctioned for incurring any offense set out in any of its Terms and Conditions.", + "p37": "- To users who have made the decision not to continue (partially or temporarily) using any of the services provided by The Administration.", + "p38": "In none of these cases will the Administration present, in full or in part, any trace of any of its monetary records or of any kind for resolution purposes.", + "p39": "Likewise, the user has the respective means and channels, namely within the Service's forums, or the Discord server, to submit a formal appeal before an administrator and thus have the case evaluated for subsequent resolution. The Administration reserves the right to evaluate but not guarantee, and at its discretion, refunds in those cases where, after being studied and reconciled, it is considered by the same to be fair and extraordinary.", + "h8": "Service-related:", + "p40": "The Administration guarantees the integrity and functionality of all the items purchased in its store. In any case, it will provide you a term of 48 hours after your purchase to request replacements for items or services of equal value, or also, upon request, the full return of the services used in those cases where said item or service is found broken or unusable, or was purchased or chosen by mistake, all of this always and after a relevant analysis has been carried out by an administrator, and after authentic and conclusive evidence relevant to the case has been demonstrated by the user.", + "p41": "As well as the Administration guaranteeing the restoration of the service due to technical and specific problems, between the Service and the payment platforms, always beyond the buyer's control, if said services were not delivered automatically and immediately in their name. ", + "h9": "PRIVACY POLICY", + "p42": "The Service and the Administration collect information regarding the user such as email address, name, password, language and time zone, in order to provide better optimization of their services each time, using this information to adapt the functionalities to better performance in line with the user and their requirements. Said information may also be used to keep the user informed through independent communication channels not related to the Service, informing about important news, updates, technical problems or any other information of such nature that the Administration considers relevant to the user's interests. ", + "p43": "The Administration and the Service commit to safeguarding the confidentiality of such data, as well as to guaranteeing the NON-disclosure of it, except in cases where the laws in force governing the Administration consider it necessary and mandatory for reasons not related to UltimoWoW. " + }, + "refund": { + "title": "Refund Policy", + "h1": "OUR SERVICE", + "p1": "All of our services are delivered immediately and are received exactly as described.", + "h2": "OUR RESPONSIBILITY", + "p2": "We guarantee the functioning, delivery time and description of the services provided by our site.", + "p3": "It is important that the user understands that what they acquire on the site are services that are received immediately.", + "p4": "They do not acquire any usage time of the services, nor any benefit, nor immunity.", + "p5": "Every case covered by our refund policy will be handled with the reset or correction of the service and a subsequent review guaranteeing the correct functioning of the reset or corrected service.", + "h3": "NOTIFICATION TIME", + "p6": "Any error or problem with our services must be notified to the administration within a maximum period of 48 hours from the delivery of the service.", + "p7": "After this period of time, the user can no longer request any type of refund.", + "p8": "Contact: contacto@ultimowow.com.", + "h4": "COVERAGE", + "p9": "This refund policy covers:", + "p10": "- Acquisition of the wrong service due to a poor selection by the user.", + "p11": "- Errors caused by the website that prevented the delivery of the service.", + "p12": "- Errors caused by third-party platforms that prevented the delivery of the service.", + "p13": "This refund policy does NOT cover, under any circumstances:", + "p14": "- Regrets.", + "p15": "- Errors in the use of the service made by the user.", + "p16": "- Ignorance of our refund policy.", + "p17": "- Improper use of third-party platforms in order to violate our refund policy.", + "p18": "- Expulsion from our site for breach of our terms and rules.", + "h5": "Refund request made through the payment platform.", + "p19": "Requesting a refund for reasons covered by this refund policy will result in a refund on our part with the corresponding cancellation of the acquired service.", + "p20": "Requesting a refund for reasons not covered by this refund policy such as:", + "p21": "- The account has been sanctioned.", + "p22": "- The person no longer uses the service and tries to request a refund after 48 hours from the moment of acquisition.", + "p23": "- Abuse of available tools claiming reasons that are untrue regarding the delivered service.", + "p24": "Do not qualify for a refund and may lead to permanent expulsion from the site for breach of our terms and improper use of the available payment platforms.", + "h6": "Regrets", + "p25": "No type of regret after the delivery of a service qualifies for a refund.", + "h7": "Errors in the use of the service made by the user", + "p26": "Errors in the use of the services, caused by the user, that are not related to any type of failure in the delivered service do not qualify for a refund.", + "p27": "Any user error caused by not reading the description of a service does not qualify for a refund.", + "p28": "Once the service is delivered, its use remains the user's responsibility.", + "h8": "Ignorance of our refund policy", + "p29": "The user's ignorance of our refund policy does not exempt the user from complying with it.", + "h9": "Improper use of third-party platforms in order to violate our refund policy", + "p30": "This type of action will result in the expulsion of the user from our site without any refund.", + "h10": "Expulsion from our site for breach of our terms and rules", + "p31": "No acquisition of our services grants any type of immunity.", + "p32": "The expulsion of a user from our site does not qualify for any type of refund.", + "p33": "Compliance with our terms and rules remains the exclusive responsibility of the user, and any expulsion resulting from breach of them does not qualify to request a refund of the services already delivered and enjoyed.", + "h11": "Changes to this Refund Policy", + "p34": "We reserve the right to update this Refund Policy at any time. We recommend that you periodically review this page to be aware of any changes.", + "h12": "Contact us", + "p35": "If you have any questions or concerns about this Refund Policy, you can contact us through the following contact information:", + "updated": "Update date: 25-05-2023" + }, + "legalNotice": { + "title": "Legal Notice", + "p1": "The website \"UltimoWoW.com\" and its subdomains (hereinafter, \"the website\") are offered solely for informational and entertainment purposes. UltimoWoW is not responsible for the use that users make of the website. Although correct use is intended, UltimoWoW assumes no responsibility for the actions, decisions or consequences derived from the use of the website. Users are responsible for verifying the accuracy, completeness and usefulness of the information provided, as well as for complying with applicable laws and regulations when using the content of the website.", + "p2": "Third-party links: The website may contain links to third-party websites. These links are provided solely for your convenience and do not imply the endorsement or affiliation of UltimoWoW with said websites. UltimoWoW is not responsible for the content or privacy practices of these third-party websites.", + "p3": "Privacy and Cookies: The collection and use of your personal data is governed by our Privacy Policy and the use of cookies is governed by our Cookie Declaration. By using the website, you accept our practices described in said policies.", + "p4": "Copyright: Users of the website must respect copyright and not publish content that infringes the intellectual property rights of third parties. UltimoWoW is committed to protecting copyright and complying with applicable laws. If you find infringing content, contact us using the infringement claim mechanism described below.", + "p5": "Infringement claim mechanism: If you believe that your work has been used in an unauthorized manner on the website, you can submit a copyright infringement claim by providing the required information. Contact us using the contact details below.", + "contactTitle": "Contact" + }, + "contact": { + "title": "Contact us", + "p1": "Thank you for your interest in contacting us!", + "p2": "If you have any questions, inquiries or comments, we will be happy to help you. Please send an email to the following address:", + "p3": "Error 404 is the company that represents the UltimoWoW service.", + "p4": "We strive to respond to all messages within 48 business hours.", + "p5": "Be sure to include the relevant information in your email so that we can provide you with an accurate and timely response.", + "p6": "At Error 404, we value your comments and opinions. Your satisfaction is our priority and we strive to provide you with the best possible experience at UltimoWoW.", + "p7": "We look forward to hearing from you soon!", + "p8": "Sincerely, the Error 404 team." + } + }, + "Misc": { + "home": { + "recruitFriend": "RECRUIT A FRIEND!", + "labelTime": "Time", + "introP1": "{realm} is a community focused on Spanish-speaking users, especially aimed at the Spanish and Latin American audience.", + "introP2": "We attract users passionate about both PvE and PvP, and we offer a wide variety of content.", + "introP3": "Our main goal is to maintain a high-level community, providing a pleasant environment so that all members, new and veteran alike, find here a place where they can experience unforgettable moments.", + "introP4": "Join us and enjoy a unique experience with thousands of users!", + "newsHeading": "NEWS", + "noNews": "No news available at this time.", + "newsLinkLabel": "Link:", + "here": "here", + "showingLatest": "* Showing the latest 50 news items" + }, + "realm": { + "charactersHeading": "Characters", + "realmHeading": "Realm" + }, + "downloadAddons": { + "title": "Addon download", + "recommended": "Recommended addons", + "intro1": "Addons are optional plugins that enhance and personalize your gaming experience.", + "intro2": "Download the ones you want from their official page (choose the version compatible with WotLK 3.4.3).", + "howToInstall": "How to install them", + "step1": "1) Download the addon and unzip the .zip file.", + "step2": "2) Copy the resulting folder into Interface/AddOns (in your client folder).", + "step3": "3) Start the game and, on the character selection screen, click AddOns to enable them.", + "download": "Download", + "descDbm": "Warnings and timers for boss abilities in dungeons and raids.", + "descDetails": "Damage, healing and threat meter with detailed graphs.", + "descAtlasLoot": "Check the loot of dungeon and raid bosses inside the game.", + "descQuestie": "Shows quest objectives and locations on the map and minimap.", + "descBagnon": "Unifies all your bags and the bank into a single searchable window.", + "descBartender4": "Fully customize your action bars.", + "descAuctioneer": "Advanced tools for the auction house.", + "descPawn": "Compares gear and tells you which item is an upgrade for your character." + }, + "twofaLogin": { + "pageTitle": "Two-step verification", + "info": "Information", + "backToAccount": "Return to my account", + "back": "Return", + "previewAlt": "Authenticator preview", + "p1": "2FA stands for \"Two Factor Authentication\", or two-step verification.", + "p2": "It is a method that adds an extra layer of security to the login process.", + "p3": "Instead of simply entering your username and password, 2FA requires a second verification step, thus increasing the protection of your account.", + "p4": "Once enabled, after entering your username and password, a window (image on the right) will appear asking for the authentication code generated by the app.", + "backupCodes": "Backup codes", + "p5": "When you enable 2FA, you will be provided with unique backup codes.", + "p6": "These codes are useful in case you lose access to your authentication app.", + "p7": "Each backup code can be used only once.", + "p8": "Keep them in a safe place, as they will allow you to access your account on the website if you cannot use the authentication app.", + "requestToken": "If you don't have a Security Token yet, you can request it here.", + "note": "NOTE", + "noteText": "Use an authentication app to log in to the game once you have it enabled." + }, + "help": { + "title": "Help", + "subtitle": "Assistance guide", + "intro1": "In this guide you will learn what steps to follow to get the right assistance depending on the type of problem you have found on our server.", + "intro2": "We offer a set of common problems, which means to use for each case and an explanation of each means of contact.", + "intro3": "The different means for each problem are listed from the most ideal to the last resort.", + "clientTitle": "With the client", + "clientText": "Problems that prevent the client from launching, connecting to the server, or errors that cause the client to crash abruptly.", + "mediaAre": "The means are:", + "mediaForos": "- Forums", + "mediaDiscord": "- Discord", + "mediaTicket": "- Ticket", + "serverErrorsTitle": "With server errors", + "serverErrorsText": "Problems related to errors that must be fixed by our repair team to improve the server.", + "characterTitle": "With the character", + "characterText": "Problems related to errors that may affect the character, abilities, spells, quests, etc.", + "otherPlayerTitle": "With another player", + "otherPlayerText1": "Problems related to other users breaking the server rules.", + "otherPlayerText2": "These types of problems require a report with the corresponding evidence of what happened.", + "accountBlocksTitle": "With account blocks", + "accountBlocksText": "Problems related to account blocks issued by the {realm} team.", + "websiteTitle": "With the website", + "websiteText": "Problems related to errors, bugs or suggestions regarding this website.", + "mailTo": "- Email to", + "pdTitle": "With PD", + "pdText": "Problems related to PD or PV.", + "contactMeans": "Means of contact", + "ticketTitle": "Ticket", + "ticket1": "To submit a ticket, you must click the red question mark in the lower right corner of the client interface (to the left of the character's keyring).", + "ticket2": "When you click it, a window will appear in the middle of the screen.", + "ticket3": "In that window, click the first button in the lower left corner called 'Talk to a GM'", + "ticket4": "A window will appear with informative text and, below in the middle, a button called 'Open a query'.", + "ticket5": "When you click the button, a text field will appear in which you can describe your problem", + "ticket6": "When you have finished, click the first button in the lower right corner called 'Send'.", + "ticket7": "The ticket has now been created and is pending a response from a team member.", + "discordTitle": "Discord", + "discord1": "Discord is a chat and voice communication platform that can be downloaded here.", + "discord2": "To join our server's Discord, click here.", + "discord3": "Once you are a member of our Discord, you can ask for help in the 'Assistance' channel or send a direct message to any team member requesting help.", + "forosTitle": "Forums", + "foros1": "The forums are a great tool where not only the {realm} team can help you, but other players can also assist you if they know how to solve the problem you have.", + "foros2": "To request help through this means, you must have a user with which to log in and open a new topic in the appropriate forum.", + "foros3": "You can visit our forums here.", + "emailTitle": "Email", + "email1": "The server has different email addresses dedicated to different server topics.", + "email2": "Depending on your problem, use the appropriate one to send us an email message." + } + }, + "Points": { + "dpoints": { + "title": "Get PD" + }, + "dpointsSuccess": { + "title": "Get PD", + "paidOk": "Payment complete! Your PD have been credited to your account.", + "alreadyPaid": "This payment had already been processed. Your PD are credited.", + "error": "We couldn't confirm your payment. If you were charged, please contact support.", + "backToAccount": "← Back to my account" + }, + "transferDp": { + "title": "Transfer PD", + "intro1": "The Transfer PD tool lets you transfer PD from your account to any other account.", + "intro2": "Using the TRANSFER PD button will transfer the amount you chose from your account to the account of the character you entered.", + "tokenHelp": "If you don't have a Security Token yet, you can request one here.", + "note": "NOTE", + "noteText": "Please make sure you have typed the correct character name, as this action cannot be reversed once done.", + "noPd": "You have no PD", + "confirm": "You are about to transfer {n} PD to the character \"{character}\".\nThis action cannot be reversed. Do you want to continue?", + "success": "You have transferred {n} PD to the character \"{character}\".", + "available": "You have {balance} PD available", + "characterPlaceholder": "Destination character name", + "amountPlaceholder": "Amount of PD", + "tokenPlaceholder": "Security token", + "transferring": "Transferring…", + "transferButton": "TRANSFER PD", + "errors": { + "missingFields": "Fill in the destination character, the amount and the security token.", + "invalidAmount": "The amount must be a whole number greater than 0.", + "invalidToken": "The security token is not valid.", + "characterNotFound": "There is no character with that name.", + "sameAccount": "You can't transfer PD to your own account.", + "insufficientFunds": "You don't have enough PD to make this transfer.", + "notAuthenticated": "Your session has expired. Please log in again.", + "generic": "The transfer could not be completed. Please try again." + } + }, + "trade": { + "title": "PD trading", + "intro1": "The PD trading tool lets you buy or sell PD for gold in a secure way.", + "intro2": "The system lets you create single-use codes worth X amount of PD in exchange for X amount of gold.", + "intro3": "Sellers have the SELL section to create the code, and buyers have the BUY section to redeem that code.", + "sellTitle": "Sell", + "sell1": "1) Decide how much the code will be worth in PD.", + "sell2": "2) Decide how much gold it can be redeemed for.", + "sell3": "3) Choose which character on the account will receive the gold when the code is redeemed.", + "sell4": "4) Fill in the details with your password and Security Token.", + "sell5": "5) Use the CREATE CODE button.", + "sell6": "6) A box will appear with the details of the created Code, including the ID to be used to send to another player.", + "buyTitle": "Buy", + "buy1": "1) Enter the ID of the code another player gave you.", + "buy2": "2) Check the PD value and gold cost with the CHECK CODE button.", + "buy3": "3) Choose which character on the account will have the gold deducted when the code is redeemed.", + "buy4": "4) Fill in the details with your password and Security Token.", + "buy5": "5) Use the REDEEM CODE button.", + "buy6": "6) A box will appear with the details of the redeemed Code, PD received and gold withdrawn from the selected character.", + "duration": "Each code lasts 1 hour.", + "onceRedeemed": "Once the code is redeemed:", + "redeemed1": "- The PD will be withdrawn from the code creator's account and sent to whoever redeemed it.", + "redeemed2": "- The gold will be withdrawn and mailed to the creator.", + "redeemed3": "- The transaction will be recorded in the PD & VP history.", + "lockNote": "The account of whoever redeems the code will be locked for 5s as a security measure if the operation is successful.", + "tokenHelp": "If you don't have a Security Token yet, you can request one here.", + "note": "NOTE", + "noteText": "Please make sure you have entered all the correct details, as this action cannot be reversed once done.", + "sellTab": "SELL", + "buyTab": "BUY", + "noCharacters": "You have no characters on this account.", + "codeCreated": "Code created!", + "sellPointsLabel": "How much will the code be worth in PD?", + "sellPointsPlaceholder": "Code value in PD", + "sellGoldLabel": "How much will the code cost in gold?", + "sellGoldPlaceholder": "Code value in gold", + "sellCharLabel": "Which character will receive the gold?", + "selectCharacter": "Select a character", + "passwordPlaceholder": "Your account password", + "tokenPlaceholder": "Security token", + "creating": "Creating…", + "createButton": "Create code", + "createdLegend": "Code created", + "codeIdLabel": "Code ID:", + "createdValue": "Value: {points} PD for {gold} gold", + "createdHint": "Send this ID to the buyer. The code expires in 1 hour.", + "buyCodeLabel": "Enter the PD code ID", + "buyCodePlaceholder": "PD code", + "checkInfo": "Worth {points} PD · Costs {gold} gold", + "buyCharLabel": "Which character will be charged the gold?", + "checkButton": "Check code", + "processing": "Processing…", + "redeemButton": "Redeem code", + "checkResult": "This code is worth {points} PD and costs {gold} gold.", + "redeemConfirm": "You are about to redeem this code. This action cannot be reversed. Do you want to continue?", + "redeemSuccess": "Redeemed successfully! You received {points} PD and {gold} gold was withdrawn from {character}.", + "errors": { + "missingFields": "Fill in all fields.", + "invalidAmount": "The amounts must be whole numbers between 1 and 99999.", + "characterInvalid": "The selected character is not valid.", + "captcha": "Verify that you are not a robot.", + "wrongPassword": "Your account password is incorrect.", + "invalidToken": "The security token is not valid.", + "insufficientPoints": "You don't have enough PD available to create this code.", + "codeNotFound": "There is no code with that ID.", + "codeUnavailable": "The code is no longer available (redeemed or expired).", + "cannotRedeemOwn": "You can't redeem your own code.", + "characterOnline": "The character must be offline to collect the gold.", + "insufficientGold": "The character doesn't have enough gold.", + "creatorInsufficient": "The code creator no longer has enough PD.", + "locked": "Wait a few seconds before redeeming another code.", + "deliveryFailed": "The gold could not be delivered (game server unavailable). Please try again later.", + "notAuthenticated": "Your session has expired. Please log in again.", + "generic": "The operation could not be completed. Please try again." + } + }, + "promo": { + "title": "Promo code", + "intro1": "Promo codes are words with letters and numbers that are redeemed in the form below for PD or VP and have limited uses. Each one may give a different amount of PD/VP.", + "intro2": "These codes are generated by the {realm} Team and may appear on the website, Discord, social media or the server.", + "intro3": "We recommend keeping an eye on social media and server announcements to know when a code is available.", + "note": "NOTE", + "noteText": "Codes are case-sensitive, so you must always type them exactly as they appear published.", + "placeholder": "Enter your promo code", + "redeeming": "Redeeming…", + "redeemButton": "REDEEM CODE", + "rewardPd": "{pd} PD", + "rewardPv": "{pv} VP", + "and": "and", + "rewardDefault": "the reward", + "success": "Code redeemed! You have received {reward}.", + "errors": { + "missingCode": "Enter a promo code.", + "notFound": "The code doesn't exist or is no longer available.", + "expired": "This code has expired.", + "exhausted": "This code has already reached its usage limit.", + "alreadyUsed": "You have already redeemed this code.", + "notAuthenticated": "Your session has expired. Please log in again.", + "generic": "The code could not be redeemed. Please try again." + } + }, + "renameGuild": { + "title": "Rename guild", + "intro1": "The Rename guild tool lets you rename a guild of which you are the Guild Master.", + "rules": "When choosing a new name, keep in mind:", + "rule1": "- The maximum length is 24 characters.", + "rule2": "- The allowed characters are A-Za-z and the space.", + "intro2": "Using the RENAME GUILD button on the guild you chose will change its name to the new name you entered.", + "intro3": "The guild name change is instant. Connected guild members may need to reconnect to finally see the new name.", + "note": "NOTE", + "noteText": "Please make sure you have chosen the correct name, as this action cannot be reversed once done.", + "requires": "Requires {pd}PD", + "noGuilds": "No Guild Master characters", + "confirm": "Are you sure you want to rename the selected guild?", + "success": "Guild renamed to \"{newName}\"! Connected members may need to reconnect to see it.", + "selectGuild": "Select a guild", + "newNamePlaceholder": "New guild name", + "tokenPlaceholder": "Security token", + "renamed": "GUILD RENAMED", + "renaming": "RENAMING GUILD", + "renameButton": "RENAME GUILD", + "errors": { + "missingFields": "Complete all fields.", + "invalidName": "The name must be 1 to 24 characters, only letters (A-Z, a-z) and spaces.", + "invalidToken": "The security token is not valid.", + "notGuildMaster": "You are not the Master of that guild.", + "nameTaken": "A guild with that name already exists.", + "insufficientPoints": "You don't have enough PD (1000 required).", + "soapError": "The change could not be applied (game server unavailable). Please try again later.", + "notAuthenticated": "Your session has expired. Please log in again.", + "generic": "The guild could not be renamed. Please try again." + } + }, + "tabs": { + "info": "Information", + "backToAccount": "Back to my account", + "back": "Back", + "whatArePd": "What are PD?", + "whatArePdText": "We offer our users the opportunity to earn levels that grant them exclusive benefits within our online community. These benefits include access to special tools, exclusive content and significant improvements to their experience on our website. When making a purchase, our users receive PD, an internal unit of recognition that reflects their commitment and progress on our platform. PD let them reach new levels and unlock exclusive rewards. It is worth noting that these PD are a unique way to value and reward our users' active participation in our community.", + "availableLevels": "What levels are available?", + "show": "Show", + "hide": "Hide", + "level": "Level {n}", + "range1": "From 0 PD", + "range2": "Up to 100 PD", + "range3": "Up to 200 PD", + "range4": "Up to 300 PD", + "range5": "Up to 400 PD", + "range6": "Up to 500 PD", + "range7": "Up to 600 PD", + "range8": "Up to 700 PD", + "range9": "Up to 800 PD", + "range10": "Up to 900 PD", + "range11": "Up to 1000 PD", + "range12": "Up to 5000 PD", + "range13": "Up to 10000 PD", + "range14": "Over 10000 PD", + "purchaseMethods": "What are the PD purchase methods?", + "purchaseMethodsText": "The currently available purchase methods are:", + "stripeMethod": "Stripe (credit/debit card, for all countries).", + "sumupMethod": "SumUp (credit/debit card).", + "howManyPd": "How many PD do you receive?", + "howManyPdText": "For every {sym}1 you receive 100 PD. The final amount is shown before confirming the payment.", + "doubts": "Do you have questions or issues with a purchase?", + "doubtsText1": "Don't make a purchase until you are completely sure you have read this information and understand the process you are going to choose.", + "doubtsText2": "If after reading this guide you still have questions, the {realm} team can assist you at any time. You can open a ticket on the server, or contact us through our Discord platform.", + "mustAccept": "You must accept the Terms and Conditions and the Refund Policy", + "confirmPurchase": "You are about to get {points} PD for {sym}{amount}.\nDo you want to continue to payment?", + "rate": "{sym}1 = 100 PD", + "minMax": "Minimum value: {sym}1 · Maximum value per transaction: {sym}200", + "important": "Important!", + "integersOnly": "Enter whole values only (no decimals).", + "example": "Example: for 200 PD type 2.", + "amountLabel": "Amount in {currency} to get", + "amountPlaceholder": "Amount in {currency}", + "willReceive": "You will receive {points} PD", + "acceptTerms": " I accept the Terms and Conditions and the Refund Policy", + "acquireButton": "GET PD", + "redirecting": "Redirecting…", + "whatIsStripe": "What is Stripe?", + "stripeAboutText": "Stripe is a secure online payment platform that processes credit and debit cards from all over the world. Your payment details are handled directly by Stripe; {realm} never stores them.

More information about Stripe here.", + "howStripe": "How to get PD through Stripe?", + "stripeHowText": "As it is a self-managed system, purchases are automatic, and within minutes of completing the payment you will receive the PD in your account.", + "step1": "- Enter the amount you wish to get in the field below.", + "stripeStep2": "- When you press GET PD, you will be redirected to Stripe's secure gateway to complete the payment with your card.", + "stripeStep3": "- Once Stripe validates your payment, you will have the PD in your account automatically.", + "reminderMin": "Remember that the amount only accepts whole numbers and the lowest possible is {sym}1.", + "wrongExamples": "Examples of incorrect value: {sym}5.90 | {sym}22.30 | {sym}53.10", + "rightExamples": "Examples of correct value: {sym}6 | {sym}22 | {sym}53", + "whatIsSumup": "What is SumUp?", + "sumupAboutText": "SumUp is a European payment platform that lets you pay quickly and securely with a credit or debit card. Your payment details are handled directly by SumUp; {realm} never stores them.

More information about SumUp here.", + "howSumup": "How to get PD through SumUp?", + "sumupHowText": "As it is a self-managed system, purchases are automatic, and after completing the payment you will receive the PD in your account.", + "sumupStep2": "- When you press GET PD, you will be redirected to SumUp's secure gateway to complete the payment with your card.", + "sumupStep3": "- Once SumUp validates your payment, you will have the PD in your account automatically.", + "checkoutErrors": { + "notConfigured": "This payment method is not available yet. Please use another method or try again later.", + "invalidAmount": "The amount must be a whole number between 1 and 200.", + "notAuthenticated": "Your session has expired. Please log in again.", + "generic": "The payment could not be started. Please try again." + } + } + }, + "UI": { + "header": { + "home": "HOME", + "register": "CREATE ACCOUNT", + "downloads": "DOWNLOADS", + "client": "CLIENT", + "addons": "ADDONS", + "changelog": "CHANGELOG", + "realm": "REALM", + "players": "PLAYERS", + "community": "COMMUNITY", + "forums": "FORUMS", + "wotlkDb": "WOTLK DB", + "videos": "VIDEOS", + "help": "HELP", + "myAccount": "MY ACCOUNT", + "logout": "LOG OUT", + "login": "LOG IN" + }, + "footer": { + "terms": "Terms and Conditions", + "privacy": "Privacy Policy", + "refund": "Refund Policy", + "cookies": "Cookie Statement", + "legal": "Legal Notice", + "contact": "Contact Us", + "copyright": "© Copyright {realmName}™ {year}. All rights reserved", + "design": "Design: \"{realmName}\" By Inna Hoover Brown" + }, + "social": { + "followUs": "FOLLOW US ON" + }, + "realmInfo": { + "ratesTitle": "Rates", + "experience": "Experience", + "experienceValue": "x8 adjustable with .xp (With Recruit-A-Friend x16)", + "greenBlueDrop": "Green and blue item drop", + "greenBlueDropValue": "x4", + "goldNpc": "Gold drop from NPCs", + "goldNpcValue": "x2", + "goldQuest": "Gold drop from quests", + "goldQuestValue": "x1", + "skills": "Skills", + "skillsValue": "x3", + "professions": "Professions", + "professionsValue": "x3", + "reputations": "Reputations", + "reputationsValue": "x3 (Bonus with Recruit-A-Friend)", + "honor": "Honor", + "honorValue": "x3", + "scheduleTitle": "Schedules", + "scheduleNote": "The following schedules are based on the realm time.", + "dailyQuests": "Daily quests", + "dailyQuestsValue": "7 am", + "dailyDungeons": "Daily dungeon reset", + "dailyDungeonsValue": "9 am", + "raidReset": "Raid reset", + "raidResetValue": "9 am (Wednesday)", + "battlegrounds": "Battlegrounds", + "battlegroundsValue": "10 am", + "arenaPoints": "Arena Points distribution", + "arenaPointsValue": "11 am (Friday)" + }, + "players": { + "updateNotice": "The information on this page is updated automatically once a day", + "charsByClass": "Characters created by class", + "total": "Total:", + "alliances": "Alliance:", + "hordes": "Horde:", + "allianceAlt": "Alliance", + "hordeAlt": "Horde", + "totalChars": "Total characters:", + "allianceChars": "Alliance characters:", + "hordeChars": "Horde characters:", + "firstsTitle": "Realm Firsts - Level 80", + "noLevel80": "There are no level 80 characters registered yet.", + "thAchievement": "Achievement", + "thCharacter": "Character", + "thDate": "Date", + "firstOfRealm": "Realm first!", + "topAchTitle": "Top achievements", + "topAchSub": "The 10 players with the most achievements", + "thName": "Name", + "thRace": "Race", + "thClass": "Class", + "thAchPoints": "Achievement points", + "topHonorTitle": "Top honorable kills", + "topHonorSub": "The 10 players with the most honorable kills", + "thTotalKills": "Total kills", + "thTodayKills": "Total kills today" + }, + "recruit": { + "errRequirements": "You do not meet the requirements for this reward yet.", + "errAlreadyClaimed": "This reward has already been claimed.", + "errInvalidCharacter": "Invalid character.", + "errNotFound": "Reward not found.", + "errGeneric": "The reward could not be claimed. Please try again.", + "accountRecruited": "Recruited account:", + "yes": "Yes", + "no": "No", + "friendsRecruited": "Recruited friends:", + "friendsAtLevel80": "Friends recruited to level 80:", + "rewardsClaimed": "Rewards claimed:", + "receiveRewardsOn": "Receive rewards on:", + "thFriends": "Recruited friends", + "thReward": "Reward", + "thStatus": "Status", + "friendsAtLevel80Row": "{count, plural, one {# friend at level 80} other {# friends at level 80}}", + "claimed": "Claimed", + "claim": "Claim", + "unclaimed": "Not claimed", + "availableRewards": "AVAILABLE REWARDS", + "recruitToClaim": "Recruit friends to be able to claim the rewards", + "readyToClaim": "You have {count, plural, one {# reward ready} other {# rewards ready}} to claim" + }, + "clientDownload": { + "torrentTitle": "Torrent Download", + "infoLabel": "Information", + "info1": "- No installation required.", + "info2": "- The realmlist is already configured.", + "info3": "- The download is handled through a magnet link. If you already know how to make downloads of this type, the following steps are optional.", + "requirementsLabel": "Download requirements", + "requirementsText": "You will need a program that handles Torrent downloads and a program that handles .rar files.", + "popupNote": "Additionally, you will need this page to be able to open pop-up windows.", + "stepByStep": "Step by step:", + "stepOptional": "Optional: If you do not have Winrar, click WinRAR and install the program.", + "step1": "1) Click qBittorrent.", + "step2": "2) Download the appropriate version for your operating system.", + "step3": "3) Run the downloaded file and install the program.", + "step4": "4) Run qBitTorrent.", + "step5": "5) Go to the bottom of this page and choose your preferred language.", + "step6": "6) Below the language, choose the operating system.", + "step7": "7) Click Download.", + "step8": "8) In the pop-up window, accept Open qBitTorrent.", + "step9": "9) Wait for qBitTorrent to load the corresponding file in the Magnet link window.", + "step10": "10) Click OK.", + "step11": "11) In the qBitTorrent window, wait for the download to complete.", + "step12": "12) Go to qBitTorrent's downloads folder (Downloads by default).", + "step13": "13) Right-click the .rar file and use the Extract here option.", + "step14": "14) Go into the extracted folder and there you will find the executable to start playing.", + "step15": "15) Connect using your website account; in the email field do not enter your email but your account name.", + "languageLabel": "Language", + "chooseLanguage": "Choose language", + "clientEses": "esES Client", + "clientEsmx": "esMX Client", + "clientEnus": "enUS Client", + "clientEngb": "enGB Client", + "langEses": "esES language: Spanish (Spain).", + "langEsmx": "esMX language: Spanish (Latin America).", + "langEnus": "enUS language: English (US).", + "langEngb": "enGB language: British English.", + "osLabel": "Operating system", + "chooseOs": "Choose operating system", + "windows": "Windows", + "macCatalina": "Mac OS Catalina", + "downloadBtn": "DOWNLOAD", + "errorChoose": "You must choose a client and an operating system.", + "macGuideTitle": "Guide to run the client on mac OS Catalina", + "mac1": "macOS Catalina no longer supports applications that run in 32-bit, and the client runs in 32-bit.", + "mac2": "By following the steps below you will be able to enjoy UltimoWoW without problems on macOS Catalina.", + "macInstructions": "Instructions", + "macStep1": "1 - Download and install CrossOver.", + "macStep2": "2 - Once you have downloaded the client, run CrossOver and click \"Install a Windows application\".", + "macStep3": "3 - In the \"Select an application to install\" field, look for the download, select it and click continue. (Do not click install yet).", + "macStep4": "4 - Go to the tab that says \"Select installer\", click \"Choose installer file\", and now look for WoW.exe and select it.", + "macStep5": "5 - In the Bottle tab, you can select Windows 7 64-bit.", + "macStep6": "6 - Go to the \"Install and finish\" tab, click Install, and it will install all the fonts, files and Visual Redistributables that WoW uses on a standard Windows operating system.", + "macStep7": "7 - It will ask you to install and accept the FONTS, Microsoft Visual C ++, click Yes for each request that appears.", + "macStep8": "8 - The client will start automatically.", + "macStep9": "9 - Once you finish and exit the client, click \"Done\" in the CrossOver application.", + "macStep10": "10 - The next time you want to return, open the CrossOver application, look at the left panel and select the WoW that was previously created in Bottle, and click RUN COMMAND, select WoW.exe and click ¨Save command as launcher¨, then click Open.", + "macStep11": "11 - Finally, you will see the WoW icon under the WoW Bottle tab; now you can drag the WoW launcher to the Dock, so that next time you want to log in, you simply run WoW from the Dock." + }, + "cookie": { + "dialogLabel": "Cookie consent", + "title": "We use cookies", + "description": "This site uses first-party and third-party cookies to ensure the site works, analyze traffic and offer you personalized advertising. Check our cookie policy for more information.", + "policyLink": "Cookie Policy", + "catNecessary": "Necessary", + "descNecessary": "Essential for the site to work. They cannot be disabled.", + "catAnalytics": "Analytics", + "descAnalytics": "They help us understand how you use the site to improve it.", + "catMarketing": "Marketing", + "descMarketing": "They are used to show you relevant ads.", + "savePrefs": "Save preferences", + "reject": "Reject", + "customize": "Customize", + "acceptAll": "Accept all", + "changeConsent": "Change consent", + "revokeConsent": "Withdraw consent", + "statusZaraz": "Current status (Cloudflare Zaraz Consent API):", + "statusSaved": "Current status (saved preference):", + "statusUnavailable": "Cloudflare Zaraz is not available on this domain; there is no saved preference yet.", + "accepted": "Accepted", + "rejected": "Rejected", + "alwaysOn": "Always on" + }, + "twofa": { + "errGeneric": "Something went wrong. Please try again later.", + "eyeHide": "Hide", + "eyeShow": "Show", + "passwordPlaceholder": "Password", + "tokenPlaceholder": "Security token", + "activating": "Activating 2FA", + "activate": "Activate 2FA", + "step1": "Step 1) Download the authenticator app:", + "step2": "Step 2) Scan this QR code with your authenticator app:", + "copyKeyNote": "If you cannot scan the QR code, copy and paste this key into your authenticator app:", + "copied": "Copied!", + "copyKey": "Copy key", + "step3": "Step 3) Enter the code generated by your authenticator app:", + "codePlaceholder": "6-digit code", + "verified": "Verified ✔️", + "verifying": "Verifying...", + "verifyCode": "Verify code", + "enabledNotice": "Two-step verification is enabled on this account.", + "disableInstruction": "To disable it, enter a current code from your authenticator app.", + "disabled": "2FA disabled ✔️", + "disabling": "Disabling...", + "disable": "Disable 2FA" + } } } diff --git a/web-next/messages/es.json b/web-next/messages/es.json index d73291e..0c8672c 100644 --- a/web-next/messages/es.json +++ b/web-next/messages/es.json @@ -563,7 +563,10 @@ "promoRedemptions": "Canjes", "noPromo": "No hay códigos de promoción.", "promoDuplicate": "Ya existe un código con ese texto.", - "promoEmptyError": "Escribe el código y al menos PD o PV (con usos máx. ≥ 1)." + "promoEmptyError": "Escribe el código y al menos PD o PV (con usos máx. ≥ 1).", + "forum": "Foros", + "search": "Buscar", + "promoConfirmDelete": "¿Borrar este código de promoción?" }, "Vote": { "title": "Votar por nosotros", @@ -637,7 +640,8 @@ "Common": { "prev": "Anterior", "next": "Siguiente", - "page": "Página" + "page": "Página", + "note": "NOTA" }, "RecruitClaim": { "title": "Recluta a un amigo", @@ -693,5 +697,1143 @@ "NotFound": { "title": "Página no encontrada", "message": "Parece que la página que estás buscando no existe o no se encuentra disponible." + }, + "CharService": { + "transfer": { + "pageTitle": "Transferir personaje", + "intro": "La herramienta Transferir personaje te permite mover un personaje a otra cuenta.", + "dkHeading": "Para personajes Caballeros de la Muerte:", + "dkCond1": "- La cuenta destino debe tener aunque sea un personaje con nivel 55 o superior.", + "dkCond2": "- La cuenta destino no puede tener un personaje Caballero de la Muerte.", + "securityLock": "Tu cuenta será bloqueada por 5s como medida de seguridad si el trámite es exitoso.", + "buttonExplain": "Al usar el botón TRANSFERIR PERSONAJE del personaje que hayas escogido, se transferirá desde tu cuenta a la cuenta que hayas indicado.", + "afterTransfer": "Cuando ingreses a la lista de personajes de la cuenta destino, verás al personaje transferido.", + "securityTokenHint": "Si aún no tienes Token de seguridad, puedes solicitarlo aquí.", + "twoFaHint": "Si aún no tienes 2FA, puedes solicitarlo aquí.", + "noteOffline": "Se requiere que el personaje esté desconectado.", + "noteIrreversible": "Por favor, asegúrate de haber escogido al personaje correcto ya que esta acción no es reversible una vez realizada.", + "requires": "Requiere {price} (SumUp)", + "noCharacters": "No tienes personajes disponibles.", + "selectPlaceholder": "Selecciona un personaje", + "destinationPlaceholder": "Cuenta de destino", + "passwordPlaceholder": "Contraseña de tu cuenta", + "tokenPlaceholder": "Token de seguridad", + "submit": "TRANSFERIR PERSONAJE", + "submitting": "Transfiriendo personaje", + "confirm": "¿Estás seguro de transferir el personaje \"{character}\" a la cuenta {destination} por {price} € (SumUp)?", + "errorGeneric": "No se pudo iniciar la transferencia. Inténtalo de nuevo.", + "errorUnexpected": "Algo ha salido mal. Inténtalo más tarde." + }, + "sendGift": { + "pageTitle": "Enviar regalo", + "intro": "La herramienta Enviar regalo te permite enviar regalos a tus amigos.", + "explain1": "Al elegir desde qué personaje se enviará el regalo y el personaje que lo recibirá, podrás ver la lista de objetos disponibles para enviar como regalo.", + "explain2": "Los objetos disponibles son los mismos de la tienda y puedes enviar varios objetos a la vez.", + "explain3": "Al usar el botón ENVIAR REGALO se enviará un correo al personaje destino con los ítems seleccionados, indicando quién lo ha regalado. El pago se realiza mediante SumUp.", + "securityTokenHint": "Si aún no tienes Token de seguridad, puedes solicitarlo aquí.", + "noteIrreversible": "Por favor, asegúrate de haber escrito el nombre del personaje correcto ya que esta acción no es reversible una vez realizada.", + "noCharacters": "No tienes personajes disponibles.", + "noItems": "No hay objetos disponibles para regalar por ahora.", + "errMissingFields": "Completa el personaje de origen, el de destino y el token de seguridad.", + "errEmptyCart": "Añade al menos un objeto al carrito.", + "confirm": "¿Enviar el regalo a \"{destination}\" por {total} {currency} (SumUp)? Esta acción no es reversible.", + "errPayment": "No se pudo iniciar el pago. Inténtalo de nuevo.", + "errUnexpected": "Algo ha salido mal. Inténtalo más tarde.", + "sourcePrompt": "Escoge desde qué personaje se envía el regalo:", + "sourcePlaceholder": "Personaje de origen", + "destPrompt": "Nombre del personaje que recibirá el regalo:", + "destPlaceholder": "Personaje de destino", + "tokenPrompt": "Token de seguridad:", + "tokenPlaceholder": "Token de seguridad", + "availableItems": "Objetos disponibles", + "add": "Añadir", + "back": "Atrás", + "next": "Siguiente", + "cart": "Carrito", + "cartEmpty": "Aún no has añadido objetos.", + "total": "Total: {total} {currency} (SumUp)", + "submit": "ENVIAR REGALO", + "submitting": "Enviando regalo" + }, + "quest": { + "pageTitle": "Rastreador de misiones", + "intro": "La herramienta Rastreador de misiones te permite ver el estado de misiones o cadenas de misiones importantes en tus personajes.", + "optionsAvailable": "Opciones disponibles:", + "className": { + "warlock": "Brujo", + "hunter": "Cazador", + "shaman": "Chamán", + "druid": "Druida", + "warrior": "Guerrero", + "paladin": "Paladín" + }, + "fromLevel": "a partir del nivel {level}", + "byReputation": "Por reputación", + "hodir": "Los Hijos de Hodir: Cadena de misiones principal hasta interactuar con el intendente Lillehoff", + "bySpecific": "Por misión específica", + "fromLevel10": "A partir del nivel 10", + "howToSearch": "Cómo buscar por misión específica:", + "step1": "1) Visita nuestra base de datos.", + "step2": "2) Busca allí el nombre de la misión.", + "step3": "3) Una vez que la hayas encontrado, su enlace se verá cómo \"{url}/?quest=12843\"", + "step4": "4) Usa el número final del enlace en el campo ID de misión (Ejemplo del enlace anterior: 12843).", + "searchButtonExplain": "Al usar el botón BUSCAR MISIONES, podrás ver el estado de las misiones del personaje.", + "noteOffline": "Se requiere que el personaje esté desconectado y cumpla con el mínimo de nivel de cada opción.", + "noteChain1h": "Se puede repetir búsqueda de cadenas de misiones en un mismo personaje cada 1 hora.", + "noteClass30": "Se puede repetir búsqueda de cadenas de misiones de clase en un mismo personaje cada 30 minutos.", + "noteSpecific10": "Se puede repetir búsqueda de misión específica en un mismo personaje cada 10 minutos.", + "specificLabel": "Por misión específica", + "selectPlaceholder": "Selecciona un personaje", + "selectOption": "Selecciona una opción", + "questIdPlaceholder": "ID de misión", + "submit": "BUSCAR MISIONES", + "submitting": "Buscando misiones", + "noCharacters": "No hay personajes disponibles para esta herramienta", + "stateCompleted": "Completada", + "stateInProgress": "En curso", + "stateNotStarted": "Sin empezar", + "questNumber": "Misión #{quest}", + "errors": { + "missingFields": "Selecciona un personaje y una opción.", + "characterNotOwned": "El personaje seleccionado no es válido.", + "characterOnline": "El personaje debe estar desconectado.", + "wrongClass": "Esa opción no corresponde a la clase del personaje.", + "levelTooLow": "El personaje no cumple el nivel mínimo de esa opción.", + "invalidQuestId": "Introduce un ID de misión válido.", + "noData": "Esa opción no está disponible todavía.", + "cooldown": "Debes esperar {minutes} min para repetir esta búsqueda en este personaje.", + "captcha": "Verifica que no eres un robot.", + "notAuthenticated": "Tu sesión ha expirado. Inicia sesión de nuevo.", + "default": "No se pudo completar la búsqueda. Inténtalo de nuevo." + } + }, + "restoreChar": { + "pageTitle": "Recuperar personaje", + "intro": "La herramienta Recuperar personaje te permite restaurar un personaje que haya sido borrado.", + "conditions": "Sólo disponible para personajes que cumplan las siguientes dos condiciones:", + "cond1": "- Nivel superior a 60.", + "cond2": "- Borrado en un período menor a 30 días.", + "dkHeading": "Para personajes Caballeros de la Muerte:", + "dkCond": "- No es posible recuperar un personaje Caballero de la Muerte si ya hay otro activo en la cuenta.", + "afterRestore": "Cuando ingreses a la lista de personajes de tu cuenta, verás al personaje recuperado.", + "noteConditions": "Personajes borrados que no cumplan dichas condiciones ya no son recuperables.", + "noteCooldown": "Se puede repetir la acción en un mismo personaje cada 12 horas.", + "noCharacters": "No hay personajes", + "selectPlaceholder": "Selecciona un personaje", + "optionLabel": "{name} (nivel {level})", + "restored": "RECUPERADO", + "recovering": "Recuperando", + "recover": "RECUPERAR", + "successMsg": "¡Personaje \"{name}\" recuperado! Lo verás al entrar al reino.", + "errors": { + "notFound": "Ese personaje borrado no es de tu cuenta.", + "notDeleted": "Ese personaje no está borrado.", + "levelTooLow": "Solo se pueden recuperar personajes de nivel superior a 60.", + "tooOld": "El personaje se borró hace más de 30 días y ya no es recuperable.", + "dkExists": "No puedes recuperar un Caballero de la Muerte: ya tienes uno activo en la cuenta.", + "nameTaken": "El nombre original ya está en uso por otro personaje.", + "cooldown": "Solo puedes intentar recuperar el mismo personaje una vez cada 12 horas.", + "notAuthenticated": "Tu sesión ha expirado. Inicia sesión de nuevo.", + "default": "No se pudo recuperar el personaje. Inténtalo de nuevo." + } + }, + "restoreItems": { + "pageTitle": "Recuperar ítems", + "intro": "La herramienta Recuperar ítems te permite recuperar ítems que hayan sido borrados.", + "conditions": "Sólo disponible para ítems que cumplan las siguientes condiciones:", + "quality": "- De calidad: Raro | Épico | Legendaria | Artefacto | Reliquia.", + "condEquip": "- Equipable.", + "condBound": "- Se liga al recogerlo.", + "condDeleted": "- Borrado en un período menor a 7 días.", + "noteConditions": "Ítems borrados que no cumplan dichas condiciones ya no son recuperables.", + "noteCooldown": "Se pueden consultar ítems borrados en un mismo personaje cada 8 horas.", + "requires": "Cada ítem requiere {price} (SumUp)", + "selectPlaceholder": "Selecciona un personaje", + "search": "BUSCAR ÍTEMS", + "searching": "Buscando", + "deletedItemsOf": "Ítems borrados de {character}", + "noDeletedItems": "No hay ítems borrados recuperables.", + "noDeletedItemsMsg": "Este personaje no tiene ítems borrados recuperables.", + "restoreItem": "Recuperar ({price} €)", + "confirm": "¿Recuperar \"{name}\" por {price} € (SumUp)?", + "queryOther": "Consultar otro personaje", + "errors": { + "characterNotOwned": "El personaje seleccionado no es válido.", + "cooldown": "Solo puedes consultar los ítems de este personaje cada 8 horas (faltan {minutes} min).", + "soapError": "No se pudo conectar con el servidor de juego. Inténtalo más tarde.", + "insufficientPoints": "No tienes suficientes PD (se requieren 100 por ítem).", + "captcha": "Verifica que no eres un robot.", + "notAuthenticated": "Tu sesión ha expirado. Inicia sesión de nuevo.", + "default": "Algo ha salido mal. Inténtalo de nuevo." + } + } + }, + "CharServiceB": { + "changeFaction": { + "intro": "La herramienta Cambiar facción del personaje te permite cambiar de la Alianza a la Horda y viceversa.", + "alsoRename": "Si también deseas cambiar el nombre del personaje, debes usar la herramienta Renombrar personaje.", + "onChange": "Al hacer un cambio de Facción:", + "change1": "- Los items, hechizos, títulos, reputaciones, monturas y logros se cambiarán a la nueva facción", + "change2": "- Las misiones activas en el Registro de misiones serán abandonadas", + "change3": "- Los teams de arena serán borrados", + "change4": "- Los amigos en la Lista de amigos se borrarán", + "restrictionsTitle": "Restricciones del personaje:", + "restriction1": "- No debe tener subastas activas", + "restriction2": "- No debe tener correos en el buzón", + "restriction3": "- No debe ser capitán de un team de arenas", + "restriction4": "- No debe ser miembro de una hermandad", + "restriction5": "- No debe tener demasiado oro", + "tableLevel": "Nivel", + "tableMaxGold": "Max. Oro", + "instructions": "Al usar el botón CAMBIAR FACCIÓN del personaje que hayas escogido, se enviará una petición de cambio de facción de dicho personaje.", + "iconInfo": "Cuando ingreses a la lista de personajes de tu cuenta, verás un ícono a la izquierda de tu personaje escogido.", + "iconClick": "Al darle click a dicho ícono ingresarás al menú de edición de personaje que te permitirá pasar a la facción contraria.", + "noteLegend": "NOTA", + "noteConfirm": "Por favor, asegúrate de haber escogido al personaje correcto ya que esta acción no es reversible una vez realizada.", + "requires": "Requiere {price} (SumUp)", + "payLabel": "CAMBIAR FACCIÓN", + "confirm": "¿Estás seguro de cambiar de facción al personaje seleccionado por {price} € (SumUp)?" + }, + "changeRace": { + "warning": "ESTE CAMBIO NO PERMITE CAMBIAR A LA FACCIÓN CONTRARIA", + "intro": "La herramienta Cambiar raza del personaje te permite cambiar la raza del personaje entre otras de la MISMA facción.", + "alsoRename": "Si también deseas cambiar el nombre del personaje, debes usar la herramienta Renombrar personaje.", + "instructions": "Al usar el botón CAMBIAR RAZA del personaje que hayas escogido, se enviará una petición de cambio de raza de dicho personaje.", + "iconInfo": "Cuando ingreses a la lista de personajes de tu cuenta, verás un ícono a la izquierda de tu personaje escogido.", + "iconClick": "Al darle click a dicho ícono ingresarás al menú de edición de personaje que te permitirá escoger entre las razas de la misma facción.", + "noteLegend": "NOTA", + "noteConfirm": "Por favor, asegúrate de haber escogido al personaje correcto ya que esta acción no es reversible una vez realizada.", + "requires": "Requiere {price} (SumUp)", + "payLabel": "CAMBIAR RAZA", + "confirm": "¿Estás seguro de cambiar de raza al personaje seleccionado por {price} € (SumUp)?" + }, + "customize": { + "intro": "La herramienta Personalizar personaje te permite cambiar los siguientes aspectos un personaje:", + "aspect1": "- Color de la piel", + "aspect2": "- Rostro", + "aspect3": "- Pelo", + "aspect4": "- Sexo", + "aspect5": "- Características correspondientes a cada raza como cuernos, pendientes, marcas, vello facial", + "alsoRename": "Si también deseas cambiar el nombre del personaje, debes usar la herramienta Renombrar personaje.", + "instructions": "Al usar el botón PERSONALIZAR del personaje que hayas escogido, se enviará una petición de personalización de dicho personaje.", + "iconInfo": "Cuando ingreses a la lista de personajes de tu cuenta, verás un ícono a la izquierda de tu personaje escogido.", + "iconClick": "Al darle click a dicho ícono ingresarás al menú de edición de personaje que te permitirá escoger diferentes características.", + "noteLegend": "NOTA", + "noteConfirm": "Por favor, asegúrate de haber escogido al personaje correcto ya que esta acción no es reversible una vez realizada.", + "requires": "Requiere {price} (SumUp)", + "payLabel": "PERSONALIZAR", + "confirm": "¿Estás seguro de personalizar al personaje seleccionado por {price} € (SumUp)?" + }, + "levelUp": { + "intro": "La herramienta Subir a nivel 80 te permite subir cualquier personaje al nivel 80.", + "onlyLevel": "Sólo subirá de nivel al personaje. Esta opción no incluye ítems/oro/etc.", + "instructions": "Al usar el botón SUBIR A NIVEL 80 del personaje que hayas escogido, se enviará el nivel 80 al personaje.", + "levelInfo": "Cuando ingreses a la lista de personajes de tu cuenta, verás que tu personaje escogido ya es nivel 80.", + "noteLegend": "NOTA", + "noteOffline": "Se requiere que el personaje esté desconectado.", + "noteConfirm": "Por favor, asegúrate de haber escogido al personaje correcto ya que esta acción no es reversible una vez realizada.", + "requires": "Requiere {price} (SumUp)", + "payLabel": "SUBIR A NIVEL 80", + "confirm": "¿Estás seguro de subir a nivel 80 al personaje seleccionado por {price} € (SumUp)?" + }, + "gold": { + "intro": "La herramienta Adquirir oro te permite enviar oro a un personaje.", + "instructions": "Al usar el botón ENVIAR ORO del personaje que hayas escogido, se enviará un correo con la cantidad de oro elegida al personaje.", + "mailInfo": "Cuando entres al reino con dicho personaje, tendrás el mensaje con la cantidad de oro seleccionada en tu buzón.", + "noteLegend": "NOTA", + "noteConfirm": "Por favor, asegúrate de haber escogido al personaje correcto ya que esta acción no es reversible una vez realizada.", + "requiresLabel": "Requiere" + }, + "rename": { + "intro": "La herramienta Renombrar personaje te permite cambiar de nombre a un personaje.", + "instructions": "Al usar el botón RENOMBRAR del personaje que hayas escogido, se enviará una petición de cambio de nombre de dicho personaje.", + "newNameInfo": "Cuando intentes entrar al reino con ese personaje, te pedirá que escojas un nuevo nombre.", + "noteLegend": "NOTA", + "noteConfirm": "Por favor, asegúrate de haber escogido al personaje correcto ya que esta acción no es reversible una vez realizada.", + "requires": "Requiere {price} (SumUp)", + "payLabel": "RENOMBRAR", + "confirm": "¿Estás seguro de renombrar al personaje seleccionado por {price} € (SumUp)?" + } + }, + "History": { + "points": { + "pageTitle": "Historial de PD y PV", + "intro1": "Aquí verás los consumos de PD y PV más recientes que ha tenido la cuenta.", + "intro2": "Con esta información podrás tener control de todo lo que has adquirido así como también chequear que toda la actividad sea normal.", + "intro3": "Si observas algún movimiento sospechoso, puedes contactar con el equipo de Nova WoW.", + "boxTitle": "Historial de PD y PV", + "currentBalance": "Saldo actual:", + "noMovements": "No hay movimientos", + "thDate": "Fecha", + "thConcept": "Concepto", + "thMethod": "Método", + "thAmount": "Importe", + "thStatus": "Estado" + }, + "trans": { + "pageTitle": "Historial de transacciones", + "intro1": "Aquí verás la información que recibimos de nuestras diferentes plataformas de pago automáticas.", + "intro2": "¿Has tenido algún problema con alguna transacción?", + "intro3": "Si has tenido un problema con una de las transacciones o no has recibido tus PD, puedes contactarnos en nuestro Discord o a través del correo contacto@ultimowow.com.", + "noteStripe": "Los pagos con tarjeta se aprueban normalmente en unos segundos.", + "noteSumup": "SumUp puede tardar unos minutos en confirmar el pago tras completar el checkout.", + "paidNote": "Recibirás los PD correspondientes a cada transacción sólo cuando esté aprobada y el estado sea PAID (Pagado).", + "important": "Importante:", + "noMovements": "No hay movimientos", + "thTxId": "ID de transacción", + "thStatus": "Estado", + "thConcept": "Concepto", + "thCreatedAt": "Fecha creación", + "thAmount": "Cantidad" + }, + "ban": { + "pageTitle": "Historial de sanciones", + "intro1": "Aquí podrás ver todas las sanciones que ha tenido la cuenta.", + "intro2": "Si tienes una sanción vigente, verás que su estado indica Activo.", + "intro3": "Para evitar que tu cuenta sea sancionada, recuerda respetar las normas de nuestro servidor.", + "important": "Importante:", + "autoBlock1": "Si tu cuenta aparece como sancionada o cerrada al intentar ingresar al reino, pero tu historial no tiene ninguna sanción activa, significa que has tenido un bloqueo automático temporal por demasiados intentos de inicio de sesión fallidos.", + "autoBlock2": "Espera al menos 10 minutos para volver a intentar y asegúrate de usar nombre de cuenta y contraseña correctas.", + "claim": "Para realizar un reclamo de sanción, por favor ingresa en nuestro foro y visita la sección Reclamaciones.", + "bansTitle": "Historial de baneos", + "noBans": "No hay baneos", + "mutesTitle": "Historial de muteos", + "noMutes": "No hay muteos", + "thScope": "Alcance", + "thReason": "Motivo", + "thBy": "Sancionado por", + "thDate": "Fecha", + "thExpires": "Expira", + "thStatus": "Estado", + "permanent": "Permanente" + }, + "security": { + "pageTitle": "Historial de seguridad", + "intro1": "Aquí verás información de actividad y conexiones de tu cuenta.", + "intro2": "Cada tabla tiene una explicación detallada de la información provista.", + "intro3": "Si desconoces algún tipo de actividad te recomendamos cambiar la contraseña de tu cuenta y del correo ligado a la misma.", + "activityTitle": "Historial de actividad", + "activityDesc": "Muestra actividad de seguridad de la cuenta, como por ejemplo cambios de contraseña.", + "realmTitle": "Historial de conexiones (Reino)", + "realmDesc": "Muestra un historial de conexiones al reino sólo cuando la IP ha cambiado. No es un historial de cada conexión.", + "webTitle": "Historial de conexiones (Web)", + "webDesc": "Muestra un historial de cada conexión al sitio web.", + "noActivity": "No hay actividad", + "noConnections": "No hay conexiones", + "thUser": "Usuario", + "thAction": "Acción", + "thStatus": "Estado", + "thDate": "Fecha" + } + }, + "Legal": { + "cookies": { + "title": "Declaración de Cookies", + "p1": "Esta página web usa cookies. Las cookies de este sitio web se usan para personalizar el contenido y los anuncios, ofrecer funciones de redes sociales y analizar el tráfico. Además, compartimos información sobre el uso que haga del sitio web con nuestros partners de redes sociales, publicidad y análisis web, quienes pueden combinarla con otra información que les haya proporcionado o que hayan recopilado a partir del uso que haya hecho de sus servicios.", + "p2": "Las cookies son pequeños archivos de texto que las páginas web pueden utilizar para hacer más eficiente la experiencia del usuario.", + "p3": "La ley afirma que podemos almacenar cookies en tu dispositivo si son estrictamente necesarias para el funcionamiento de esta página. Para todos los demás tipos de cookies necesitamos tu permiso.", + "p4": "Esta página utiliza tipos diferentes de cookies. Algunas cookies son colocadas por servicios de terceros que aparecen en nuestras páginas.", + "p5": "En cualquier momento puedes cambiar o retirar tu consentimiento desde esta Declaración de cookies en nuestro sitio web.", + "p6": "Obten más información sobre quiénes somos, cómo puedes contactarnos y cómo procesamos los datos personales en nuestra Política de Privacidad.", + "h1cat": "Tipos de cookies que utilizamos", + "necessaryTitle": "Cookies Necesarias", + "necessaryDesc": "Las cookies necesarias ayudan a hacer una página web utilizable activando funciones básicas como la navegación en la página y el acceso a áreas seguras de la página web. La página web no puede funcionar adecuadamente sin estas cookies.", + "thCookie": "Cookie", + "thProvider": "Proveedor", + "thPurpose": "Propósito", + "thDuration": "Duración", + "thContentType": "Tipo de contenido", + "thMoreInfo": "Más información", + "durSession": "Sesión", + "dur1Year": "1 año", + "dur30Min": "30 minutos", + "dur30Days": "30 días", + "durVariable": "Variable", + "durPersistent": "Persistente", + "dur2Years": "2 años", + "dur24Hours": "24 horas", + "dur1Minute": "1 minuto", + "dur90Days": "90 días", + "dur3Months": "3 meses", + "providerVarious": "Varios", + "nPurpose1": "Mantiene el estado de la sesión del usuario entre páginas. Presente en ultimowow.com y wotlk.ultimowow.com.", + "nPurpose2": "Almacena tus preferencias de consentimiento de cookies. Se comparte entre ultimowow.com y wotlk.ultimowow.com.", + "nPurpose3": "Identifica tráfico legítimo y protege contra bots.", + "nPurpose4": "Bot management y protección contra ataques DDoS.", + "nPurpose5": "Identificador de sesión para gestión de tráfico.", + "nPurpose6": "Verificación de dispositivo para seguridad.", + "nPurpose7": "Indica estado de autenticación en servicios Cloudflare.", + "nPurpose8": "Cookies del sistema de verificación captcha Turnstile.", + "nPurpose9": "Distingue entre humanos y bots en el sistema de verificación.", + "nPurpose10": "Gestión de consentimiento del sistema Zaraz.", + "nPurpose11": "Cookies técnicas del sistema de gestión de tags Zaraz.", + "cfNote": "Nota sobre Cloudflare: Utilizamos Cloudflare como proveedor de seguridad y rendimiento. Cloudflare puede establecer cookies adicionales de forma dinámica para proteger el sitio contra amenazas, gestionar el tráfico y optimizar el rendimiento. Estas cookies son estrictamente necesarias para el funcionamiento seguro del sitio. Para más información, consulta la Política de Cookies de Cloudflare.", + "prefTitle": "Cookies de Preferencias", + "prefDesc": "Las cookies de preferencias permiten a la página web recordar información que cambia la forma en que la página se comporta o el aspecto que tiene, como su idioma preferido o la región en la que usted se encuentra.", + "prefPurpose1": "Guarda tu preferencia de ordenación de comentarios.", + "prefPurpose2": "Guarda tu preferencia de ordenación de comentarios.", + "prefPurpose3": "Guarda la configuración del visor 3D de modelos.", + "analyticsTitle": "Cookies Analíticas", + "analyticsDesc": "Las cookies analíticas nos permiten contar las visitas y fuentes de tráfico para poder medir y mejorar el rendimiento de nuestro sitio. Nos ayudan a saber qué páginas son las más y menos populares, y a ver cómo se mueven los visitantes por el sitio. Toda la información que recogen estas cookies es agregada y, por lo tanto, anónima.", + "aPurpose1": "Distingue usuarios únicos asignando un número aleatorio.", + "aPurpose2": "Mantiene el estado de la sesión.", + "aPurpose3": "Distingue usuarios para análisis estadístico.", + "aPurpose4": "Limita la velocidad de solicitudes.", + "aPurpose5": "Identificador para análisis de rendimiento web.", + "marketingTitle": "Cookies de Marketing", + "marketingDesc": "Las cookies de marketing se utilizan para rastrear a los visitantes en las páginas web. La intención es mostrar anuncios relevantes y atractivos para el usuario individual, y por lo tanto, más valiosos para los editores y terceros anunciantes.", + "mPurpose1": "Conversiones de Google Ads.", + "mPurpose2": "Publicidad personalizada.", + "mPurpose3": "Identifica navegadores para proporcionar servicios de publicidad y análisis.", + "mPurpose4": "Almacena el último clic en anuncios de Facebook.", + "mPurpose5": "Habilita la entrega y medición de anuncios.", + "mPurpose6": "Identificación de visitantes para servicios de Adobe.", + "mPurpose7": "Gestión de estado para servicios de publicidad.", + "thirdPartyNote": "Nota sobre servicios de terceros: Utilizamos Cloudflare Zaraz como sistema de gestión de tags. Los servicios de marketing (Google Ads, Facebook, Adobe, etc.) pueden establecer cookies adicionales cuando aceptas cookies de marketing. Para más información sobre cada servicio, consulta sus respectivas políticas de privacidad.", + "embeddedTitle": "Cookies de Contenido Embebido", + "embeddedDesc": "Algunas páginas de nuestro sitio incluyen contenido embebido de terceros (vídeos de YouTube, widgets de Discord, publicaciones de redes sociales, etc.). Estos servicios pueden establecer sus propias cookies cuando visualizas dicho contenido.", + "embType1": "Vídeos embebidos", + "embType2": "Widgets de servidor", + "embType3": "Streams embebidos", + "embType4": "Vídeos y publicaciones", + "privacyPolicyLink": "Política de Privacidad", + "embeddedNote": "Utilizamos youtube-nocookie.com cuando es posible para minimizar el seguimiento. Sin embargo, los servicios de terceros pueden establecer cookies como: YSC, VISITOR_INFO1_LIVE, yt-remote-*, __Secure-*, y otras relacionadas con la reproducción de contenido.", + "h2cat": "Cómo eliminar cookies de tu navegador", + "deleteP": "Además de utilizar nuestro panel de configuración, puedes eliminar las cookies directamente desde tu navegador:", + "deleteLi1": "Chrome: Configuración → Privacidad y seguridad → Cookies y otros datos de sitios", + "deleteLi2": "Firefox: Opciones → Privacidad & Seguridad → Cookies y datos del sitio", + "deleteLi3": "Safari: Preferencias → Privacidad → Gestionar datos de sitios web", + "deleteLi4": "Edge: Configuración → Cookies y permisos del sitio → Cookies", + "h3cat": "Tu estado de consentimiento", + "consentP": "Puedes cambiar o retirar tu consentimiento en cualquier momento. Al contactarnos respecto a su consentimiento, por favor, indique la fecha de su consentimiento.", + "h4cat": "Más información", + "moreInfoP": "Si tienes alguna pregunta sobre nuestra política de cookies, puedes contactarnos a través de nuestra página de Contacto.", + "updated": "Última actualización: Marzo 2026" + }, + "privacy": { + "title": "Política de privacidad", + "p1": "Esta Política de Privacidad describe cómo recopilamos, utilizamos, almacenamos y protegemos la información personal de los usuarios (\"usted\" o \"usuario\") de nuestro sitio web. Al utilizar nuestro sitio web, usted acepta las prácticas descritas en esta política.", + "h1": "Recopilación de Información Personal", + "p2": "Recopilamos la siguiente información personal cuando usted utiliza nuestro sitio web:", + "p3": "1. Cookies: Utilizamos cookies para recopilar información sobre su actividad en nuestro sitio web. Las cookies son pequeños archivos de texto que se almacenan en su dispositivo y nos permiten reconocer su navegador o dispositivo y recordar cierta información. Estas cookies pueden ser cookies de sesión o cookies persistentes. Puede ajustar la configuración de su navegador para rechazar todas las cookies o para indicar cuándo se envía una cookie. Sin embargo, si desactiva las cookies, es posible que algunas funciones de nuestro sitio web no funcionen correctamente.", + "p4": "2. Direcciones IP: Recopilamos direcciones IP de los usuarios que visitan nuestro sitio web. Las direcciones IP se utilizan para analizar tendencias, administrar el sitio web, rastrear el movimiento del usuario y recopilar información demográfica. No vinculamos las direcciones IP con ninguna información de identificación personal.", + "p5": "3. Direcciones de correo electrónico: Recopilamos las direcciones de correo electrónico que usted proporciona al registrarse en nuestro sitio web o al actualizar su información de registro. Utilizamos estas direcciones de correo electrónico para enviarle información relacionada con su cuenta, como confirmaciones de registro, notificaciones de cambios en los términos o políticas, y actualizaciones de seguridad.", + "p6": "4. Nombres de usuario y contraseñas: Recopilamos los nombres de usuario y las contraseñas que usted elige al registrar una cuenta en nuestro sitio web. Estas credenciales se utilizan para autenticar su acceso a su cuenta y para proteger su información personal.", + "h2": "Uso de la Información Personal", + "p7": "Utilizamos la información personal que recopilamos para los siguientes fines:", + "p8": "1. Brindar y mejorar nuestros servicios: Utilizamos su información personal para brindarle los servicios solicitados y mejorar su experiencia en nuestro sitio web. Esto incluye personalizar el contenido y las recomendaciones, proporcionar soporte técnico, y analizar el rendimiento y la eficacia de nuestro sitio web.", + "p9": "2. Comunicaciones: Podemos utilizar su dirección de correo electrónico para enviarle comunicaciones relacionadas con su cuenta, como confirmaciones de registro, notificaciones de cambios en los términos o políticas, actualizaciones de seguridad y otras actualizaciones importantes.", + "h3": "Protección de la Información Personal", + "p10": "Tomamos medidas razonables para proteger la información personal que recopilamos y almacenamos. Utilizamos medidas de seguridad técnicas, administrativas y físicas para proteger su información contra el acceso no autorizado, la divulgación, la alteración o la destrucción.", + "h4": "Divulgación de la Información Personal a Terceros", + "p11": "No vendemos, intercambiamos ni transferimos su información personal a terceros sin su consentimiento, excepto en los siguientes casos:", + "p12": "- Proveedores de servicios: Podemos compartir su información personal con proveedores de servicios que realizan funciones en nuestro nombre, como el alojamiento del sitio web, el procesamiento de pagos y el análisis de datos. Estos proveedores de servicios tienen acceso a su información personal solo en la medida necesaria para realizar sus funciones y están obligados a no divulgar ni utilizar la información con ningún otro fin.", + "p13": "- Cumplimiento legal: Podemos divulgar su información personal si creemos de buena fe que dicha divulgación es necesaria para cumplir con una obligación legal, proteger sus derechos o seguridad, investigar fraudes o responder a una solicitud legal.", + "h5": "Sus Derechos y Opciones", + "p14": "Usted tiene ciertos derechos y opciones con respecto a su información personal:", + "p15": "- Acceso y actualización: Usted puede acceder y actualizar cierta información personal proporcionada a través de su cuenta en nuestro sitio web.", + "p16": "- Eliminación de datos: Usted puede solicitar la eliminación de su información personal de nuestros registros, sujeto a cualquier requisito legal o contractual que podamos tener.", + "p17": "- Cookies: Puede ajustar la configuración de su navegador para rechazar cookies o para indicar cuándo se envía una cookie. Sin embargo, tenga en cuenta que deshabilitar las cookies puede afectar el funcionamiento de nuestro sitio web.", + "h6": "Uso incorrecto de plataformas de terceros con el fin de violar nuestra política de devolución", + "p18": "Este tipo de acciones conllevará a la expulsión del usuario de nuestro sitio sin ningún tipo de devolución.", + "h7": "Cambios a esta Política de Privacidad", + "p19": "Nos reservamos el derecho de actualizar esta Política de Privacidad en cualquier momento. Le recomendamos que revise periódicamente esta página para conocer los cambios. La fecha de entrada en vigencia de la política se indicará en la parte superior de la página.", + "h8": "Contáctanos", + "p20": "Si tiene alguna pregunta o inquietud sobre esta Política de Privacidad, puede contactarnos a través de la siguiente información de contacto:", + "updated": "Fecha de actualización: 23-05-2023" + }, + "terms": { + "title": "Términos y condiciones", + "h1": "IMPORTANTE", + "p1": "Por favor, tómese un momento para leer los términos y condiciones detallados debajo. Si está de acuerdo con ellos, entonces podrá ingresar en nuestro sitio.", + "h2": "ACEPTACIÓN DE LOS TÉRMINOS DE USO Y CONDICIONES", + "p2": "UltimoWoW es un proyecto sin ánimo de lucro desarrollado con la finalidad de simular versiones desactualizadas del servidor con fines únicamente educativos. Los Servicios ofrecidos por UltimoWoW no apoyan ni proveerán modificación de ningún tipo para con el servidor o sus ficheros, dicho esto, el usuario al hacer uso de este sitio o cualquier servicio perteneciente o derivado de la Administración, acepta hacerse responsable de seguir y cumplir con el contrato de licencia para usuarios finales (EULA) del servidor.", + "p3": "UltimoWoW no provee ni se responsabiliza por la distribución de ningún cliente del servidor o fuente externa que lo contenga. Los enlaces de descarga para el cliente ofrecidos por este sitio o cualquier medio bajo su responsabilidad, apuntarán siempre a dichas fuentes externas, las cuales, a la fecha no pertenecen ni poseen relación alguna con esta administración. No haciéndose UltimoWoW de esta manera, y bajo ningún concepto, responsable sobre aspecto alguno sobre dicha fuente, dígase: calidad, rendimiento, garantías o cualquiera fuese o no, característica determinante a su fin.", + "p4": "Al acceder, navegar o usar este sitio de Internet y en adelante (el “Sitio”), propiedad de la administración UltimoWoW en adelante (la “Administración”), el usuario admite haber leído y entendido los presentes términos y condiciones de uso, en adelante (“Términos y Condiciones”) y está de acuerdo en acatar los mismos y cumplir con todas las normas, leyes y reglamentos aplicables que hagan parte de la legislación vigente en su lugar de residencia, o a las que se sujete indistintamente. Además, cuando el usuario utilice cualquier servicio suministrado o referenciado en el Sitio, (siempre y cuando éste resida bajo responsabilidad o propiedad de la Administración) estará sujeto a las reglas, guías, políticas, términos y condiciones aplicables a dichos servicios.", + "p5": "Este Sitio es controlado y desarrollado por la Administración, localizable a través de sus plataformas de Discord.", + "p6": "La Administración no es responsable de que el material en este Sitio sea apropiado o esté disponible para su uso en otros lugares, estando prohibido su acceso desde territorios donde su contenido sea ilegal. Aquellos que decidan acceder a este Sitio desde otros lugares lo harán bajo su propia iniciativa, y es su responsabilidad el sujetarse a las leyes locales que sean aplicables.", + "p7": "Estos Términos y Condiciones están sujetos a cambios a discreción, sin previo aviso y en cualquier momento, bajo la sola voluntad de UltimoWoW, y partiendo de la fecha de publicación de la modificación de los mismos en este Sitio, todas las operaciones celebradas entre la Administración y el usuario se regirán por el documento modificado.", + "h3": "NUESTRO SERVICIO: USO, DISTRIBUCIÓN Y DESCARGO DE RESPONSABILIDADES", + "p8": "De conformidad con las legislaciones bajo las cuales la Administración se acate, el material contenido en este Sitio o cualquier otro que se encontrase bajo su responsabilidad o tutela y en adelante, (los “Servicios” o el “Servicio”), incluyendo sin limitación, toda imagen, links, logotipo, diseño, insignia, marca, fotografía, sonido, texto, mensaje, herramienta, software, tecnología, producto, archivo, información, dato, demostración, muestra, material promocional, obra audiovisual u obra multimedia, y cualquiera sea otro elemento o forma de expresión (de forma colectiva y en adelante, (los \"Materiales\"), son suministrados según nuestro leal saber y entender, sin embargo, no es posible descartar errores de contenido o del material, razón por la cual la Administración no asume responsabilidad por la calidad, veracidad o exactitud, de la información publicada ni por las omisiones, errores o discrepancias que pudiesen encontrarse en la información publicada o servicio brindado. ", + "p9": "Respecto a la información publicada en los Servicios, la Administración no confiere garantías de ningún tipo, expresas ni implícitas, excluyendo, más no limitado a:", + "p10": "- Garantías de comerciabilidad o adecuación para un propósito particular.", + "p11": "- Estabilidad ininterrumpida del Servicio.", + "p12": "- Existencia de errores o virus, así como sobre su seguridad.", + "p13": "- Exactitud, confiabilidad, calificación o certificación para su descarga.", + "p14": "La Administración no se hace responsable sobre el uso que el usuario haga de los contenidos incluidos en los Servicios, ni de las decisiones que tome respecto a éstos. La información respecto a los productos y servicios de UltimoWoW, incluida en sus Servicios es brindada con fines edcuativos no comerciales y no constituye oferta de venta para sus usuarios.", + "p15": "UltimoWoW se reserva el derecho de a discreción:", + "p16": "- Corregir cualquier error, omisión o inexactitud en los datos brindados.", + "p17": "- Cambiar o actualizar, descontinuar o eliminar la información contenida en los Servicios en cualquier momento y sin previo aviso.", + "p18": "- Así como también se exime de responsabilidad sobre lo que refiere a la puntualidad, falta de almacenamiento, inexactitud o entrega incorrecta de cualquier información o dato de los que “normalmente” proporcione, ya sea temporal o permanentemente.", + "h4": "RESPONSABILIDADES Y OBLIGACIONES DE REGISTRO Y CONTRASEÑAS", + "p19": "El usufructo de las principales funciones fundamentales y objetivas del Servicio estará siempre determinado y sujeto a la existencia de un registro personal e intransferible (dígase cuenta de usuario). La Administración le exhorta a proporcionar información veraz y comprobable según fuese la misma solicitada. Más allá de un carácter intrusivo, dicha información se haría utilizar estricta y discretamente en aras de posibilitar a futuro, una resolución por parte de la Administración, de alguna situación extraordinaria que surgiese por descuidos de parte del usuario, intentando así dictar la misma en la forma menos perjudicial posible para con este. ", + "p20": "Pertenece completa y estrictamente, y recae sobre el usuario la responsabilidad de mantener confidenciales y de forma segura las contraseñas establecidas para con el Servicio. Así como de las acciones a través del uso de su registro que pudiesen estar estas bajo autorización o no indistintamente por parte del usuario. Queda así también bajo responsabilidad del usuario, la notificación inmediata a la Administración si éste notase alguna actividad sospechosa, uso no autorizado o registro no concebido en el que figurase su propia cuenta como objeto de manipulación, o violación.", + "p21": "Queda terminantemente prohibido el intercambio, comercio, compra-venta y cualquier actividad similar de cualquier forma y bajo cualquier concepto donde figurase e involucrase el conocimiento por parte de cualquiera persona ajena al usuario; de sus credenciales de acceso al Servicio. Violar dichas prohibiciones podría hacer incurrir al usuario en una falta grave, la cual podría sancionarse con penalizaciones de magnitud determinada por la Administración a su juicio y a discreción, la cual en ningún caso quedaría exenta de dicha penalización mediante alegato de uso por parte de terceros y en general bajo ninguna justificación.", + "p22": "Los personajes del reino que hubiesen sido borrados y alcanzados estos, el límite máximo de tiempo (on-hold) para recuperación, establecido por la Administración, desaparecerán permanentemente, claudicando con ellos la posibilidad de restauración o asistencia por parte de la Administración en estos casos, independientemente y descartando por completo la voluntad del usuario para con tal acción en dicho momento.", + "h5": "HACER TRAMPA", + "p23": "Se entiende como trampa cualquier acto fuera y dentro del servidor, que intente alterar o de hecho altere e interfiera con las reglas o con el comportamiento normal del servidor. Así como intentar o de hecho aventajarse sobre otros jugadores. Entre ello, a título meramente enunciativo y sin ánimo limitativo, cualquiera de los siguientes comportamientos, ya sea en su propio nombre o por cuenta de terceros será considerado como tal:", + "p24": "- Acceder a los Servicios de manera no autorizada (incluyendo el uso de software modificado o malicioso).", + "p25": "- Utilizar varias cuentas a la vez en un mismo reino de una forma en la que controlar varios personajes al unísono y sobre el mismo reino, suponga una desventaja de cualquier índole para otros usuarios con respecto infractor.", + "p26": "- Utilizar cualquier técnica o software para alterar o manipular las variables preestablecidas por el servidor y la Administración.", + "p27": "Se prohíbe terminantemente hacer trampas y la Administración se reserva el derecho de denegar a cualquier usuario el acceso al Servicio, siempre y cuando hubiere incurrido o fuese objeto de una falta de este tipo ya fuese directa e indirectamente.", + "h6": "COMPRAS, RECLAMACIONES, REEMBOLSOS Y GARANTÍAS", + "p28": "UltimoWoW no representa ni constituye entidad remesadora ni de servicios financieros de ninguna índole y en consecuencia no posee control o responsabilidad alguna sobre el origen de aquellos fondos utilizados para realizar compras hacia su comunidad. Así como tampoco se responsabiliza por los riesgos que el usuario tomase bajo su propia voluntad, a la hora de ejecutar operaciones financieras de cualquier tipo.", + "p29": "Las compras: serán consideradas siempre de fe voluntaria y en ningún caso, obligación de ningún tipo para ningún usuario. Nótese además que quedan terminantemente prohibidos las compras por parte de personas naturales menores de 18 años o dígase en cualquier caso aquellas personas que no alcanzaran aún al amparo de las entidades legales locales y pertinentes que le competan, su mayoría de edad.", + "p30": "El Servicio: en cualquier caso, no requiere ningún tipo de compra para un uso y disfrute total y a plenitud. Dicho esto, el usuario contará con un canal de comunicación oficial vía email contacto@ultimowow.com con el objetivo de notificar a la Administración de cualquier error cometido por cualquiera de las partes, en aras de emitir y hacer efectiva justa resolución", + "p31": "La Administración: garantiza y se compromete en brindar al comprador toda información que requiriese sobre las formas o métodos de compra vigentes para con la comunidad. Así como aclarar cualquier duda que pudiese surgir sobre los pasos o procesos establecidos de las mismas, siempre y cuando dicha información resida dentro de los límites que competan al comprador y posea un propósito únicamente informativo.", + "p32": "Tomado en cuenta lo anterior, el comprador cuenta con garantías de reembolso monetario y de servicios, atendiendo a aspectos y condiciones expuestos a continuación.", + "h7": "Monetarios:", + "p33": "Tomando en cuenta el carácter que posee cualquier transacción monetaria hacia las arcas de la comunidad, la Administración se compromete a reembolsar (libre de costos por transacción, a consideración de la misma), de forma total o parcial, en definitiva, colegiada conjuntamente entre ambas partes, aquellas compras donde no intencionalmente, el usuario quedase bajo la inconveniencia a la hora de realizar la misma, de errores por su parte en la cuantía del monto total a transferir. Siendo dicho error en todos los casos veraz y de comprobable naturaleza a consideración de la administración.", + "p34": "Tomando en cuenta que los servicios adquiridos se reciben de forma inmediata y no constituyen, determinan, pactan ni modifican plazo alguno para su uso. Así como tampoco para el usufructo del servicio y sus funcionalidades los cuales, recalcado sea de paso, se consideran completamente gratuitos, de carácter educativo y carecen de plazos de admisión y vencimiento.", + "p35": "La Administración no garantiza ni proporcionará en ningún caso ni bajo ningún concepto o circunstancia, reembolso alguno sobre compras o cualquier bien en general transferido a la comunidad. Nótense y háganse aclaratorios lo siguientes casos:", + "p36": "- A usuarios cuyas cuentas hayan sido sancionadas temporal o permanentemente por incurrir en alguna falta expuesta en cualquiera de sus Términos y Condiciones.", + "p37": "- A usuarios que hubiesen tomado la decisión de no continuar (parcial o temporalmente) haciendo uso de cualquiera de los servicios prestados por La Administración.", + "p38": "En ninguno de estos casos la Administración presentará completa ni parcialmente traza alguna de ninguno de sus registros monetarios o de cualquier tipo para fines resolutorios.", + "p39": "Igualmente, el usuario dispone de las respectivas vías y canales, dígase dentro de los foros del Servicio, o servidor de Discord para presentar una apelación formal ante un administrador y ser así evaluado el caso para posterior resolución. La Administración se reserva el derecho de evaluar más no garantizar y a discreción, reembolsos en aquellos casos donde después de estudiado y conciliado, fuese considerado por la misma, justo y extraordinario.", + "h8": "De servicios:", + "p40": "La Administración le garantiza la integridad y funcionalidad de todos los artículos comprados en su tienda. En todo caso, ésta le proveerá un término de 48 horas posterior a su compra para solicitar reemplazos por artículos o servicios de igual valor, o también y a solicitud, la devolución íntegra de los servicios utilizados en aquellos casos donde se encontrarse dicho artículo o servicio roto o inutilizable, o hubiere sido comprado o elegido por error, todo esto siempre y después de efectuado un análisis pertinente por parte de un administrador, y de demostradas pruebas auténticas y concluyentes por parte del usuario a fines con el caso.", + "p41": "Así como también la Administración garantizará la restauración del servicio por problemas técnicos y puntuales, entre el Servicio y las plataformas de pago siempre ajenos al comprador, no fuesen entregados dichos servicios de forma automática e inmediata a nombre del mismo. ", + "h9": "POLÍTICA DE PRIVACIDAD", + "p42": "El Servicio y la Administración recopilan información referente al usuario tales como dirección de correo electrónico, nombre, contraseña, idioma y zona horaria, con el fin de brindarle una mejor optimización cada vez a sus servicios, utilizando esta información para acomodar las funcionalidades a un mejor rendimiento a fin con el usuario y sus requerimientos. Dicha información también podrá ser usada para mantener al usuario mediante canales de comunicaciones independientes y no referentes al Servicio, informando sobre noticias importantes, actualizaciones, problemas técnicos o cualquier otra información de tal índole que considerase la Administración relevante a los intereses del usuario. ", + "p43": "La Administración y el Servicio se comprometen a salvaguardar la confidencialidad sobre tales datos, así como a garantizar la NO divulgación de estos, exceptuando los casos donde las leyes vigentes que rigiesen sobre la Administración lo consideraran necesario y mandatorio por motivos no referentes a UltimoWoW. " + }, + "refund": { + "title": "Política de reembolso", + "h1": "NUESTRO SERVICIO", + "p1": "Todos nuestros servicios son de entrega inmediata y se reciben tal cual se encuentran descritos.", + "h2": "NUESTRA RESPONSABILIDAD", + "p2": "Garantizamos el funcionamiento, tiempo de entrega y descripción de los servicios brindados por nuestro sitio.", + "p3": "Es importante que el usuario comprenda que lo que adquiere en el sitio son servicios que se reciben de forma inmediata.", + "p4": "No adquiere tiempo de uso de los servicios, ni beneficio alguno, ni inmunidad.", + "p5": "Todo caso avalado por nuestra política de devolución será tratado con el reinicio o corrección del servicio y posterior revisión garantizando el funcionamiento correcto del servicio reiniciado o corregido.", + "h3": "TIEMPO DE NOTIFICACIÓN", + "p6": "Cualquier error o problema de nuestros servicios debe ser notificado a la administración en un período máximo de 48 horas desde la entrega del servicio.", + "p7": "Pasado este período de tiempo, el usuario ya no puede solicitar ningún tipo de devolución.", + "p8": "Contacto: contacto@ultimowow.com.", + "h4": "COBERTURA", + "p9": "Esta política de devolución cubre:", + "p10": "- Adquisición del servicio incorrecto por una mala selección del usuario.", + "p11": "- Errores ocasionados por el sitio web que hayan impedido la entrega del servicio.", + "p12": "- Errores ocasionados por plataformas de terceros que hayan impedido la entrega del servicio.", + "p13": "Esta política de devolución NO cubre, bajo ninguna circunstancia:", + "p14": "- Arrepentimientos.", + "p15": "- Errores en el uso del servicio realizados por el usuario.", + "p16": "- Desconocimiento de nuestra política de devolución.", + "p17": "- Uso incorrecto de plataformas de terceros con el fin de violar nuestra política de devolución.", + "p18": "- Expulsión de nuestro sitio por incumplimiento de nuestros términos y normas.", + "h5": "Solicitud de reembolso hecha a través de la plataforma de pago.", + "p19": "Pedir un reembolso por razones avaladas en esta política de devolución procederá a un reembolso de nuestra parte con la correspondiente cancelación del servicio adquirido.", + "p20": "Pedir un reembolso por razones no avaladas en esta política de devolución como:", + "p21": "- La cuenta ha sido sancionada.", + "p22": "- La persona ya no usa el servicio e intenta solicitar un reembolso posterior a las 48 hs del momento de la adquisición.", + "p23": "- Abuso de herramientas disponibles alegando razones que falten a la verdad respecto del servicio entregado.", + "p24": "No aplican para devolución y puede conllevar a la expulsión permanente del sitio por falta a nuestros términos y un uso inadecuado de las plataformas de pago disponibles.", + "h6": "Arrepentimientos", + "p25": "Ningún tipo de arrepentimiento posterior a la entrega de un servicio aplica para devolución.", + "h7": "Errores en el uso del servicio realizados por el usuario", + "p26": "Errores en el uso de los servicios, ocasionados por el usuario, que no tienen relación con ningún tipo de falla en el servicio entregado no aplica para devolución.", + "p27": "Cualquier error de usuario ocasionado por no leer la descripción de un servicio no aplica para devolución.", + "p28": "Una vez que el servicio se encuentra entregado, el uso del mismo queda a responsabilidad del usuario.", + "h8": "Desconocimiento de nuestra política de devolución", + "p29": "El desconocimiento por parte del usuario de nuestra política de devolución no exime al usuario de su cumplimiento.", + "h9": "Uso incorrecto de plataformas de terceros con el fin de violar nuestra política de devolución", + "p30": "Este tipo de acciones conllevará a la expulsión del usuario de nuestro sitio sin ningún tipo de devolución.", + "h10": "Expulsión de nuestro sitio por incumplimiento de nuestros términos y normas", + "p31": "Ninguna adquisición de nuestros servicios otorga ningún tipo de inmunidad.", + "p32": "La expulsión de un usuario de nuestro sitio no aplica a ningún tipo de devolución.", + "p33": "El cumplimiento de nuestros términos y normas queda a exclusiva responsabilidad del usuario y cualquier expulsión que resulte del incumplimiento de los mismos no califica a solicitar devolución de los servicios ya entregados y disfrutados.", + "h11": "Cambios a esta Política de Reembolso", + "p34": "Nos reservamos el derecho de actualizar esta Política de Reembolso en cualquier momento. Le recomendamos que revise periódicamente esta página para conocer los cambios.", + "h12": "Contáctanos", + "p35": "Si tiene alguna pregunta o inquietud sobre esta Política de Reembolso, puede contactarnos a través de la siguiente información de contacto:", + "updated": "Fecha de actualización: 25-05-2023" + }, + "legalNotice": { + "title": "Aviso legal", + "p1": "El sitio web \"UltimoWoW.com\" y sus subdominios (en adelante, \"el sitio web\") se ofrecen únicamente con fines informativos y de entretenimiento. UltimoWoW no se hace responsable del uso que los usuarios hagan del sitio web. Aunque se procura que se dé un uso correcto, UltimoWoW no asume responsabilidad por las acciones, decisiones o consecuencias derivadas del uso del sitio web. Los usuarios son responsables de verificar la precisión, integridad y utilidad de la información proporcionada, así como de cumplir con las leyes y regulaciones aplicables al utilizar el contenido del sitio web.", + "p2": "Enlaces a terceros: El sitio web puede contener enlaces a sitios web de terceros. Estos enlaces se proporcionan únicamente para tu conveniencia y no implican el respaldo o afiliación de UltimoWoW con dichos sitios web. UltimoWoW no se hace responsable del contenido o las prácticas de privacidad de estos sitios web de terceros.", + "p3": "Privacidad y Cookies: La recopilación y uso de tus datos personales se rigen por nuestra Política de Privacidad y el uso de cookies se rige por nuestra Declaración de Cookies. Al utilizar el sitio web, aceptas nuestras prácticas descritas en dichas políticas.", + "p4": "Derechos de autor: Los usuarios del sitio web deben respetar los derechos de autor y no publicar contenido que infrinja los derechos de propiedad intelectual de terceros. UltimoWoW se compromete a proteger los derechos de autor y cumplir con las leyes aplicables. Si encuentras contenido infractor, contáctanos utilizando el mecanismo de reclamación de infracción descrito a continuación.", + "p5": "Mecanismo de reclamación de infracción: Si crees que tu trabajo ha sido utilizado de manera no autorizada en el sitio web, puedes presentar una reclamación por infracción de derechos de autor proporcionando la información requerida. Contáctanos utilizando los datos de contacto a continuación.", + "contactTitle": "Contacto" + }, + "contact": { + "title": "Contáctanos", + "p1": "¡Gracias por tu interés en contactar con nosotros!", + "p2": "Si tienes alguna pregunta, consulta o comentario, estaremos encantados de ayudarte. Por favor, envía un correo electrónico a la siguiente dirección:", + "p3": "Error 404 es la empresa que representa el servicio de UltimoWoW.", + "p4": "Nos esforzamos por responder a todos los mensajes en un plazo de 48 horas hábiles.", + "p5": "Asegúrate de incluir la información relevante en tu correo para que podamos brindarte una respuesta precisa y oportuna.", + "p6": "En Error 404, valoramos tus comentarios y opiniones. Tu satisfacción es nuestra prioridad y nos esforzamos por brindarte la mejor experiencia posible en UltimoWoW.", + "p7": "¡Esperamos tener noticias tuyas pronto!", + "p8": "Atentamente, el equipo de Error 404." + } + }, + "Misc": { + "home": { + "recruitFriend": "¡RECLUTA A UN AMIGO!", + "labelTime": "Hora", + "introP1": "{realm} es una comunidad enfocada en usuarios de habla hispana, especialmente dirigida al público español y latino.", + "introP2": "Atraemos a usuarios apasionados tanto por el PvE como por el PvP, y ofrecemos una amplia variedad de contenido.", + "introP3": "Nuestro objetivo principal es mantener una comunidad de alto nivel, brindando un ambiente agradable para que todos los miembros, nuevos y veteranos, encuentren aquí un lugar donde puedan vivir momentos inigualables.", + "introP4": "¡Únete y disfruta de una experiencia única con miles de usuarios!", + "newsHeading": "NOTICIAS", + "noNews": "No hay noticias disponibles en este momento.", + "newsLinkLabel": "Enlace:", + "here": "aquí", + "showingLatest": "* Mostrando las últimas 50 noticias" + }, + "realm": { + "charactersHeading": "Personajes", + "realmHeading": "Reino" + }, + "downloadAddons": { + "title": "Descarga de addons", + "recommended": "Addons recomendados", + "intro1": "Los addons son complementos opcionales que mejoran y personalizan tu experiencia de juego.", + "intro2": "Descarga los que quieras desde su página oficial (elige la versión compatible con WotLK 3.4.3).", + "howToInstall": "Cómo instalarlos", + "step1": "1) Descarga el addon y descomprime el archivo .zip.", + "step2": "2) Copia la carpeta resultante dentro de Interface/AddOns (en la carpeta de tu cliente).", + "step3": "3) Inicia el juego y, en la pantalla de selección de personaje, pulsa Complementos para activarlos.", + "download": "Descargar", + "descDbm": "Avisos y temporizadores de habilidades de jefes en mazmorras y bandas.", + "descDetails": "Medidor de daño, curación y amenaza con gráficas detalladas.", + "descAtlasLoot": "Consulta el botín de jefes de mazmorras y bandas dentro del juego.", + "descQuestie": "Muestra objetivos y ubicaciones de misiones en el mapa y el minimapa.", + "descBagnon": "Unifica todas tus bolsas y el banco en una sola ventana con búsqueda.", + "descBartender4": "Personaliza por completo tus barras de acción.", + "descAuctioneer": "Herramientas avanzadas para la casa de subastas.", + "descPawn": "Compara equipo y te indica qué objeto es una mejora para tu personaje." + }, + "twofaLogin": { + "pageTitle": "Verificación en 2 pasos", + "info": "Información", + "backToAccount": "Regresar a mi cuenta", + "back": "Regresar", + "previewAlt": "Vista previa autenticador", + "p1": "2FA son las siglas de \"Two Factor Authentication\", o verificación en dos pasos.", + "p2": "Es un método que añade una capa adicional de seguridad al proceso de inicio de sesión.", + "p3": "En lugar de simplemente ingresar tu nombre de usuario y contraseña, 2FA requiere un segundo paso de verificación, aumentando así la protección de tu cuenta.", + "p4": "Una vez activado, luego de ingresar usuario y contraseña, aparecerá una ventana (Imagen derecha) que te pedirá el código de autenticación generado por la aplicación.", + "backupCodes": "Códigos de respaldo", + "p5": "Al activar 2FA, se te proporcionarán códigos de respaldo únicos.", + "p6": "Estos códigos son útiles en caso de que pierdas acceso a tu aplicación de autenticación.", + "p7": "Cada código de respaldo puede usarse una sola vez.", + "p8": "Guárdalos en un lugar seguro, ya que te permitirán acceder a tu cuenta en el sitio web si no puedes usar la aplicación de autenticación.", + "requestToken": "Si aún no tienes Token de seguridad, puedes solicitarlo aquí.", + "note": "NOTA", + "noteText": "Utiliza una aplicación de autenticación para iniciar sesión en el juego una vez que lo tengas activado." + }, + "help": { + "title": "Ayuda", + "subtitle": "Guía de asistencia", + "intro1": "En esta guía podrás saber qué pasos seguir para obtener asistencia adecuada dependiendo del tipo de problema que hayas encontrado en nuestro servidor.", + "intro2": "Ofrecemos un conjunto de problemas comunes, qué medios utilizar para cada caso y una explicación de cada medio de contacto.", + "intro3": "Los diferentes medios para cada problema se listan desde el más ideal hasta la última opción.", + "clientTitle": "Con el cliente", + "clientText": "Problemas que impiden arrancar el cliente, conectar al servidor o errores que provocan el cierre abrupto del cliente.", + "mediaAre": "Los medios son:", + "mediaForos": "- Foros", + "mediaDiscord": "- Discord", + "mediaTicket": "- Ticket", + "serverErrorsTitle": "Con errores del servidor", + "serverErrorsText": "Problemas relacionados a errores que deben ser reparados por nuestro equipo de reparación para mejorar el servidor.", + "characterTitle": "Con el personaje", + "characterText": "Problemas relacionados a errores que puedan afectar al personaje, habilidades, hechizos, misiones, etc.", + "otherPlayerTitle": "Con otro jugador", + "otherPlayerText1": "Problemas relacionados a otros usuarios cometiendo faltas a las normas del servidor.", + "otherPlayerText2": "Este tipo de problemas requieren de una denuncia con las pruebas correspondientes de lo que haya sucedido.", + "accountBlocksTitle": "Con bloqueos de cuenta", + "accountBlocksText": "Problemas relacionados a bloqueos de cuenta realizados por el equipo de {realm}.", + "websiteTitle": "Con la página web", + "websiteText": "Problemas relacionados a errores, fallas o sugerencias respecto de este sitio web.", + "mailTo": "- Correo a", + "pdTitle": "Con PD", + "pdText": "Problemas relacionados a PD o PV.", + "contactMeans": "Medios de contacto", + "ticketTitle": "Ticket", + "ticket1": "Para colocar un ticket, debes hacer click al signo de interrogación rojo en la parte inferior derecha de la interfaz del cliente (a la izquierda del llavero del personaje).", + "ticket2": "Al hacerle click, aparecerá una ventana en el medio de la pantalla.", + "ticket3": "En dicha ventana, hacer click al primer botón en la esquina inferior izquierda llamado 'Hablar con un MJ'", + "ticket4": "Aparecerá una ventana con un texto informativo y debajo en medio, un botón llamado 'Abrir una consulta'.", + "ticket5": "Al darle click al botón, aparecerá un campo de texto en el que puedes describir tu problema", + "ticket6": "Cuando hayas finalizado haz click en el botón en el primer botón en la esquina inferior derecha llamado 'Enviar'.", + "ticket7": "El ticket ya ha sido creado y está pendiente de respuesta de un miembro del equipo.", + "discordTitle": "Discord", + "discord1": "Discord es una plataforma de chat y comunicación por voz que puede descargarse aquí.", + "discord2": "Para entrar en el servidor de Discord de nuestro servidor, haz click aquí.", + "discord3": "Una vez que seas miembro de nuestro Discord podrás pedir ayuda en el canal 'Asistencia' o enviar un mensaje directo a cualquier miembro del equipo solicitando ayuda.", + "forosTitle": "Foros", + "foros1": "Los foros son una gran herramienta en donde no sólo puede ayudarte el equipo de {realm} sino que además otros jugadores pueden asistirte si conocen cómo resolver el problema que tengas.", + "foros2": "Para solicitar ayuda por este medio, debes tener un usuario con el cual poder conectar y abrir un nuevo tema en el foro adecuado.", + "foros3": "Puedes visitar nuestros foros aquí.", + "emailTitle": "Correo electrónico", + "email1": "El servidor tiene diferentes direcciones de correo dedicados a diferentes temas del servidor.", + "email2": "Depende cual sea tu problema, usa el adecuado para enviarnos un mensaje de correo." + } + }, + "Points": { + "dpoints": { + "title": "Adquirir PD" + }, + "dpointsSuccess": { + "title": "Adquirir PD", + "paidOk": "¡Pago completado! Tus PD ya fueron acreditados a tu cuenta.", + "alreadyPaid": "Este pago ya había sido procesado. Tus PD están acreditados.", + "error": "No pudimos confirmar tu pago. Si se realizó el cargo, contacta con soporte.", + "backToAccount": "← Regresar a mi cuenta" + }, + "transferDp": { + "title": "Transferir PD", + "intro1": "La herramienta Transferir PD permite transferir PD desde tu cuenta a cualquier otra cuenta.", + "intro2": "Al usar el botón TRANSFERIR PD se transferirá la cantidad que hayas escogido desde tu cuenta a la cuenta del personaje que hayas indicado.", + "tokenHelp": "Si aún no tienes Token de seguridad, puedes solicitarlo aquí.", + "note": "NOTA", + "noteText": "Por favor, asegúrate de haber escrito el nombre del personaje correcto ya que esta acción no es reversible una vez realizada.", + "noPd": "No tienes PD", + "confirm": "Vas a transferir {n} PD al personaje \"{character}\".\nEsta acción no es reversible. ¿Deseas continuar?", + "success": "Has transferido {n} PD al personaje \"{character}\".", + "available": "Tienes {balance} PD disponibles", + "characterPlaceholder": "Nombre del personaje de destino", + "amountPlaceholder": "Cantidad de PD", + "tokenPlaceholder": "Token de seguridad", + "transferring": "Transfiriendo…", + "transferButton": "TRANSFERIR PD", + "errors": { + "missingFields": "Rellena el personaje de destino, la cantidad y el token de seguridad.", + "invalidAmount": "La cantidad debe ser un número entero mayor que 0.", + "invalidToken": "El token de seguridad no es válido.", + "characterNotFound": "No existe ningún personaje con ese nombre.", + "sameAccount": "No puedes transferirte PD a tu propia cuenta.", + "insufficientFunds": "No tienes suficientes PD para realizar esta transferencia.", + "notAuthenticated": "Tu sesión ha expirado. Inicia sesión de nuevo.", + "generic": "No se pudo completar la transferencia. Inténtalo de nuevo." + } + }, + "trade": { + "title": "Comercio de PD", + "intro1": "La herramienta Comercio de PD permite comprar o vender PD a cambio de oro de una forma segura.", + "intro2": "El sistema permite crear códigos de 1 solo uso que valdrán X cantidad de PD a cambio de X cantidad de oro.", + "intro3": "Los vendedores disponen de la sección VENTA para crear el código y los compradores disponen de la sección COMPRA para canjear dicho código.", + "sellTitle": "Venta", + "sell1": "1) Decide cuánto valdrá el código en PD.", + "sell2": "2) Decide por cuánto oro se podrá canjear.", + "sell3": "3) Escoge a qué personaje de la cuenta se enviará el oro cuando el código sea canjeado.", + "sell4": "4) Completa los datos con la contraseña y Token de Seguridad.", + "sell5": "5) Usa el botón CREAR CÓDIGO.", + "sell6": "6) Un recuadro aparecerá con los datos del Código creado con el ID que se debe usar para enviar a otro jugador.", + "buyTitle": "Compra", + "buy1": "1) Ingresa ID del código que te ha dado otro jugador.", + "buy2": "2) Chequea el valor en PD y costo en oro con el botón CHEQUEAR CÓDIGO.", + "buy3": "3) Escoge de qué personaje de la cuenta se descontará el oro cuando el código sea canjeado.", + "buy4": "4) Completa los datos con la contraseña y Token de Seguridad.", + "buy5": "5) Usa el botón CANJEAR CÓDIGO.", + "buy6": "6) Un recuadro aparecerá con los datos del Código canjeado, PD recibidos y oro retirado del personaje seleccionado.", + "duration": "Cada código tiene una duración de 1 hora.", + "onceRedeemed": "Una vez canjeado el código:", + "redeemed1": "- Los PD serán retirados de la cuenta del creador del código y enviados a quien lo haya canjeado.", + "redeemed2": "- El oro será retirado y enviado por correo al creador.", + "redeemed3": "- La transacción quedará registrada en el Historial de PD y PV.", + "lockNote": "La cuenta de quien canjee el código será bloqueada por 5s como medida de seguridad si el trámite es exitoso.", + "tokenHelp": "Si aún no tienes Token de seguridad, puedes solicitarlo aquí.", + "note": "NOTA", + "noteText": "Por favor, asegúrate de haber escrito todos los datos correctos ya que esta acción no es reversible una vez realizada.", + "sellTab": "VENTA", + "buyTab": "COMPRA", + "noCharacters": "No tienes personajes en esta cuenta.", + "codeCreated": "¡Código creado!", + "sellPointsLabel": "¿Cuánto valdrá el código en PD?", + "sellPointsPlaceholder": "Valor del código en PD", + "sellGoldLabel": "¿Cuánto costará el código en oro?", + "sellGoldPlaceholder": "Valor del código en oro", + "sellCharLabel": "¿A qué personaje se enviará el oro?", + "selectCharacter": "Selecciona un personaje", + "passwordPlaceholder": "Contraseña de tu cuenta", + "tokenPlaceholder": "Token de seguridad", + "creating": "Creando…", + "createButton": "Crear código", + "createdLegend": "Código creado", + "codeIdLabel": "ID del código:", + "createdValue": "Valor: {points} PD por {gold} de oro", + "createdHint": "Envía este ID al comprador. El código caduca en 1 hora.", + "buyCodeLabel": "Ingresa el ID del código de PD", + "buyCodePlaceholder": "Código de PD", + "checkInfo": "Vale {points} PD · Cuesta {gold} de oro", + "buyCharLabel": "¿De qué personaje se cobrará el oro?", + "checkButton": "Chequear código", + "processing": "Procesando…", + "redeemButton": "Canjear código", + "checkResult": "Este código vale {points} PD y cuesta {gold} de oro.", + "redeemConfirm": "Vas a canjear este código. Esta acción no es reversible. ¿Deseas continuar?", + "redeemSuccess": "¡Canje correcto! Recibiste {points} PD y se retiraron {gold} de oro de {character}.", + "errors": { + "missingFields": "Rellena todos los campos.", + "invalidAmount": "Las cantidades deben ser números enteros entre 1 y 99999.", + "characterInvalid": "El personaje seleccionado no es válido.", + "captcha": "Verifica que no eres un robot.", + "wrongPassword": "La contraseña de tu cuenta es incorrecta.", + "invalidToken": "El token de seguridad no es válido.", + "insufficientPoints": "No tienes suficientes PD disponibles para crear este código.", + "codeNotFound": "No existe ningún código con ese ID.", + "codeUnavailable": "El código ya no está disponible (canjeado o expirado).", + "cannotRedeemOwn": "No puedes canjear tu propio código.", + "characterOnline": "El personaje debe estar desconectado para poder cobrar el oro.", + "insufficientGold": "El personaje no tiene suficiente oro.", + "creatorInsufficient": "El creador del código ya no tiene suficientes PD.", + "locked": "Espera unos segundos antes de canjear otro código.", + "deliveryFailed": "No se pudo entregar el oro (servidor de juego no disponible). Inténtalo de nuevo más tarde.", + "notAuthenticated": "Tu sesión ha expirado. Inicia sesión de nuevo.", + "generic": "No se pudo completar la operación. Inténtalo de nuevo." + } + }, + "promo": { + "title": "Código de promoción", + "intro1": "Los Códigos de promoción son palabras con letras y números que se canjean en el formulario de abajo por PD o PV y tienen usos limitados. Cada uno puede dar diferente cantidad de PD/PV.", + "intro2": "Estos códigos son generados por el Equipo de {realm} y pueden aparecer en la página web, Discord, las redes sociales o el servidor.", + "intro3": "Aconsejamos poner atención a las redes sociales y los anuncios del servidor para saber cuándo hay un código disponible.", + "note": "NOTA", + "noteText": "Los códigos son sensibles a mayúsculas y minúsculas por lo que siempre debes escribirlos igual a como aparecen publicados.", + "placeholder": "Escribe tu código de promoción", + "redeeming": "Canjeando…", + "redeemButton": "CANJEAR CÓDIGO", + "rewardPd": "{pd} PD", + "rewardPv": "{pv} PV", + "and": "y", + "rewardDefault": "la recompensa", + "success": "¡Código canjeado! Has recibido {reward}.", + "errors": { + "missingCode": "Escribe un código de promoción.", + "notFound": "El código no existe o ya no está disponible.", + "expired": "Este código ha caducado.", + "exhausted": "Este código ya ha alcanzado su límite de usos.", + "alreadyUsed": "Ya has canjeado este código.", + "notAuthenticated": "Tu sesión ha expirado. Inicia sesión de nuevo.", + "generic": "No se pudo canjear el código. Inténtalo de nuevo." + } + }, + "renameGuild": { + "title": "Renombrar hermandad", + "intro1": "La herramienta Renombrar hermandad te permite cambiar de nombre a una hermandad de la cual seas Maestro de Hermandad.", + "rules": "A la hora de escoger un nuevo nombre, ten en cuenta:", + "rule1": "- La longitud máxima es de 24 caracteres.", + "rule2": "- Los caracteres permitidos son A-Za-z y el espacio.", + "intro2": "Al usar el botón RENOMBRAR HERMANDAD de la hermandad que hayas escogido, se cambiará su nombre al nuevo nombre que hayas ingresado.", + "intro3": "El cambio de nombre de hermandad es instantáneo. Puede ser necesario que los miembros de la hermandad conectados deban volver a conectar para finalmente ver el nuevo nombre.", + "note": "NOTA", + "noteText": "Por favor, asegúrate de haber elegido el nombre correcto ya que esta acción no es reversible una vez realizada.", + "requires": "Requiere {pd}PD", + "noGuilds": "No hay personajes Maestros de hermandad", + "confirm": "¿Estás seguro de renombrar la hermandad seleccionada?", + "success": "¡Hermandad renombrada a \"{newName}\"! Puede que los miembros conectados deban reconectar para verlo.", + "selectGuild": "Selecciona una hermandad", + "newNamePlaceholder": "Nuevo nombre de la hermandad", + "tokenPlaceholder": "Token de seguridad", + "renamed": "HERMANDAD RENOMBRADA", + "renaming": "RENOMBRANDO HERMANDAD", + "renameButton": "RENOMBRAR HERMANDAD", + "errors": { + "missingFields": "Completa todos los campos.", + "invalidName": "El nombre debe tener de 1 a 24 caracteres, solo letras (A-Z, a-z) y espacios.", + "invalidToken": "El token de seguridad no es válido.", + "notGuildMaster": "No eres Maestro de esa hermandad.", + "nameTaken": "Ya existe una hermandad con ese nombre.", + "insufficientPoints": "No tienes suficientes PD (se requieren 1000).", + "soapError": "No se pudo aplicar el cambio (servidor de juego no disponible). Inténtalo más tarde.", + "notAuthenticated": "Tu sesión ha expirado. Inicia sesión de nuevo.", + "generic": "No se pudo renombrar la hermandad. Inténtalo de nuevo." + } + }, + "tabs": { + "info": "Información", + "backToAccount": "Regresar a mi cuenta", + "back": "Regresar", + "whatArePd": "¿Qué son los PD?", + "whatArePdText": "Ofrecemos a nuestros usuarios la oportunidad de obtener niveles que les brindan beneficios exclusivos dentro de nuestra comunidad en línea. Estos beneficios incluyen acceso a herramientas especiales, contenido exclusivo y mejoras significativas para su experiencia en nuestro sitio web. Al realizar una compra, nuestros usuarios reciben PD, una unidad de reconocimiento interna que refleja su compromiso y progreso en nuestra plataforma. Los PD les permiten alcanzar nuevos niveles y desbloquear recompensas exclusivas. Cabe destacar que estos PD son una forma única de valorar y premiar la participación activa de nuestros usuarios en nuestra comunidad.", + "availableLevels": "¿Cuáles son los niveles disponibles?", + "show": "Mostrar", + "hide": "Ocultar", + "level": "Nivel {n}", + "range1": "Desde 0 PD", + "range2": "Hasta 100 PD", + "range3": "Hasta 200 PD", + "range4": "Hasta 300 PD", + "range5": "Hasta 400 PD", + "range6": "Hasta 500 PD", + "range7": "Hasta 600 PD", + "range8": "Hasta 700 PD", + "range9": "Hasta 800 PD", + "range10": "Hasta 900 PD", + "range11": "Hasta 1000 PD", + "range12": "Hasta 5000 PD", + "range13": "Hasta 10000 PD", + "range14": "Más de 10000 PD", + "purchaseMethods": "¿Cuáles son los métodos de compra de PD?", + "purchaseMethodsText": "Los métodos de compra disponibles actualmente son:", + "stripeMethod": "Stripe (tarjeta de crédito/débito, para todos los países).", + "sumupMethod": "SumUp (tarjeta de crédito/débito).", + "howManyPd": "¿Cuántos PD se reciben?", + "howManyPdText": "Por cada {sym}1 recibes 100 PD. La cantidad final se indica antes de confirmar el pago.", + "doubts": "¿Tienes dudas o problemas con una compra?", + "doubtsText1": "No realices una compra hasta estar completamente seguro de que has leído esta información y sabes cómo es el proceso que vayas a escoger.", + "doubtsText2": "Si a pesar de leer este instructivo aún tienes dudas, el equipo de {realm} podrá asesorarte en cualquier momento. Puedes colocar un ticket en el servidor, o contactarnos mediante nuestra plataforma de Discord.", + "mustAccept": "Debes aceptar los Términos y Condiciones y la Política de Reembolso", + "confirmPurchase": "Vas a adquirir {points} PD por {sym}{amount}.\n¿Deseas continuar al pago?", + "rate": "{sym}1 = 100 PD", + "minMax": "Valor mínimo: {sym}1 · Valor máximo por transacción: {sym}200", + "important": "¡Importante!", + "integersOnly": "Introduce sólo valores enteros (sin decimales).", + "example": "Ejemplo: para 200 PD escribe 2.", + "amountLabel": "Cantidad en {currency} a adquirir", + "amountPlaceholder": "Cantidad en {currency}", + "willReceive": "Recibirás {points} PD", + "acceptTerms": " Acepto los Términos y Condiciones y la Política de Reembolso", + "acquireButton": "ADQUIRIR PD", + "redirecting": "Redirigiendo…", + "whatIsStripe": "¿Qué es Stripe?", + "stripeAboutText": "Stripe es una plataforma de pagos en línea segura que procesa tarjetas de crédito y débito de todo el mundo. Tus datos de pago se gestionan directamente en Stripe; {realm} nunca los almacena.

Más información sobre Stripe aquí.", + "howStripe": "¿Cómo adquirir PD a través de Stripe?", + "stripeHowText": "Al ser un sistema auto-gestionado, las adquisiciones son automáticas y en cuestión de minutos tras completar el pago recibirás los PD en tu cuenta.", + "step1": "- Introduce en el campo de más abajo la cantidad que deseas adquirir.", + "stripeStep2": "- Al presionar ADQUIRIR PD, serás redirigido a la pasarela segura de Stripe para completar el pago con tu tarjeta.", + "stripeStep3": "- Una vez que Stripe valide tu pago, tendrás los PD en tu cuenta de forma automática.", + "reminderMin": "Recuerda que la cantidad sólo acepta números enteros y el mínimo posible es {sym}1.", + "wrongExamples": "Ejemplos de valor incorrecto: {sym}5,90 | {sym}22,30 | {sym}53,10", + "rightExamples": "Ejemplos de valor correcto: {sym}6 | {sym}22 | {sym}53", + "whatIsSumup": "¿Qué es SumUp?", + "sumupAboutText": "SumUp es una plataforma de pagos europea que permite pagar de forma rápida y segura con tarjeta de crédito o débito. Tus datos de pago se gestionan directamente en SumUp; {realm} nunca los almacena.

Más información sobre SumUp aquí.", + "howSumup": "¿Cómo adquirir PD a través de SumUp?", + "sumupHowText": "Al ser un sistema auto-gestionado, las adquisiciones son automáticas y tras completar el pago recibirás los PD en tu cuenta.", + "sumupStep2": "- Al presionar ADQUIRIR PD, serás redirigido a la pasarela segura de SumUp para completar el pago con tu tarjeta.", + "sumupStep3": "- Una vez que SumUp valide tu pago, tendrás los PD en tu cuenta de forma automática.", + "checkoutErrors": { + "notConfigured": "Este método de pago aún no está disponible. Por favor, utiliza otro método o inténtalo más tarde.", + "invalidAmount": "La cantidad debe ser un número entero entre 1 y 200.", + "notAuthenticated": "Tu sesión ha expirado. Inicia sesión de nuevo.", + "generic": "No se pudo iniciar el pago. Inténtalo de nuevo." + } + } + }, + "UI": { + "header": { + "home": "INICIO", + "register": "CREAR CUENTA", + "downloads": "DESCARGAS", + "client": "CLIENTE", + "addons": "ADDONS", + "changelog": "CHANGELOG", + "realm": "REINO", + "players": "JUGADORES", + "community": "COMUNIDAD", + "forums": "FOROS", + "wotlkDb": "WOTLK DB", + "videos": "VIDEOS", + "help": "AYUDA", + "myAccount": "MI CUENTA", + "logout": "DESCONECTAR", + "login": "CONECTAR" + }, + "footer": { + "terms": "Términos y Condiciones", + "privacy": "Política de Privacidad", + "refund": "Política de Reembolso", + "cookies": "Declaración de Cookies", + "legal": "Aviso legal", + "contact": "Contáctanos", + "copyright": "© Copyright {realmName}™ {year}. Todos los derechos reservados", + "design": "Diseño: \"{realmName}\" Por Inna Hoover Brown" + }, + "social": { + "followUs": "SÍGUENOS EN" + }, + "realmInfo": { + "ratesTitle": "Rates", + "experience": "Experiencia", + "experienceValue": "x8 modificable con .xp (Con Recluta a un Amigo x16)", + "greenBlueDrop": "Drop de objetos verdes y azules", + "greenBlueDropValue": "x4", + "goldNpc": "Drop de oro en NPCs", + "goldNpcValue": "x2", + "goldQuest": "Drop de oro en misiones", + "goldQuestValue": "x1", + "skills": "Habilidades", + "skillsValue": "x3", + "professions": "Profesiones", + "professionsValue": "x3", + "reputations": "Reputaciones", + "reputationsValue": "x3 (Bonus con Recluta a un amigo)", + "honor": "Honor", + "honorValue": "x3", + "scheduleTitle": "Horarios", + "scheduleNote": "Los siguientes horarios son basados en la hora del reino.", + "dailyQuests": "Misiones diarias", + "dailyQuestsValue": "7 am", + "dailyDungeons": "Reinicio de mazmorras diarias", + "dailyDungeonsValue": "9 am", + "raidReset": "Reinicio de bandas", + "raidResetValue": "9 am (Miércoles)", + "battlegrounds": "Campos de Batalla", + "battlegroundsValue": "10 am", + "arenaPoints": "Reparto de Puntos de Arena", + "arenaPointsValue": "11 am (Viernes)" + }, + "players": { + "updateNotice": "La información de esta página se actualiza 1 vez al día automáticamente", + "charsByClass": "Personajes creados por clase", + "total": "Total:", + "alliances": "Alianzas:", + "hordes": "Hordas:", + "allianceAlt": "Alianza", + "hordeAlt": "Horda", + "totalChars": "Personajes totales:", + "allianceChars": "Personajes alianzas:", + "hordeChars": "Personajes hordas:", + "firstsTitle": "Primeros del Reino - Nivel 80", + "noLevel80": "Aún no hay personajes de nivel 80 registrados.", + "thAchievement": "Logro", + "thCharacter": "Personaje", + "thDate": "Fecha", + "firstOfRealm": "¡Primero del reino!", + "topAchTitle": "Top de logros", + "topAchSub": "Los 10 jugadores con más logros", + "thName": "Nombre", + "thRace": "Raza", + "thClass": "Clase", + "thAchPoints": "Puntos de logros", + "topHonorTitle": "Top de muertes con honor", + "topHonorSub": "Los 10 jugadores con más muertes con honor", + "thTotalKills": "Total de muertes", + "thTodayKills": "Total de muertes hoy" + }, + "recruit": { + "errRequirements": "Aún no cumples los requisitos para esta recompensa.", + "errAlreadyClaimed": "Esta recompensa ya fue reclamada.", + "errInvalidCharacter": "Personaje no válido.", + "errNotFound": "Recompensa no encontrada.", + "errGeneric": "No se pudo reclamar la recompensa. Inténtalo de nuevo.", + "accountRecruited": "Cuenta reclutada:", + "yes": "Sí", + "no": "No", + "friendsRecruited": "Amigos reclutados:", + "friendsAtLevel80": "Amigos reclutados al nivel 80:", + "rewardsClaimed": "Recompensas reclamadas:", + "receiveRewardsOn": "Recibir recompensas en:", + "thFriends": "Amigos reclutados", + "thReward": "Recompensa", + "thStatus": "Estado", + "friendsAtLevel80Row": "{count, plural, one {# amigo al nivel 80} other {# amigos al nivel 80}}", + "claimed": "Reclamado", + "claim": "Reclamar", + "unclaimed": "Sin reclamar", + "availableRewards": "RECOMPENSAS DISPONIBLES", + "recruitToClaim": "Recluta amigos para poder reclamar las recompensas", + "readyToClaim": "Tienes {count, plural, one {# recompensa lista} other {# recompensas listas}} para reclamar" + }, + "clientDownload": { + "torrentTitle": "Descarga por Torrent", + "infoLabel": "Información", + "info1": "- No requiere instalación.", + "info2": "- El realmlist ya está configurado.", + "info3": "- La descarga se gestiona a través de magnet link. Si ya conoces cómo realizar descargas de este tipo, los pasos a seguir son opcionales.", + "requirementsLabel": "Requisitos para la descarga", + "requirementsText": "Se necesitará un programa que gestione descargas por Torrent y un programa que gestione archivos .rar.", + "popupNote": "Adicionalmente, necesitarás que esta página pueda abrir ventanas emergentes.", + "stepByStep": "Paso a paso:", + "stepOptional": "Opcional: Si no tienes Winrar, haz clic en WinRAR e instala el programa.", + "step1": "1) Haz clic en qBittorrent.", + "step2": "2) Descarga la versión adecuada para tu sistema operativo.", + "step3": "3) Ejecuta el archivo descargado y realiza la instalacion del programa.", + "step4": "4) Ejecuta qBitTorrent.", + "step5": "5) Ve a la parte final de esta página y escoge el idioma de tu preferencia.", + "step6": "6) Debajo del idioma, escoge el sistema operativo.", + "step7": "7) Haz clic en Descargar.", + "step8": "8) En la ventana emergente, acepta Abrir qBitTorrent.", + "step9": "9) Espera a que qBitTorrent cargue el archivo correspondiente en la ventana de Enlace magnet.", + "step10": "10) Haz clic en Aceptar.", + "step11": "11) En la ventana de qBitTorrent espera a que la descarga se haya completado.", + "step12": "12) Ingresa en la carpeta de descargas de qBitTorrent (Por defecto Descargas).", + "step13": "13) Haz clic derecho en el archivo .rar y usa la opción Extraer aquí.", + "step14": "14) Ingresa en la carpeta extraída y allí encontrarás el ejecutable para comenzar a jugar.", + "step15": "15) Conecta usando tu cuenta de la web, en el campo email no pongas tu email sino tu nombre de cuenta.", + "languageLabel": "Idioma", + "chooseLanguage": "Elegir idioma", + "clientEses": "Cliente esES", + "clientEsmx": "Cliente esMX", + "clientEnus": "Cliente enUS", + "clientEngb": "Cliente enGB", + "langEses": "Idioma esES: Español de España.", + "langEsmx": "Idioma esMX: Español de Latinoamérica.", + "langEnus": "Idioma enUS: Inglés de EEUU.", + "langEngb": "Idioma enGB: Inglés británico.", + "osLabel": "Sistema operativo", + "chooseOs": "Elegir sistema operativo", + "windows": "Windows", + "macCatalina": "Mac OS Catalina", + "downloadBtn": "DESCARGAR", + "errorChoose": "Debes escoger un cliente y un sistema operativo.", + "macGuideTitle": "Guía para ejecutar el cliente en mac OS Catalina", + "mac1": "macOS Catalina ya no soporta aplicaciones que trabajan en 32bits, y el cliente se ejecuta en 32bits.", + "mac2": "Siguiendo los pasos a continuación podrás disfrutar UltimoWoW sin problemas en macOS Catalina.", + "macInstructions": "Instrucciones", + "macStep1": "1 - Descarga e instala CrossOver.", + "macStep2": "2 - Una vez que tengas descargado el cliente, ejecuta CrossOver y haz clic en \"Instalar una aplicación para Windows\".", + "macStep3": "3 - En el campo \"Seleccionar una aplicación para instalar\", busca la descarga, selecciónalo y haz clic en continuar. (No hagas clic en instalar aún).", + "macStep4": "4 - Ve a la pestaña donde dice \"Seleccionar instalador\", haz clic en \"Elegir archivo de instalador\", y ahora busca WoW.exe y selecciónalo.", + "macStep5": "5 - En la pestaña Botella, puedes seleccionar Windows 7 64bits.", + "macStep6": "6 - Ve a la pestaña \"Instalar y finalizar\", haz clic en Instalar, se instalarán todas las fuentes, archivos y Visual Redistributables necesarios que WoW usa en un sistema operativo Windows estándar.", + "macStep7": "7 - Te pedirá instalar y aceptar los FONTS, Microsoft Visual C ++, haz clic en Sí para cada solicitud que aparezca.", + "macStep8": "8 - El cliente se iniciará automáticamente.", + "macStep9": "9 - Una vez que termines y salgas del cliente, haz clic en \"Listo\" en la aplicación CrossOver.", + "macStep10": "10 - La próxima vez que desees volver, abre la aplicación CrossOver, mira el panel izquierdo y selecciona en Botella el WoW que se creó anteriormente, y haz clic en RUN COMMAND, selecciona WoW.exe y haz clic en ¨Guardar comando como iniciador¨, luego haz clic en Abrir.", + "macStep11": "11 - Finalmente, verás el ícono de WoW debajo de la pestaña Botella de WoW, ahora puedes arrastrar el lanzador de WoW al Dock, de esta manera, la próxima vez que quieras entrar, simplemente ejecuta WoW desde el Dock." + }, + "cookie": { + "dialogLabel": "Consentimiento de cookies", + "title": "Utilizamos cookies", + "description": "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.", + "policyLink": "Política de Cookies", + "catNecessary": "Necesarias", + "descNecessary": "Esenciales para el funcionamiento del sitio. No se pueden desactivar.", + "catAnalytics": "Analíticas", + "descAnalytics": "Nos ayudan a entender cómo usas el sitio para mejorarlo.", + "catMarketing": "Marketing", + "descMarketing": "Se utilizan para mostrarte anuncios relevantes.", + "savePrefs": "Guardar preferencias", + "reject": "Rechazar", + "customize": "Personalizar", + "acceptAll": "Aceptar todas", + "changeConsent": "Cambiar consentimiento", + "revokeConsent": "Retirar consentimiento", + "statusZaraz": "Estado actual (Cloudflare Zaraz Consent API):", + "statusSaved": "Estado actual (preferencia guardada):", + "statusUnavailable": "Cloudflare Zaraz no está disponible en este dominio; aún no hay preferencia guardada.", + "accepted": "Aceptada", + "rejected": "Rechazada", + "alwaysOn": "Siempre activas" + }, + "twofa": { + "errGeneric": "Algo ha salido mal. Por favor intente más tarde.", + "eyeHide": "Ocultar", + "eyeShow": "Mostrar", + "passwordPlaceholder": "Contraseña", + "tokenPlaceholder": "Token de seguridad", + "activating": "Activando 2FA", + "activate": "Activar 2FA", + "step1": "Paso 1) Descarga la aplicación de autenticación:", + "step2": "Paso 2) Escanea este código QR con tu aplicación de autenticación:", + "copyKeyNote": "Si no puedes escanear el código QR copia y pega esta clave en tu aplicación de autenticación:", + "copied": "¡Copiado!", + "copyKey": "Copiar clave", + "step3": "Paso 3) Ingresa el código generado por tu aplicación de autenticación:", + "codePlaceholder": "Código de 6 dígitos", + "verified": "Verificado ✔️", + "verifying": "Verificando...", + "verifyCode": "Verificar código", + "enabledNotice": "La verificación en 2 pasos está activada en esta cuenta.", + "disableInstruction": "Para desactivarla, introduce un código actual de tu aplicación de autenticación.", + "disabled": "2FA desactivado ✔️", + "disabling": "Desactivando...", + "disable": "Desactivar 2FA" + } } }