feat: configure next-intl i18n with ES/EN locales

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
consultoria-as
2026-02-22 03:54:05 +00:00
parent 6f342a065b
commit 00d500d3d3
12 changed files with 1322 additions and 637 deletions

View File

@@ -0,0 +1,35 @@
import type { Metadata } from "next";
import { NextIntlClientProvider } from "next-intl";
import { getMessages } from "next-intl/server";
import { notFound } from "next/navigation";
import { routing } from "@/i18n/routing";
import "./globals.css";
export const metadata: Metadata = {
title: "Project Afterlife",
description: "Preserving online games that deserve a second life",
};
export default async function LocaleLayout({
children,
params,
}: {
children: React.ReactNode;
params: Promise<{ locale: string }>;
}) {
const { locale } = await params;
if (!routing.locales.includes(locale as any)) {
notFound();
}
const messages = await getMessages();
return (
<html lang={locale}>
<body>
<NextIntlClientProvider messages={messages}>
{children}
</NextIntlClientProvider>
</body>
</html>
);
}

View File

@@ -1,19 +0,0 @@
import type { Metadata } from "next";
import "./globals.css";
export const metadata: Metadata = {
title: "Project Afterlife",
description: "Preserving online games that deserve a second life",
};
export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<html lang="es">
<body>{children}</body>
</html>
);
}

View File

@@ -0,0 +1,13 @@
import { getRequestConfig } from "next-intl/server";
import { routing } from "./routing";
export default getRequestConfig(async ({ requestLocale }) => {
let locale = await requestLocale;
if (!locale || !routing.locales.includes(locale as any)) {
locale = routing.defaultLocale;
}
return {
locale,
messages: (await import(`../messages/${locale}.json`)).default,
};
});

View File

@@ -0,0 +1,6 @@
import { defineRouting } from "next-intl/routing";
export const routing = defineRouting({
locales: ["es", "en"],
defaultLocale: "es",
});

View File

@@ -0,0 +1,63 @@
{
"nav": {
"home": "Home",
"catalog": "Catalog",
"about": "About Us",
"donate": "Donations"
},
"home": {
"hero_title": "Project Afterlife",
"hero_subtitle": "Preserving online games that deserve a second life",
"latest_games": "Latest restored games",
"view_all": "View all",
"donate_cta": "Support preservation"
},
"catalog": {
"title": "Game Catalog",
"filter_genre": "Genre",
"filter_status": "Server status",
"all": "All",
"no_results": "No games found"
},
"game": {
"released": "Released",
"shutdown": "Shutdown",
"developer": "Developer",
"publisher": "Publisher",
"server_status": "Server status",
"play_now": "Play now",
"view_documentary": "View documentary",
"status_online": "Online",
"status_maintenance": "Maintenance",
"status_coming_soon": "Coming soon"
},
"documentary": {
"chapters": "Chapters",
"listen": "Listen",
"reading_progress": "Reading progress"
},
"audio": {
"play": "Play",
"pause": "Pause",
"speed": "Speed",
"chapter_mode": "By chapter",
"continuous_mode": "Continuous"
},
"about": {
"title": "About Us",
"mission": "Our Mission",
"team": "The Team",
"contribute": "How to Contribute"
},
"donate": {
"title": "Donations",
"description": "Project Afterlife is funded exclusively by donations. Your support keeps these games alive.",
"patreon": "Donate on Patreon",
"kofi": "Donate on Ko-fi",
"transparency": "Fund transparency"
},
"footer": {
"rights": "Project Afterlife. Preserving gaming history.",
"language": "Language"
}
}

View File

@@ -0,0 +1,63 @@
{
"nav": {
"home": "Inicio",
"catalog": "Catálogo",
"about": "Sobre Nosotros",
"donate": "Donaciones"
},
"home": {
"hero_title": "Project Afterlife",
"hero_subtitle": "Preservando juegos online que merecen una segunda vida",
"latest_games": "Últimos juegos restaurados",
"view_all": "Ver todos",
"donate_cta": "Apoya la preservación"
},
"catalog": {
"title": "Catálogo de Juegos",
"filter_genre": "Género",
"filter_status": "Estado del servidor",
"all": "Todos",
"no_results": "No se encontraron juegos"
},
"game": {
"released": "Lanzado",
"shutdown": "Cerrado",
"developer": "Desarrolladora",
"publisher": "Distribuidora",
"server_status": "Estado del servidor",
"play_now": "Jugar ahora",
"view_documentary": "Ver documental",
"status_online": "En línea",
"status_maintenance": "Mantenimiento",
"status_coming_soon": "Próximamente"
},
"documentary": {
"chapters": "Capítulos",
"listen": "Escuchar",
"reading_progress": "Progreso de lectura"
},
"audio": {
"play": "Reproducir",
"pause": "Pausar",
"speed": "Velocidad",
"chapter_mode": "Por capítulo",
"continuous_mode": "Continuo"
},
"about": {
"title": "Sobre Nosotros",
"mission": "Nuestra Misión",
"team": "El Equipo",
"contribute": "Cómo Contribuir"
},
"donate": {
"title": "Donaciones",
"description": "Project Afterlife se financia exclusivamente con donaciones. Tu apoyo mantiene vivos estos juegos.",
"patreon": "Donar en Patreon",
"kofi": "Donar en Ko-fi",
"transparency": "Transparencia de fondos"
},
"footer": {
"rights": "Project Afterlife. Preservando la historia del gaming.",
"language": "Idioma"
}
}

View File

@@ -0,0 +1,8 @@
import createMiddleware from "next-intl/middleware";
import { routing } from "./i18n/routing";
export default createMiddleware(routing);
export const config = {
matcher: ["/((?!api|_next|_vercel|.*\\..*).*)"],
};