Foro multiidioma: nombres/descripciones de categorías y foros (ES/EN)

forum_categories.name_en y forums.name_en/description_en (sql/add_forum_en.sql,
aplicado en prod y traducidos los existentes: Comunidad/Anuncios/Discusión general).
getForumIndex(locale) y getForum(id, locale) usan EN si existe, si no caen al
español. Las páginas del foro pasan el locale. Labels (Temas/Mensajes) ya estaban
traducidos. Verificado: /en/forum en inglés, /es/forum en español.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-14 19:50:20 +00:00
parent 1d2aae5df2
commit cc6c76859c
4 changed files with 31 additions and 10 deletions
@@ -23,7 +23,7 @@ export default async function ForumPage({
const t = await getTranslations('Forum')
const id = Number(forumId)
const forum = await getForum(id)
const forum = await getForum(id, locale)
if (!forum) notFound()
const total = await countTopics(id)
const totalPages = Math.max(1, Math.ceil(total / PER_PAGE))
+1 -1
View File
@@ -10,7 +10,7 @@ export default async function ForumIndexPage({ params }: { params: Promise<{ loc
const { locale } = await params
setRequestLocale(locale)
const t = await getTranslations('Forum')
const categories = await getForumIndex()
const categories = await getForumIndex(locale)
return (
<PageShell title={t('title')}>
+16 -8
View File
@@ -60,13 +60,14 @@ export interface SearchResult {
}
/** Índice del foro: categorías con sus foros visibles (+ contadores y último tema). */
export async function getForumIndex(): Promise<Category[]> {
export async function getForumIndex(locale = 'es'): Promise<Category[]> {
const en = locale === 'en'
try {
const [cats] = await db(DB.web).query<RowDataPacket[]>(
'SELECT id, name FROM forum_categories ORDER BY `order`, id',
'SELECT id, name, name_en FROM forum_categories ORDER BY `order`, id',
)
const [forums] = await db(DB.web).query<RowDataPacket[]>(
`SELECT f.id, f.category_id, f.name, f.description, f.icon,
`SELECT f.id, f.category_id, f.name, f.name_en, f.description, f.description_en, f.icon,
(SELECT COUNT(*) FROM forum_topics t WHERE t.forum_id = f.id AND t.deleted = 0) AS topic_count,
(SELECT COUNT(*) FROM forum_posts p JOIN forum_topics t ON p.topic_id = t.id
WHERE t.forum_id = f.id AND p.deleted = 0 AND t.deleted = 0) AS post_count,
@@ -82,12 +83,14 @@ export async function getForumIndex(): Promise<Category[]> {
)
const byCat = new Map<number, ForumInfo[]>()
for (const f of forums) {
const info = f as unknown as ForumInfo
const info = f as unknown as ForumInfo & { name_en?: string | null; description_en?: string | null }
info.name = en && info.name_en ? info.name_en : info.name
info.description = en && info.description_en ? info.description_en : info.description
if (!byCat.has(info.category_id)) byCat.set(info.category_id, [])
byCat.get(info.category_id)!.push(info)
}
return cats
.map((c) => ({ id: c.id, name: c.name, forums: byCat.get(c.id) ?? [] }))
.map((c) => ({ id: c.id, name: en && c.name_en ? c.name_en : c.name, forums: byCat.get(c.id) ?? [] }))
.filter((c) => c.forums.length > 0)
} catch {
return []
@@ -106,13 +109,18 @@ export async function listForumsForMove(): Promise<{ id: number; name: string }[
}
}
export async function getForum(id: number): Promise<{ name: string; description: string } | null> {
export async function getForum(id: number, locale = 'es'): Promise<{ name: string; description: string } | null> {
const en = locale === 'en'
try {
const [rows] = await db(DB.web).query<RowDataPacket[]>(
'SELECT name, description FROM forums WHERE id = ? AND visibility = 1 AND deleted = 0',
'SELECT name, name_en, description, description_en FROM forums WHERE id = ? AND visibility = 1 AND deleted = 0',
[id],
)
return rows[0] ? { name: rows[0].name, description: rows[0].description } : null
if (!rows[0]) return null
return {
name: en && rows[0].name_en ? rows[0].name_en : rows[0].name,
description: en && rows[0].description_en ? rows[0].description_en : rows[0].description,
}
} catch {
return null
}
+13
View File
@@ -0,0 +1,13 @@
-- Foro multiidioma: nombre/descripción en inglés (opcional). Si están vacíos, se
-- cae a la versión en español. El texto original es ES.
ALTER TABLE forum_categories ADD COLUMN name_en VARCHAR(255) NULL AFTER name;
ALTER TABLE forums
ADD COLUMN name_en VARCHAR(45) NULL AFTER name,
ADD COLUMN description_en TEXT NULL AFTER description;
-- Traducción de las categorías/foros existentes.
UPDATE forum_categories SET name_en = 'Community' WHERE name = 'Comunidad';
UPDATE forums SET name_en = 'Announcements',
description_en = 'Official server news and announcements.' WHERE name = 'Anuncios';
UPDATE forums SET name_en = 'General Discussion',
description_en = 'Talk about everything server-related with the community.' WHERE name = 'Discusión general';