i18n con next-intl: raíz multilenguaje (es por defecto, /en) + textos externalizados
- next-intl 4 (compatible Next 16): routing (es default en RAÍZ sin prefijo, en con /en, localePrefix 'as-needed'), middleware, request config, navigation helpers. - Estructura app/[locale]/ (layout con <html lang>, NextIntlClientProvider, metadata SEO por idioma vía generateMetadata; page home con getTranslations). - Catálogos messages/es.json y en.json: TODOS los textos de la UI (nada hardcodeado en los .tsx, se usan con t()). Verificado: / -> español (lang=es, título ES), /en -> inglés (lang=en, título EN), datos SSR desde MySQL. Añadir idioma = locale en routing + messages/<loc>.json. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,52 @@
|
||||
import type { Metadata } from 'next'
|
||||
import { notFound } from 'next/navigation'
|
||||
import { NextIntlClientProvider, hasLocale } from 'next-intl'
|
||||
import { getTranslations, setRequestLocale } from 'next-intl/server'
|
||||
import { routing } from '@/i18n/routing'
|
||||
import '../globals.css'
|
||||
|
||||
export function generateStaticParams() {
|
||||
return routing.locales.map((locale) => ({ locale }))
|
||||
}
|
||||
|
||||
// SEO por idioma (SSR) vía Metadata API.
|
||||
export async function generateMetadata({
|
||||
params,
|
||||
}: {
|
||||
params: Promise<{ locale: string }>
|
||||
}): Promise<Metadata> {
|
||||
const { locale } = await params
|
||||
const t = await getTranslations({ locale, namespace: 'Metadata' })
|
||||
return {
|
||||
title: t('title'),
|
||||
description: t('description'),
|
||||
openGraph: {
|
||||
siteName: 'Nova WoW',
|
||||
title: t('title'),
|
||||
description: t('description'),
|
||||
type: 'website',
|
||||
locale: locale === 'es' ? 'es_ES' : 'en_US',
|
||||
url: 'https://www.nightspire.gg/',
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
export default async function LocaleLayout({
|
||||
children,
|
||||
params,
|
||||
}: {
|
||||
children: React.ReactNode
|
||||
params: Promise<{ locale: string }>
|
||||
}) {
|
||||
const { locale } = await params
|
||||
if (!hasLocale(routing.locales, locale)) notFound()
|
||||
setRequestLocale(locale)
|
||||
|
||||
return (
|
||||
<html lang={locale}>
|
||||
<body>
|
||||
<NextIntlClientProvider>{children}</NextIntlClientProvider>
|
||||
</body>
|
||||
</html>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user