Navigating through sub-paths with the same location on various domain routes (Next.JS & i18n)

The challenge ahead:

Developing a website that caters to multiple countries, each with its own unique set of products, services, etc. The website also needs to be able to translate into different languages based on the country/TLD. Some domains may share certain translation languages. The desired outcome should look like this:

US
sitename.com - US market, English language (US)

Germany
sitename.de - native language
sitename.de/en - English language (INT)

France
sitename.fr - native language
sitename.fr/en - English language (INT)

Netherlands
sitename.nl - native language
sitename.nl/en - English language (INT)

United Kingdom
sitename.co.uk - English language (GB)

Current status:

In my next.config.js, I have configured domain routing as shown in the following example:

module.exports = {
  ...
  i18n: {
    localeDetection: false,
    defaultLocale: 'en',
    locales: [],
    domains: [
      {
        domain: 'sitename.com',
        defaultLocale: 'en-US', 
        locales: []
      },
      {
        domain: 'sitename.de',
        defaultLocale: 'de-DE', 
        locales: ['en']
      },
      {
        domain: 'sitename.fr',
        defaultLocale: 'fr-FR', 
        locales: ['en']
      },
      {
        domain: 'sitename.nl',
        defaultLocale: 'nl-NL', 
        locales: ['en']
      },
      {
        domain: 'sitename.co.uk',
        defaultLocale: 'en-GB', 
        locales: []
      },
      // more countries can be added here...
    ]
  }
}

Unfortunately, Next.JS is not cooperating with my configuration and throws the following error message:

Both sitename.de and sitename.fr configured the locale (en) but only one can. Remove it from one i18n.domains config to continue
Both sitename.fr and sitename.de configured the locale (en) but only one can. Remove it from one i18n.domains config to continue
Both sitename.nl and sitename.de configured the locale (en) but only one can. Remove it from one i18n.domains config to continue
Error: Invalid i18n.domains values:
{"domain":"sitename.de","defaultLocale":"de-DE","locales":["en"]}
{"domain":"sitename.fr","defaultLocale":"fr-FR","locales":["en"]}
{"domain":"sitename.nl","defaultLocale":"nl-NL","locales":["en"]}

The domains value must follow the format { domain: 'example.fr', defaultLocale: 'fr', locales: ['fr'] }.
For more information, refer to: https://nextjs.org/docs/messages/invalid-i18n-config

Question:

Is there a way to successfully implement this type of localization in NEXT.JS, where certain domains may share a language without needing to include every other language in the list?

Answer №1

  1. Include all supported language options in the i18n root array
    locales: ["en-US", "de-DE", "fr-FR", "nl-NL"...]
  1. Remove language options array from domain items. Keep only if you want a specific language to redirect to that domain. Currently, every "en" option will redirect to 3 different domains.
   {
        domain: 'sitename.de',
        defaultLocale: 'de-DE', 
        locales: ['en']
      },
      {
        domain: 'sitename.fr',
        defaultLocale: 'fr-FR', 
        locales: ['en']
      },
      {
        domain: 'sitename.nl',
        defaultLocale: 'nl-NL', 
        locales: ['en']
      }

Remove the array and specify redirection for each language to its respective domain.

In the initial part of the task, it might not be achievable with just pure nextjs as each language has a distinct domain and needs to be redirected accordingly.

One possible solution is available at: https://github.com/tomsoderlund/nextjs-multi-domain-locale but unfortunately, it did not work for me.

Answer №2

If you want to configure multiple domains with support for multiple locales without using domain redirections, here is a method you can follow:

  1. Modify your locale switch code from the current implementation:
const { pathname, asPath, query } = router
router.push({ pathname, query }, asPath, { locale: newLocale })

to the following code snippet:

const { pathname, asPath, query, defaultLocale } = router
router.push({ pathname, query }, asPath, {
    locale: newLocale === defaultLocale
        ? 'default-locale'
        : `locale-${newLocale}`
})

By implementing this change, you can avoid domain routing and redirection when using locales outside of the predefined list.

  1. Redirect custom locales to the correct paths in your next.config.js:
async redirects() {
    return [
        {
            source: '/default-locale/:slug*',
            destination: '/:slug*',
            permanent: false,
        },
        {
            source: '/locale-:locale/:slug*',
            destination: '/:locale/:slug*',
            permanent: false,
        },
    ];
}
  1. Set up domains in the i18n section of your next.config.js:
i18n: {
    defaultLocale: 'en',
    locales: ['en', 'fr'],
    localeDetection: false,
    domains: [
        {
            domain: 'example.en',
            defaultLocale: 'en',
        },
        {
            domain: 'example.fr',
            defaultLocale: 'fr',
        },
    ],
}

That's all you need to do!

Answer №3

It appears that some environment variables may be missing. Make sure to verify with your colleagues that all necessary settings are included in your .env file on your local machine.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

D3.js: Difficulty fitting the chart within my bootstrap div

Currently, I'm encountering a problem where the "card" component from Bootstrap is not adjusting responsively with my d3.chart. The screenshot below displays the outcome: https://i.sstatic.net/2MhBx.png Chart Code const sample = [ { languag ...

Utilizing Mongoose/Node.js to Set TTL/Expiration on an Object

UPDATE 1 Upon further investigation, it appears that MongoDB is only storing the most recent 7 records. Is this happening due to the way I am sending objects to mongoose? Is it overwriting them? After removing all references to TTL/Timeout, I still only ...

Why does Vuetify/Javascript keep throwing a ReferenceError stating that the variable is undefined?

I'm currently developing in Vuetify and I want to incorporate a javascript client for Prometheus to fetch data for my application. You can find the page Here. Despite following their example, I keep encountering a ReferenceError: Prometheus is not def ...

Leverage OpenID Connect in Azure Active Directory with authentication code flow

Currently, I am developing an authentication system for a NodeJS and Express web application that requires users to be directed to Microsoft SSO. To achieve this, I am utilizing passport-azure-ad and OpenID Connect. My main query is - Is it mandatory to ...

gist-react: containing gist within a scrollable div

Struggling to contain a gist within a div with scrollbars on my next.js site using gist-react. It seems like my CSS is being overridden when the gist loads from the underlying dependency. Is there a way to achieve this without modifying the dependency itse ...

The use of Mongoose with an express server does not allow for posting of

Currently, I've been exploring Mongoose and working on a small project. Here's the setup: db.js var db = mongoose.connect('mongodb://localhost/boeken', function(){ console.log('mongoose connected'); }); module.exports = ...

Exploring ways to retrieve boolean values with Angular and PHP

I am currently learning Angular and PHP and I am trying to make some modifications to the tutorial found at . Specifically, I want to change the second value to a checkbox and retrieve its value using both Angular and PHP. However, I am encountering an iss ...

Looping HTML5 audio with Javascript

function switchSongs() { var songOptions = ['1507', '1530']; // array of available songs var audioPlayer = document.getElementsByTagName('audio')[0]; for (var i = 0; i < songOptions.length; i++) { i ...

Extracting all usernames of members present in a specific voice channel and converting them into a string using Node.js on Discord

Hey everyone, I'm looking for a code snippet that will help me retrieve all the members from a specific voice channel by using its ID. I also need to extract and store the usernames of these members who are currently in that particular voice channel w ...

Creating state management for reusable React components and managing browser history

I am currently exploring strategies for organizing state within my React components to achieve two objectives simultaneously: (1) effectively managing browser history in a complex application, and (2) facilitating easy reusability of individual components ...

Reordering div elements with JQuery

As soon as my page loads, I have a div set to display:block and another div set to display:none. I have implemented a toggle switch that should replace the visible div with the hidden one. However, I am facing an issue where after performing the switch, ...

Which is Better for Creating DropDown Menus: CSS or JavaScript?

Starting a new project that involves dropdown menus with categories and subcategories within them. I'm curious about the advantages of using CSS3 only menus compared to traditional JavaScript ones. There are several jQuery menu options available as we ...

The create document feature seems to be malfunctioning for some reason. Any ideas why it's not working properly in Firebase with Angular

I've been attempting to submit user data to the Firebase Firestore database, but I'm experiencing issues with the function that is supposed to create a new collection. Despite trying different methods, none of them seem to be working for me. I ha ...

Can you explain the distinction between Mongoose's Delete and the Express app.delete function?

As I dive into learning NodeJS and utilizing MongoDB with mongoose, I've come across an interesting comparison. The course I'm currently enrolled in focuses on using mongoose methods for "Delete" and "Update" operations, implementing Express to h ...

Solving the puzzle of filtering nested arrays in JavaScript

Consider a JavaScript object representing JSON data like this: [ { "Id": "8868dfdd-9b4e-4bad-a4ce-ecae6a3cc828", "Name": "Company 1", "Locations": [ { "Id": "bd017b9c-b62e-43aa-9f00-c164a855eed1", ...

How can I implement a promise loop in Angular that continues until it encounters a rejection?

My goal is to efficiently load around 10000 resources, but loading them all at once during the resolve phase is taking too long due to some calculations. I then had the idea to load the resources page by page sequentially, however, since all resources need ...

How can we bring in a JavaScript file to an Angular 2 project?

I've been struggling with importing a JavaScript file into my Angular2 project. This particular file is not a module from npm, and the usual instructions using npm don't apply in this case. My setup involves using Angular CLI, and within my angu ...

Adding several entries into mysql with the assistance of php

I've been attempting to input multiple records into my database table, but every time I try, all I see are zeros(0) inserted into the fields. Here's what I attempted: I used a foreach loop for insertion, but unfortunately it doesn't seem to ...

The interaction between a JavaScript function call and C# is not functioning properly

Attempting to invoke the JavaScript function from CodeBehind ( C# ) : function scrollToBottom() { window.scrollTo(0, document.body.scrollHeight); } The function successfully executes when directly called from my asp.net application. However, ...

Dynamic content display using AJAX

Having already tried to find a solution through Google with no success, I am at a loss. I have articles where a paragraph is initially displayed, followed by a "read more" link which reveals more content using JavaScript. However, this approach may slow do ...