Support for internationalization (i18n) does not work with next export in NextJS 10, as it is not compatible with

NextJS Export Not Compatible with i18n Support

i18n Feature Cannot Be Used for Deployment in NextJS

Running NextJS 10 has been a great choice for me as it allows for Server-Side Rendering (SSR) and utilization of the i18n feature. Internationalized Routing is a new feature in NextJS 10 that has its own dedicated page.

However, when attempting to deploy, I encountered this error: i18n support is not compatible with next export. This issue is not addressed on the Internationalized Routing page.

Code Implementation

next.config.js

const withImages = require('next-images')
const path = require('path')

module.exports = withImages({
    esModule: false,
    i18n: {
        locales: ['en-US', 'pt-BR', 'pt-PT', 'es-ES'],
        defaultLocale: 'pt-BR',
      },
});

I have created translation files that work based on conditions from the next router. Note: PT and EN are JSON files containing text content.

import * as pt from "./pt";
import * as en from './en';
import { useRouter } from "next/router"

export const traducao = () =>{
  let routes = useRouter();

  let translate;
 
    if (routes.locale == 'pt-PT' || routes.locale == 'pt-BR') {
      translate = pt.default;
    } else {
      translate = en.default;
    }
  
  return translate 
}

Using this function in my project:

{traducao().homeText.button_text}

It works well, detecting browser language and switching accordingly. I am using the following deployment script:

npm run deploy
"deploy": "npm run clean && npm run build && next export -o dist/"

Reproduction Steps

  1. Navigate to 'next.config.js'
  2. Create the i18n export
  3. Generate a Translate file that can detect browser language
  4. Import JSON files containing your site's text content
  5. Implement translations where needed
  6. Attempt deployment

Expected Outcome

The deployment should proceed smoothly without any issues.

Screenshots

System Details

  • OS: Linux Ubuntu
  • IDE: VSCode
  • Next.js Version: 10
  • Node.js Version: v15.3.0
  • Deployment Method: next deploy

Answer №1

In my quest to find solutions on vercel's github, I stumbled upon an interesting alternative that eliminates the need for next-i18next or any other nextjs magic:

https://github.com/Xairoo/nextjs-i18n-static-page-starter

This solution simply involves basic i18n implementation using i18next, which bundles all locale data together with JS. While there are some tradeoffs involved, it does work well with SSG. There is room for further customization and enhancements based on this foundation. That's the approach I plan to take moving forward.

Answer №2

If you want to bypass the i18n feature of next.js and handle language detection on your own, there is an alternative approach. You can create a custom language detector using the next-language-detector module as outlined in this blog post. Here's an example:

// customLanguageDetector.js
import languageDetector from 'next-language-detector'
import i18nextConfig from '../next-i18next.config'

export default languageDetector({
  supportedLngs: i18nextConfig.i18n.locales,
  fallbackLng: i18nextConfig.i18n.defaultLocale
})

// redirectHandler.js
import { useEffect } from 'react'
import { useRouter } from 'next/router'
import languageDetector from './customLanguageDetector'

export const useCustomRedirect = (to) => {
  const router = useRouter()
  to = to || router.asPath

  // Handle language detection
  useEffect(() => {
    const detectedLng = languageDetector.detect()
    if (to.startsWith('/' + detectedLng) && router.route === '/404') { // Prevent infinite loop
      router.replace('/' + detectedLng + router.route)
      return
    }

    languageDetector.cache(detectedLng)
    router.replace('/' + detectedLng + to)
  })

  return <></>
};

export const CustomRedirectHandler = () => {
  useCustomRedirect()
  return <></>
}

// eslint-disable-next-line react/display-name
export const getCustomRedirectHandler = (to) => () => {
  useCustomRedirect(to)
  return <></>
}

For a detailed guide and more code examples, refer to these resources:

Answer №3

Next.js i18n implementation does not support the use of export.

It's important to note that Internationalized Routing is not compatible with next export because next export does not make use of the Next.js routing layer. However, Hybrid Next.js applications that do not utilize next export are fully compatible.

Visit Next.js documentation

Answer №4

Greetings! Below is my solution using only i18n-js:

// i18n.ts
import i18n from "i18n-js";

import en from "./en.json";
import fr from "./fr.json";

const localeEnable = ["fr", "en"];

const formatLocale = () => {
  const { language } = window.navigator;
  if (language.includes("en")) return "en";
  if (language.includes("fr")) return "fr";
  if (!localeEnable.includes(language)) return "en";

  return "en";
};
// Define key-value pairs for supported languages.
i18n.translations = {
  en,
  fr,
};
// Set the initial locale for the app.
i18n.locale = "en";

const useTranslate = () => {
  return (t: string) => {
    if (typeof window !== "undefined") {
      i18n.locale = formatLocale();
    }
    return i18n.t(t);
  };
};

export default useTranslate;

// home.tsx
import useTranslate from "../locales/i18n";

const t = useTranslate();

return (<p>{t("idstring")}</p>)

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

"Comparing the Surprising Performance Discrepancy Between Safari's Private and Regular

While debugging OpenSpeedTest for 10Gbps, I noticed a significant performance gap between using a Private window versus a Normal window. https://i.sstatic.net/gSMuw.jpg I'm puzzled as to why this disparity exists. What steps should I take to investi ...

The Xero Node OAuth Authorize Callback URL is malfunctioning after granting access

When utilizing the xero-node library to produce a Request Token using the getRequestToken function, the URL provided does not automatically redirect the user to the designated callback address specified in the configuration. Instead, a screen displaying a ...

The changes made by this.students.splice(index, 1) are not reflecting in the Angular UI

I am attempting to remove a student object from a students array within my parent component. The student is removed by passing their name to the method. However, the view does not reflect this change. Below is my code for the delete method utilizing splice ...

The argument for the e2e test is invalid because it must be a string value

Currently, I am conducting an end-to-end test for an Angular application using Protractor. However, I encountered an error while running the test for a specific feature file. The UI value that I am checking is - WORKSCOPES (2239) Below is the code snippe ...

Timing of Bindings in AngularJS

In my setup, I have a controller that calls a service to retrieve a list of categories: $scope.enquiryCategories = CategoryServices.listCategories(); The service then fetches this data from an external API: listCategories: function () { return $http({ ...

Refresh the webpage after a mobile device is awakened from sleep mode

I have developed a custom countdown clock using Javascript, HTML, PHP, and MySQL. Upon clicking "Start Countdown," the epoch time is saved in the database and the countdown begins. After reloading the page, the script retrieves the initial countdown star ...

Error message stating that there is an issue with the `this.extButton` variable being null when attempting to manually adjust the toolbar settings for

When using aloha in a web application, I have found it to be very effective and capable of performing all necessary tasks. However, I have run into an issue when attempting to customize the toolbar with the following settings: Aloha.settings = { ... ...

Using Material-UI version 1, pass the outer index to the MenuItem component when clicked

Within my component, there is a Table that displays rows generated from a custom array of objects. In the last TableCell, I aim to include an icon button that, upon being clicked, opens a Menu containing various MenuItem actions (such as edit and delete). ...

acquire information using ajax in conjunction with jquery

I am currently working with the following code: <div data-role="content"> <div data-role="content"> <form id="registerForm" action="/register" method="post" data-ajax="false" class="ui-body ui-body-a ui-corner-al ...

In production, NextJS struggles to acknowledge dynamically added static assets

I currently have a setup with two docker containers: NextJS for the public-facing web and Django backend for content management. The routing is functioning well using getInitialProps, which retrieves the added content. To connect static images referenced b ...

The module cannot be located: Unable to find '../typings' in '/vercel/path0/pages'

Having trouble deploying my Next.js website through Vercel. It seems to be stuck at this stage. Can someone assist me, please? I've attempted deleting the node_modules folder and package-lock.json, then running npm install again, but unfortunately it ...

Storing, Transmitting, and Fetching information using AngularJS

My goal is to create a news object with separate sub-sections that can be added and removed by the user. You can see an example of how it should look here. When the save button is pressed, the data should be sent in the following JSON structure with each ...

Javascript lags behind in utilizing Regex compared to PHP

My regex string is used to extract a value from CSS code like this: body { background: #000; } /* drapeDecalage: 10px */ I am trying to parse the commented drapeDecalage value. I have created a regex expression for that: (?<=\/\* drape ...

Linking functions as needed

I apologize for the not-so-great title of this question. Basically, I have a library that generates users with predetermined capabilities. Currently, it involves creating a new user instance and calling asynchronous methods like: var User = require(...).U ...

How can we efficiently retrieve data for both page content and title with a single call using generateMetadata in Next.js (App Router)?

I'm looking to dynamically update the title with Next.js (App Router). The current code I have achieves this task, but it makes two API calls which seems unnecessary. Is there a way to optimize this to just one API call? export async function generat ...

Using JSON parsing to dynamically create classes with preloaded background images

Today, I successfully deployed my browser game using MVC4 to my website for the first time. I am currently navigating through the differences between running the site off of localhost and running it from the actual website. My process involves loading all ...

Issue with THREEJS: Unable to load jpg file as material map when assigning it to an object

I am having trouble getting the camouflage pattern to apply to the bow. camo.jpg is the image I want to use for the riser child object: https://i.sstatic.net/V1imW.jpg After rendering with three.js, this is how the bow looks: https://i.sstatic.net/iQjw1. ...

Manually browse through images in photoswipe by clicking on them to move to the previous or next ones

Utilizing photoswipe within my mobile app has been a seamless experience. Instead of utilizing the full screen view, we are displaying images within a target div. A new requirement was introduced to hide the built-in toolbar and incorporate arrow buttons ...

Finding parent elements using parentElementArrayFinder

Is there a specific attribute called parentElementArrayFinder within an ElementFinder object that can retrieve the parent element? var myElement = $(".myclass"); var parentElement = myElement.parentElementArrayFinder; Although not listed in Protractor&ap ...

Insert to the beginning of an array using VueJs

I need to add data at the beginning of an array in VueJs: numbers: [ ], this.numbers.unshift({ number: 1 }) Is there a way to prepend instead of append? ...