Foro: enlaces de wowhead en el idioma del lector

Los enlaces de wowhead se guardan con el locale de quien los postea (subdominio,
domain y nombre), así que un ítem posteado en /es se veía en español aunque lo
leyeras en /en, y al revés. Ahora siguen el idioma de QUIEN LEE.

Al renderizar el tema (server component, conoce el locale del lector) se localizan
los enlaces: se reescribe el subdominio y el domain del data-wowhead y se vuelve a
resolver el nombre en el idioma del lector (lib/forum-wowhead + lib/wowhead-resolve,
compartido con la API del editor y cacheado). Es solo de presentación: no cambia lo
guardado ni añade parpadeo (el nombre llega ya resuelto del servidor).

Verificado: un post guardado con nombre inglés y domain=wotlk se lee como «Bolsa de
tejido de Escarcha» + es.wotlk en /es, y «Frostweave Bag» + www en /en.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-16 14:08:08 +00:00
parent e65e102244
commit 5bcf71a37b
4 changed files with 113 additions and 27 deletions
@@ -9,6 +9,7 @@ import {
getUserPostCount,
} from '@/lib/forum'
import { formatForumDate } from '@/lib/forum-format'
import { localizeWowheadLinks } from '@/lib/forum-wowhead'
import { getSession } from '@/lib/session'
import { forumIsModerator, canEditPost } from '@/lib/forum-perm'
import { PageShell } from '@/components/PageShell'
@@ -43,7 +44,11 @@ export default async function TopicPage({
const total = await countPosts(id, isMod)
const totalPages = Math.max(1, Math.ceil(total / PER_PAGE))
const page = Math.min(Math.max(1, Number((await searchParams).page) || 1), totalPages)
const posts = await getPosts(id, (page - 1) * PER_PAGE, PER_PAGE, isMod)
const rawPosts = await getPosts(id, (page - 1) * PER_PAGE, PER_PAGE, isMod)
// Enlaces de wowhead en el idioma de QUIEN LEE (no de quien posteó).
const posts = await Promise.all(
rawPosts.map(async (p) => ({ ...p, text: await localizeWowheadLinks(p.text, locale) })),
)
const posters = await resolvePosters(posts.map((p) => p.poster))
// Nº de posts por autor visible (para el panel lateral), en paralelo.
+8 -26
View File
@@ -1,33 +1,15 @@
// Resuelve nombre, calidad e icono de una entidad de wowhead (rama WotLK) para que
// el editor del foro pueda insertar el enlace ya con su nombre real y su color de
// calidad, sin el parpadeo de «item=xxx». Usa el endpoint de tooltip de wowhead
// (el mismo que consume tooltips.js) con dataEnv=8 = WotLK Classic.
import { fetchWowheadInfo } from '@/lib/wowhead-resolve'
const TYPES = new Set(['item', 'spell', 'quest', 'npc', 'achievement', 'object'])
// Código de locale de wowhead: 0 = inglés, 6 = español.
const WH_LOCALE: Record<string, number> = { es: 6, en: 0 }
// Resuelve nombre, calidad e icono de una entidad de wowhead (rama WotLK) para que
// el editor del foro pueda insertar el enlace ya con su nombre real, sin el parpadeo
// de «item=xxx». La lógica vive en lib/wowhead-resolve (compartida con el render).
export async function GET(request: Request) {
const url = new URL(request.url)
const type = String(url.searchParams.get('type') || 'item')
const id = String(url.searchParams.get('id') || '').replace(/\D/g, '')
const id = String(url.searchParams.get('id') || '')
const locale = String(url.searchParams.get('locale') || 'es')
if (!TYPES.has(type) || !id) return Response.json({ name: null }, { status: 400 })
const wl = WH_LOCALE[locale] ?? 0
try {
const r = await fetch(`https://nether.wowhead.com/tooltip/${type}/${id}?dataEnv=8&locale=${wl}`, {
// cache un día: los nombres/calidades no cambian
next: { revalidate: 86400 },
})
if (!r.ok) return Response.json({ name: null })
const d = (await r.json()) as { name?: string; quality?: number; icon?: string }
return Response.json({
name: d.name ?? null,
quality: typeof d.quality === 'number' ? d.quality : null,
icon: d.icon ?? null,
})
} catch {
return Response.json({ name: null })
}
const info = await fetchWowheadInfo(type, id, locale)
if (!info) return Response.json({ name: null }, { status: 400 })
return Response.json(info)
}