i18n con Gatsby

Author: Alfredo Navas

Agregando I18n a mi sitio en Gatsby

Cuando tenía mi sitio originalmente en WordPress manejaba las traducciones con algun plugin como WPML o Polylang, como decidí moverme hacia MDX pues mi blog era una mezcla de artículos en inglés y español.

Esta es una descripción paso a paso de la solución que implemente.

1. Investigación

Primero me puse a buscar información relacionada, mucha de la que encontré, aplicaba más que nada a proyectos muy específicos, pero me dieron una buena idea de por dónde empezar. dentro de la informacion que encontre destacan estos artículos:

2. Manos a la Obra

Lo que pienso hacer con ayuda del plugin, es duplicar mis páginas y agregar el prefijo del lenguaje, en mi caso es para español y ninguno para inglés ( pues es el lenguaje que uso por defecto ), así pues lo primero es instalar el plugin.

Nota: Este plugin no traduce mensajes, solo crea rutas para cada idioma, y puede usar diferentes componentes para cada idioma si lo deseas.

Nos vamos a la consola:

npm i gatsby-plugin-i18n

Luego actualize mi gatsby-config.js :

{ resolve: 'gatsby-plugin-i18n', options: { langKeyDefault: 'en', useLangKeyLayout: true } },

Luego en mis páginas estáticas, solo les agregue el prefijo es así pues:

- 📁 pages # Para español usamos el prefijo .es - 📄 index.es.js # El default para el resto de los idiomas es inglés - 📄 index.js

Veamos para qué sirven esas opciones que hemos agregado.

langKeyDefault: lanKey para usar cuando no se especifica lanKey.

useLangKeyLayout:

  • true: usa un layout diferente para cada langKey (src/pages/index.js, src/pages/index.es.js, ...)

  • false: usa el layout por defecto (src/layouts/index.js)

Entonces, ya resuelto el dilema con las páginas estáticas, vamos a reventar el sitio 😃 ..., nos vamos a la consola:

gatsby clean && gatsby develop

giphy

me voy a localhost:8000 o elpuas y voila! mis paginas estan ahora en inglés y español, lo puedes notar haciendo click en el tab ES/EN en la navegación, pues listo primer paso resuelto.

No tuve mucho que cambiar en mi código más que en gatsby-config.js

Se me olvido agregar que a algunos de mis componentes tambien les agregue un prefijo cuando era necesario, por ejemplo la navegacion quedó navigation.es.js para español y navigation.js para usarse por defecto.

entonces en algunas de mis paginas simplemente importe el componente dependiendo del idioma.

3. Creando Páginas Programaticamente

Como he mencionado antes mis paginas estan en MDX, y para eso uso el plugin gatsby-plugin-mdx con este plugin puedo accesar todos los post en mi query con el keyword allMDX, dicho esto nos abro mi archivo gatsby-node

Inicialmente asi tenia mi función de crear paginas usando el API de Gatsby:

exports.createPages = ({ graphql, actions }) => { const { createPage } = actions return graphql(` query { allMdx(sort: { order: DESC, fields: [frontmatter___date] }) { edges { node { id excerpt(pruneLength: 250) fields { slug } frontmatter { title author thumbnail { childImageSharp { id fluid(fit: COVER, maxWidth: 287, maxHeight: 446) { base64 src srcSet sizes } } } } } } } } `).then((results, errors) => { if (errors) return Promise.reject(errors) const posts = results.data.allMdx.edges }

CreatePages

Crea páginas de forma dinámica. Este punto de extensión se llama solo después de que se completan el abastecimiento inicial y la transformación de los nodos, además de la creación del esquema GraphQL, para que pueda consultar sus datos para crear páginas.

También puede obtener datos de fuentes locales o remotas para crear páginas.

Se me ocurrió, crear un nuevo campo en mis archivos MDX, agregue language ES para español y EN para inglés, así de esa manera puedo filtrar mis queries por lenguaje.

--- title: Como agregar scripts a WP de la manera correcta author: Alfredo Navas date: 2016-11-03 thumbnail: ../../images/bosh.png language: ES ---

De esta forma simplemente duplique mi query esta vez con un filtro,un query para español y uno por defecto, que serían los post con el language: EN:

Este seria mi query para español:

const postEs = await graphql(` query { allMdx(filter: {frontmatter: {language: {eq: "ES"}}}, sort: { order: DESC, fields: [frontmatter___date] }) { edges { node { id excerpt(pruneLength: 250) fields { slug } frontmatter { title author language thumbnail { childImageSharp { id fluid(fit: COVER, maxWidth: 287, maxHeight: 446) { base64 src srcSet sizes } } } } } } } } `).then((results, errors) => { if (errors) return Promise.reject(errors) const posts = results.data.allMdx.edges }

Finalmente usando una vez más el API de Gatsby, con createPage le indico a cada query cual template usar y el path:

createPage({ path: `/es/blog/${page}`, component: path.resolve('./src/components/browse-blog-posts.es.js'), // El context también se pasa como props al // componente como en la consulta GraphQL del componente. context: { groupedPosts, group, page } })

CreatePage

Gatsby usa Redux internamente para administrar el estado. Cuando se implementa una API de Gatsby, se le pasa una colección de acciones (equivalente a acciones vinculadas con bindActionCreators en Redux) que puede usar para manipular el estado de su sitio.

Las acciones del objeto contienen las funciones y estas se pueden extraer individualmente utilizando la desestructuración de objetos ES6.

Una de estas acciones es CreatePage(), a esta función dentro de los parámetros que acepta estan path, component, y context

  • path: Cualquier URL válida. Debe comenzar con una barra inclinada /
  • component: La ruta absoluta al componente de esta página
  • context: Para esta página. Se pasan como props al componente this.props.pageContext, así como a la consulta graphql como argumentos graphql.

it works!

El resultado lo pueden ver en:

El Siguiente paso son las páginas individuales, que no son generadas con el API de Gatsby directamente, si no con el plugin gatsby-plugin-mdx...

Update

Hay un gihub issue reportado, y aparentemente ya esta merge en la ultima version, pero el npm package esta desactualizado y no contiene la ultima version.

przemuh tiene un workaround pero claramente falla en la nube.

Solucion

Mientras se resulve la actualizacion del plugin, mi solucion fue agregandole un condicional al post layout asi que basicamente:

extraigo language del objeto:

const BlogPostLayout = ({ children, pageContext }) => { deckDeckGoHighlightElement(); const { title, author, language } = pageContext.frontmatter ... }

Y como en mi caso lo único que cambia es el layout lo use de esta manera:

if (language && language === 'ES') { return ( // Regreso el layout para español <LayoutEs /> ) } else { return( // Regreso el layout por defecto <Layout /> ) }

El único problema aquí es que las rutas en español no llevan el prefijo /es/ así que será esperar a que actualicen el plugin, por el momento mi sitio está en dos idiomas.

no way

Espero que esta experiencia te sirva en algún proyecto, gracias por llegar hasta aquí.

© 2021, Hecho con Gatsby por El.Puas