reactjsinternationalizationnext.js

Routing localization with NextJS


I'm migrating a website developed with Gatsby to NextJS, but something I could achieve using Gatsby's createPage API is localizing the app's routes, but until now I couldn't achieve this with NextJS APIs.

I'm using Next v10.0.1 for this.


As I see in other threads regarding this type of resource, this is actually kinda confusing of what it actually means, so here goes an example of what is the desired result:

User access route /my-data/1234 (where the NextJS equivalent routing would be: /my-data/[dataId].js)

User must be able to access the same page but translated in the URL /pt/meus-dados/1234 (using, for example, portuguese translation).


Some guesses on how to achieve that keeping Next's static optimizations (Static rendering and Incrementing Static Rendering)?


Solution

  • I actually found an answer which is pretty useful for my use case, I'm using NextJS rewrites for that, maybe not the best solution, but fits my needs well.

    I use a single file for each route, so the directory structure should be something like this:

    pages
    -- my-data
       -- [id].js
    

    then I'll have some kind of internationalization, in my case I'm using react-i18next, won't think about the aspects of implementations for the library here, it could also be achieved with any other.

    Next step is to set a translation somewhere for the pages routes, for example, add an entry for the i18next messages named routes containing a key-value pair for the routes translations. e.g (intl/pt.json):

    {
      ...
      "routes": {
        "/my-data/:id": "/meus-dados/:id"
      }
      ...
    }
    

    and then use NextJS rewrites, so you will have to import the intl messages (e.g: from intl/pt.json) and map them as rewrites in next.config.js:

    # next.config.js
    ...
    async rewrites() {
      // languages here is a key-value pair object containing the structure { [language]: { routes: {...} } }
      // in my case, imported from `intl/pt.json`
      const intlRewrites = Object.entries(languages).reduce((rewrites, [ language, { routes } ]) => {
        return [
          ...rewrites,
          ...Object.entries(routes).map(([ path, translatedPath ]) => {
            const source = translatedPath
            const destination = path // here you can write a logic to add a language prefix if needed
    
            return { source, destination }
          })
        ]
      }, [])
    
      return intlRewrites
    }
    

    From my experience, optimizations like ISG work fine. Should work with SSG too, but I haven't tested it.