El inglés es mi segundo idioma y antes de dominar este idioma, siempre me resultó muy difícil encontrar recursos tecnológicos en mi propio idioma. Por eso decidí traducir mi blog y tener todo mi contenido disponible en español e inglés
Internationalización con Next.js
Next.js ha facilitado la internacionalización (i18n) de sitios web con una de las nuevas funciones avanzadas disponibles en la versión 10: Enrutamiento internacionalizado.
De las dos opciones proporcionadas por Next.js, he decidido usar Sub-path Routing
en lugar de Domain Routing
ya que no quiero crear un subdominio para la versión en español de mi blog.
Configuración Básica
next.config.js
module.exports = {
i18n: {
locales: ['en', 'es'],
defaultLocale: 'en',
},
}
Esta es la única configuración necesaria para habilitar la “Detección automática de idioma”.
El sistema de detección automática de idioma proporcionado por Next.js
redirigirá a los usuarios a la ruta con prefíjo /es
si el navegador está configurado en español (o cualquiera de sus variaciones regionales) como idioma predeterminado. Next.js
examinará el HTTP Header Accept-Language
e intentará seleccionar el idioma correcto, sin embargo, si el idioma no coincide, utilizará el idioma predeterminado. Por ejemplo, si los usuarios tienen alemán (DE-de) como idioma en su navegador, seleccionará el idioma predeterminado en inglés (en).
Archivos de Traducción de Idioma
Next.js
no prescribe una forma de almacenar los datos de traducción para cada idioma, o qué librería de i18n
se puede usar (o si necesita una librería).
Para proyectos pequeños (como en mi caso), un archivo JSON simple es suficiente, sin embargo, para una aplicación grande, se recomienda una solución más robusta para evitar cosas como un paquete inflado.
Creemos una carpeta llamada locale
y agreguémos un solo archivo JSON por idioma. es decir, locale/en.json
y locale/es.json
{
"greeting": "Hola amigos!"
}
Podríamos usar la clave del objeto para obtener el valor de la frase traducido sin ninguna librería, sin embargo, quiero usar react-intl
ya que es una de las librerías i18n
más populares que existen.
Agrega la siguiente configuración a tu _app.js
import '../styles/index.css'
import { IntlProvider } from 'react-intl';
import { useRouter } from "next/router"
const languages = {
en: require('../locale/en.json'),
es: require('../locale/es.json')
};
function MyApp({ Component, pageProps }) {
const router = useRouter()
const { locale, defaultLocale } = router;
const messages = languages[locale];
return <IntlProvider messages={messages} locale={locale} defaultLocale={defaultLocale}>
<Component {...pageProps} />
</IntlProvider>
}
export default MyApp
En el código anterior, estamos encapsulando toda nuestra aplicación con IntlProvider
y pasando los mensajes y la configuración del idioma que obtuvimos del useRouter() hook
. Ahora podemos usar los componentes de react-intl
como FormatedMessage
en toda nuestra aplicación.
import { FormattedMessage } from 'react-intl'
export default function Greeting() {
return (
<h1><FormattedMessage id="greeting" /></h1>
)}
Cambiando de Idioma
Al cambiar de idioma, quiero conservar la selección del usuario, de modo que si vuelve a visitar mi blog, el idioma preferido será seleccionado en lugar de la configuración detectada automáticamente por Next.js
.
Para lograr esto, podemos usar la cookie de configuración: Next.js Locale Cookie
:
import { useRouter } from "next/router"
import { useCookies } from 'react-cookie';
export default function LanguageSwitcher() {
const [ cookie, setCookie ] = useCookies(['NEXT_LOCALE']);
const router = useRouter();
const { locale } = router;
const switchLanguage = (e) => {
const locale = e.target.value;
router.push('/','/', { locale });
if(cookie.NEXT_LOCALE !== locale){
setCookie("NEXT_LOCALE", locale, { path: "/" });
}
}
return (
<select
onChange={switchLanguage}
defaultValue={locale}
>
<option value="en">EN</option>
<option value="es">ES</option>
</select>
);
}
getStaticProps
Para Cada Idioma
Para renderizar la lista de los artículos de mi blog en el idioma seleccionado, el parámetro locale
estará disponible en getStaticProps
para que se pueda pasar a la función que provee la información de la lista de artículos.
Por Ejemplo:
export async function getStaticProps({ locale }) {
const allPosts = await getAllPostsForHome(locale)
return {
props: { allPosts },
}
}
Optimización de motores de búsqueda (SEO)
Next.js
agregará un atributo HTML global llamado lang
a su sitio con la configuración del idioma actual; sin embargo, si tienes un archivo _document.js
personalizado, asegúrese de eliminar el valor de lang
.
Para informar a los motores de búsqueda sobre versiones alternativas de los artículos en diferentes idiomas, debemos agregar un metatag
llamado hreflang
por cada idioma disponible (incluido el idioma original) en el head
de cada artículo.
Por Ejemplo:
import Head from 'next/head'
export default function Post({ post }) {
return (
...
<article>
<Head>
<link rel="alternate" hreflang={locale} href={`${SITE_URL}${locale}/${post?.slug}`} />
<link rel="alternate" hreflang={altLocale} href={`${SITE_URL}${altLocale}/${altPost?.slug}`} />
</Head>
</article>
...
)}
Conclusión
La internacionalización (i (18 letras) n)
solía ser una tarea compleja, sin embargo, con la ayuda de Meta-Frameworks como Next.js
y librerías como react-intl
, traducir contenido para nuestros usuarios nunca ha sido más fácil! .
Espero que disfruten de mi contenido (traducido) y para mis amigos de habla inglesa, See you laters alligators…