Configuración de múltiples idiomas en Nextjs

힘센캥거루
2025년 10월 19일(수정됨)
5
19
Configuración de múltiples idiomas en Nextjs-1

Para aumentar el tráfico a mi blog, decidí probar la configuración multilingüe.

Investigué varias maneras y el primer paso es enrutar por idioma.

Decidí usar next-intl.

1. Instalación

yarn add next-intl

2. Aplicación

La aplicación es algo complicada.

Aproximadamente se sigue el siguiente orden:

  1. Colocar toda la estructura de carpetas internas de la app dentro de la carpeta [locale].

  2. Crear una carpeta i18n y generar config.ts, request.ts, ko.json, en.json en su interior.

  3. Configurar en middleware.ts y next.config.ts.

  4. Envolver niños con params y provider en el layout.

  5. Cargar mensajes en los componentes.

3. Probar

1) Carpeta [locale]

Configuración de múltiples idiomas en Nextjs-2

Esta es la estructura de carpetas interna de mi app. 

Voy a envolver todas las carpetas excepto api y uploads dentro de [locale].

Al mover carpetas con .next presente, se produce un error de permisos, así que elimínelo con sudo rm -r .next y luego mueva las carpetas.

Es importante adaptar las llamadas de rutas relativas ya que la estructura de carpetas ha cambiado.

Configuración de múltiples idiomas en Nextjs-3

2) Crear carpeta i18n

Si tiene una carpeta src, puede crearla dentro de src; de lo contrario, simplemente en la raíz si solo usa la carpeta app.

Cree config.ts, request.ts en la carpeta i18n y ko.json, en.json en la carpeta message.

Configuración de múltiples idiomas en Nextjs-4

Configura config.ts como sigue:

Configuré la ruta base "/" al coreano.

export const locales = ['ko', 'en'] as const;
export type Locale = (typeof locales)[number];

export const defaultLocale: Locale = 'ko'; // Establece la ruta base en coreano

export const pathnames = {
  '/': '/',
  '/about': {
    ko: '/about',
    en: '/about',
  },
  '/post/[slug]': {
    ko: '/post/[slug]',
    en: '/post/[slug]',
  },
} as const;

Configura request.ts de la siguiente manera:

Se llama a la información del locale y se devuelve al servidor.

import { getRequestConfig } from 'next-intl/server';
import { defaultLocale } from './config';

export default getRequestConfig(async ({ requestLocale }: { requestLocale: Promise<string | undefined> }) => {
  const locale = await requestLocale || defaultLocale;

  return {
    locale,
    messages: (await import(`./message/${locale}.json`)).default,
  };
});

3) Configuración middleware.ts, next.config.ts

Primero, configura middleware.ts de la siguiente manera:

Es fácil pensar que se añade createMiddleware al principio como export.

import createMiddleware from 'next-intl/middleware';
import { locales, defaultLocale } from './i18n/config';

export createMiddleware({
  locales,
  defaultLocale,
  localePrefix: 'as-needed', // El coreano (ko) no tiene prefijo en la ruta
});
//...configuraciones existentes...//
export default withAuth(
	  function middleware(req) {
		//...configuraciones existentes...//
	});

Luego en next.config.ts, crea createNextIntlPlugin y envuelve las configuraciones existentes:

import type { NextConfig } from "next";
import createNextIntlPlugin from 'next-intl/plugin';

const withNextIntl = createNextIntlPlugin()

const withNextIntlConfig: NextConfig = withNextIntl({
	configuraciones de next.config existentes...
});

export default withNextIntlConfig;

4) Envolviendo el Layout

Ahora, obtén el locale con getMessage en el layout, envuelve con provider para que los componentes secundarios lo usen.

import { NextIntlClientProvider } from "next-intl";
import { getMessages, getLocale } from "next-intl/server";

export default async function RootLayout({
  children,
}: Readonly<{
  children: React.ReactNode;
}>) {
  const messages = await getMessages();
  const locale = await getLocale();

  return (
    <html
      lang={locale}
    >
      <NextIntlClientProvider locale={locale} messages={messages}>
        <body>
		{children}
        </body>
      </NextIntlClientProvider>
    </html>
  );
}

5) Usar mensajes

Los nombres de las funciones son diferentes cuando se renderiza en el lado servidor y el lado cliente.

import {useTranslations, useLocale, useFormatter} from 'next-intl'; // se llama desde el componente 'use client'
import {getTranslations, getLocale, getFormatter} from 'next-intl/server'; // se llama desde el componente del servidor

Categoría

Componente Cliente

Componente Servidor / Función Servidor

Descripción

Traducciones

useTranslations(namespace?)

getTranslations(namespace?)

Trae mensajes de traducción como ko.json, en.json y se utilizan en forma t('key')

Locale

useLocale()

getLocale()

Devuelve el locale activo como cadena (/en, /ko, …)

Formatter

useFormatter()

getFormatter()

Formatea fecha, hora, números según el locale

Mensajes

getMessages()

Objeto de mensajes de traducción completa de la solicitud actual (usualmente para layout como Provider)

Establecer Locale de Solicitud

unstable_setRequestLocale(locale)

Se usa en layout para asegurar consistencia de locale en caching SSG·SSR

Decidí cambiar /about.

El componente /about estaba codificado así que era bueno para cambios.

import {
  HeroSection,
  JourneySection,
  ProjectsSection,
} from "@/components/about";


const baseUrl = process.env.NEXT_PUBLIC_URL||"";

export default function AboutPage() {
	...
  const heroData = {
	...
  };

  const journeyData = {
    title: "My Journey",
    items: [
	.....
	]
  };

  const projectsData = {
    title: "Featured Projects",
    projects: [
      {
        title: "Análisis Estadístico de Admisiones",
		...
      },
	...
    ],
  };

  return (
    <div className="min-h-screen bg-gray-900 ">
      <main className="rounded-lg container relative mx-auto scroll-my-12 overflow-auto">
        {/* Selector de Idioma */}
        <HeroSection {...heroData} />
        <JourneySection {...journeyData} />
        <ProjectsSection {...projectsData} />
      </main>
    </div>
  );
}

Configura ko.json y en.json y utiliza getTranslations para insertar texto en el componente.

Configuración de múltiples idiomas en Nextjs-5

El problema es que lo obtenido con getTranslations es solo texto.

Intenté cambiarlo así y resultó en un error.

export default async function AboutPage() {
	...
  const t = await getTranslations("about");
  const heroData = JSON.parse(JSON.stringify(t("hero")));
  const journeyData = JSON.parse(JSON.stringify(t("journey")));
  const projectsData = JSON.parse(JSON.stringify(t("projects")));
	...
}

Fue una molestia, así que pedí ayuda a Cursor.

Configuración de múltiples idiomas en Nextjs-6

De esta forma, se pasó a todos los componentes secundarios a través de props.

Luego verifiqué con en.

Configuración de múltiples idiomas en Nextjs-7

Puedo ver que se ha aplicado correctamente.

4. Conclusión

Hasta ahora pensaba que debía hacer todo el trabajo del blog en inglés manualmente, pero ahora con AI y herramientas automatizadas, será más fácil.

Lo que queda es traducir todas las entradas del blog e incorporarlas en la base de datos.

Luego agregaré el locale a la base de datos y recuperaré las publicaciones mediante búsquedas por locale.

Lo intentaré pronto.

관련 글

공문서 완전 자동화 해보기 - ChatGPT, Claude, kordoc + python-hwpx
공문서 완전 자동화 해보기 - ChatGPT, Claude, kordoc + python-hwpx
대한민국 공공기관은 여전히 .hwp 확장자를 가진 파일을 많이 사용한다.이 파일은 한글과컴퓨터에서 만든 독자 규격 문서다.문제는 이 형식이 다른 프로그램과 완전히 호환되지 않는다는 데 있다.문서를 열어보는 것은 가능하다.하지만 그 내용을 구조적으로 읽고, 데이터처럼 활...
Relato del desarrollo de un blog full‑stack con Next.js
Relato del desarrollo de un blog full‑stack con Next.js
Alrededor de un año después de empezar con el desarrollo web, empecé a pensar que quería tener mi propio blog.Así que estuve dedicado a esto durante u...
Despliegue sin interrupciones de Nextjs (servidor local) usando Caddy
Despliegue sin interrupciones de Nextjs (servidor local) usando Caddy
Cada vez que me entraban ganas de seguir añadiendo cosas a la página web, hacía un build, y en ese intervalo parece que había gente que se conectaba d...
Automatización de la indexación de búsqueda de Google - Web Search Indexing API
Automatización de la indexación de búsqueda de Google - Web Search Indexing API
Después de IndexNow, decidí probar también la automatización con Google.Buscando un poco, vi que Google ofrecía algo llamado Web Search Indexing a tra...
Automatizar la creación de índices de búsqueda - IndexNow
Automatizar la creación de índices de búsqueda - IndexNow
Mientras estaba registrando el sitio en Bing, me enteré de que Bing ofrece una función llamada IndexNow.Lo esencial es que, usando una clave de API, p...
Experiencia de que hackearan mi servidor Nextjs y React
Experiencia de que hackearan mi servidor Nextjs y React
La primera vez que me encontré con este problema de seguridad fue la madrugada del 5 de diciembre.Que en React era posible ejecutar código de forma re...

댓글을 불러오는 중...