feat(i18n): restrict public routes and metadata to enabled locales
CI / Lint e auditorias (push) Successful in 41s
CI / Trivy (dependências e segredos) (push) Successful in 10s
CI / Imagem Docker (linux/arm64) (push) Successful in 2m5s

- Add ENABLED_LOCALES configuration in i18n/links.js (currently ["pt"])
- Redirect inactive locale prefixes to /pt via 307 in middleware.js
- Restrict root locale negotiation to active locales with fallback to pt
- Hide LanguageSelector when only one locale is enabled
- Generate sitemap, hreflang alternates, and og:locale only for active locales
- Generate static SSG pages only for active locales in build
- Adapt check:i18n and smoke-imagem.sh to validate active vs inactive locales

Co-Authored-By: Antigravity <noreply@google.com>
This commit is contained in:
Lucas RayanandAntigravity committed 2026-11-01 12:10:25 -03:00
1 parent 3a1a095e97
commit d479a8d361
9 files changed
+219 -79

No files matched your search

+12 -3
View File
@@ -3,6 +3,7 @@ import { JetBrains_Mono, Manrope, Space_Grotesk } from "next/font/google";
import { NextIntlClientProvider } from "next-intl";
import { getMessages } from "next-intl/server";
import { routing } from "@/i18n/routing";
import { ENABLED_LOCALES } from "@/i18n/links";
import "../globals.css";
import Providers from "@/components/Providers";
import { SITE, jsonLd } from "@/lib/seo";
@@ -38,7 +39,7 @@ const LANG_MAP = {
};
export function generateStaticParams() {
return routing.locales.map((locale) => ({ locale }));
return ENABLED_LOCALES.map((locale) => ({ locale }));
}
export async function generateMetadata({ params }) {
@@ -52,6 +53,8 @@ export async function generateMetadata({ params }) {
"zh-CN": "zh_CN",
};
const alternateLocales = ENABLED_LOCALES.filter((l) => l !== locale).map((l) => ogLocaleMap[l]);
return {
metadataBase: new URL(SITE.url),
title: {
@@ -71,10 +74,16 @@ export async function generateMetadata({ params }) {
"comparar ESP32", "qual ESP32 escolher", "datasheet ESP32",
"microcontrolador", "Espressif", "ESP-IDF", "IoT", "sistemas embarcados",
],
alternates: { canonical: `/${locale}` },
alternates: {
canonical: `/${locale}`,
languages: Object.fromEntries(
ENABLED_LOCALES.map((l) => [LANG_MAP[l] || l, `/${l}`])
),
},
openGraph: {
type: "website",
locale: ogLocaleMap[locale] || "pt_BR",
alternateLocale: alternateLocales.length > 0 ? alternateLocales : undefined,
url: `${SITE.url}/${locale}`,
siteName: SITE.nome,
title: "ESPDocs · Documentação do ESP32 em português",
@@ -127,7 +136,7 @@ export const viewport = {
export default async function RootLayout({ children, params }) {
const { locale } = await params;
if (!routing.locales.includes(locale)) {
if (!ENABLED_LOCALES.includes(locale)) {
notFound();
}