Next-i18next: i18next doesn't switch to other language, is stucked in the default one

Created on 24 Sep 2019  路  6Comments  路  Source: isaachinman/next-i18next

Describe the bug

i18next update doesnt update the text when switching to other language.

So the issue is i dont get any error. so i click to change language button expecting to see the text change, but i doesn't work.
seems to be stuck in english on load
i only get in the terminal a warning about namespaces:

You have not declared a namespacesRequired array on your page-level component: ErrorPage. This will cause all namespaces to be sent down to the client, possibly negatively impacting the performance of your app. For more info, see: https://github.com/isaachinman/next-i18next#4-declaring-namespace-dependencies

Locales

locales/en/common.json
locales/es/common.json
locales/de/common.json
locales/fr/common.json

sample:

{
  "hello": "Hello",
  "language": {
    "english" : "english",
    "french" : "french",
    "german" : "german",
    "spanish" : "spanish"
  }
}

Occurs in next-i18next version

"next": "^9.0.1",
"next-i18next": "^1.2.1",

"engines": {
    "node": "^12.6.0",
    "npm": "^6.10.0",
    "yarn": "^1.17.0"
  },

OS

  • Device: MBP OS Mojave 10.14.6
  • Browser: Version 76.0.3809.132 (Official Build) (64-bit)

Files

i18n.js

const NextI18Next = require('next-i18next').default

module.exports = new NextI18Next({
  browserLanguageDetection: true,
  serverLanguageDetection:  true,
  defaultNS: 'common',
  defaultLanguage: 'en',
  ignoreRoutes: ['/_next/', '/static/'],
  otherLanguages: ['de, es, fr'],
  localeExtension:'json',
  localePath:   'locales',
  localeStructure: '{{lng}}/{{ns}}',
  localeSubpaths: {
    de: 'german',
    en: 'eng',
    es: 'esp',
    fr: 'french'
  }
})

聽server.js

const express = require('express');
const next = require('next');
const nextI18NextMiddleware = require('next-i18next/middleware').default;

// i18n middleware setup options
const NextI18NextInstance = require('./i18n');

const port = parseInt(process.env.PORT || 3000, 10);
const dev = process.env.NODE_ENV !== 'production';
const app = next({ dev });
const handle = app.getRequestHandler();

(async () => {
  await app.prepare();
  const server = express();

  // i18n middleware to handle multilingual app
  try {
    server.use(nextI18NextMiddleware(NextI18NextInstance))
  } catch (e) {
    throw (e)
  }

  // Handle nextjs routing
  server.get('*', (req, res) => handle(req, res));

  await server.listen(port);
  console.info(`> Ready on http://localhost:${port}`);
})();

pages/_app.tsx

import App from 'next/app'
import React from 'react'
import withRedux from 'next-redux-wrapper'
import { Provider } from 'react-redux'
import { ThemeProvider } from 'styled-components';

import i18n from '../i18n';

import { theme } from '../styles/reset';
import { initStore } from '../redux/store'

export interface AppProps {
  store: any
}

export interface AppState { }

class MyApp extends App<AppProps, AppState> {
  static async getInitialProps({ Component, ctx }) {

    const pageProps = Component.getInitialProps ? await Component.getInitialProps(ctx) : {}

    return { pageProps }
  }

  render() {
    const { Component, pageProps, store } = this.props

    return (
      <ThemeProvider theme={theme}>
        <Provider store={store}>
          <Component {...pageProps} />
        </Provider>
      </ThemeProvider>
    )
  }
}

export default withRedux(initStore)(i18n.appWithTranslation(MyApp))

pages/index.tsx

import {聽Fragment } from 'react'
import { connect } from 'react-redux'

import i18next from '../i18n';

const IndexPage = ({ mediaType }) => {
  const { t, i18n } = i18next.useTranslation()

  return (
    <Fragment>
      <h1>{t('hello')}</h1>
      <p>{i18n.language}</p>
      <button type='button' onClick={() => i18n.changeLanguage('en')}>{t('language.spanish')}</button>
      <button type='button' onClick={() => i18n.changeLanguage('es')}>{t('language.spanish')}</button>
      <button type='button' onClick={() => i18n.changeLanguage('fr')}>{t('language.french')}</button>
      <button type='button' onClick={() => i18n.changeLanguage('de')}>{t('language.german')}</button>
    </Fragment>
  )
}

/* IndexPage.getInitialProps = () => {
  return {
    namespacesRequired: i18next.includeDefaultNamespaces
  };
}; */


const mapStateToProps = ({ browser }) => {
  const { mediaType } = browser

  return { mediaType }
}

const withRedux = connect(mapStateToProps)

export default withRedux(IndexPage)

Most helpful comment

@isaachinman

I have read the documentation and i set the localePath to dont use the static folder, and use locales instead.

Anyway if i move the locales into a static folder and remove the localePath key to use the defaults. problem persist...

i18n.js

module.exports = new NextI18Next({
  browserLanguageDetection: true,
  serverLanguageDetection:  true,
  defaultNS: 'common',
  defaultLanguage: 'en',
  ignoreRoutes: ['/_next/', '/static/'],
  otherLanguages: ['de, es, fr'],
  localeExtension:'json',
  localePath:   'locales',     //  Problem persist if i comment this line and use ./static/locales
  localeStructure: '{{lng}}/{{ns}}',
  localeSubpaths: {
    de: 'german',
    en: 'eng',
    es: 'esp',
    fr: 'french'
  }
})

All 6 comments

Please provide a repository.

Describe the bug

i18next update doesnt update the text when switching to other language.

So the issue is i dont get any error. so i click to change language button expecting to see the text change, but i doesn't work.
seems to be stuck in english on load
i only get in the terminal a warning about namespaces

Locales

locales/en/common.json
locales/es/common.json
locales/de/common.json
locales/fr/common.json

sample:

{
  "hello": "Hello",
  "language": {
    "english" : "english",
    "french" : "french",
    "german" : "german",
    "spanish" : "spanish"
  }
}

Occurs in next-i18next version

"next": "^9.0.1",
"next-i18next": "^1.2.1",

"engines": {
    "node": "^12.6.0",
    "npm": "^6.10.0",
    "yarn": "^1.17.0"
  },

OS

  • Device: MBP OS Mojave 10.14.6
  • Browser: Version 76.0.3809.132 (Official Build) (64-bit)

Files

i18n.js

const NextI18Next = require('next-i18next').default

module.exports = new NextI18Next({
  browserLanguageDetection:   true,
  serverLanguageDetection:    true,
  defaultNS: 'common',
  defaultLanguage: 'en',
  ignoreRoutes:   ['/_next/', '/static/'],
  otherLanguages: ['de, es, fr'],
  localeExtension:'json',
  localePath: 'locales',
  localeStructure: '{{lng}}/{{ns}}',
  localeSubpaths: {
    de: 'german',
    en: 'eng',
    es: 'esp'
    fr: 'french'
  }
})

聽server.js

const express = require('express');
const next = require('next');
const nextI18NextMiddleware = require('next-i18next/middleware').default;

// i18n middleware setup options
const NextI18NextInstance = require('./i18n');

const port = parseInt(process.env.PORT || 3000, 10);
const dev = process.env.NODE_ENV !== 'production';
const app = next({ dev });
const handle = app.getRequestHandler();

(async () => {
  await app.prepare();
  const server = express();

  // i18n middleware to handle multilingual app
  try {
    server.use(nextI18NextMiddleware(NextI18NextInstance))
  } catch (e) {
    throw (e)
  }

  // Handle nextjs routing
  server.get('*', (req, res) => handle(req, res));

  await server.listen(port);
  console.info(`> Ready on http://localhost:${port}`);
})();

pages/_app.tsx

import App from 'next/app'
import React from 'react'
import withRedux from 'next-redux-wrapper'
import { Provider } from 'react-redux'
import { ThemeProvider } from 'styled-components';

import i18n from '../i18n';

import { theme } from '../styles/reset';
import { initStore } from '../redux/store'

export interface AppProps {
  store: any
}

export interface AppState { }

class MyApp extends App<AppProps, AppState> {
  static async getInitialProps({ Component, ctx }) {

    const pageProps = Component.getInitialProps ? await Component.getInitialProps(ctx) : {}

    return { pageProps }
  }

  render() {
    const { Component, pageProps, store } = this.props

    return (
      <ThemeProvider theme={theme}>
        <Provider store={store}>
          <Component {...pageProps} />
        </Provider>
      </ThemeProvider>
    )
  }
}

export default withRedux(initStore)(i18n.appWithTranslation(MyApp))

pages/index.tsx

import {聽Fragment } from 'react'
import { connect } from 'react-redux'

import i18next from '../i18n';

const IndexPage = ({ mediaType }) => {
  const { t, i18n } = i18next.useTranslation()

  return (
    <Fragment>
      <h1>{t('hello')}</h1>
      <p>{i18n.language}</p>
      <button type='button' onClick={() => i18n.changeLanguage('en')}>{t('language.spanish')}</button>
      <button type='button' onClick={() => i18n.changeLanguage('es')}>{t('language.spanish')}</button>
      <button type='button' onClick={() => i18n.changeLanguage('fr')}>{t('language.french')}</button>
      <button type='button' onClick={() => i18n.changeLanguage('de')}>{t('language.german')}</button>
    </Fragment>
  )
}

/* IndexPage.getInitialProps = () => {
  return {
    namespacesRequired: i18next.includeDefaultNamespaces
  };
}; */


const mapStateToProps = ({ browser }) => {
  const { mediaType } = browser

  return { mediaType }
}

const withRedux = connect(mapStateToProps)

export default withRedux(IndexPage)

Hi. In property localePath write path from the root project, static/locales.

Please provide a repository.

Hi @isaachinman , sorry the delay i had to created from the scratch to do a clean sample case

Repository
yarn dev

Presumably, your language is not changing because the call to your locales destination is 404'ing, because you haven't put your locales inside the NextJs static dir.

I suggest you read the documentation carefully, and heed advice from fellow users like @FMakareev.

@isaachinman

I have read the documentation and i set the localePath to dont use the static folder, and use locales instead.

Anyway if i move the locales into a static folder and remove the localePath key to use the defaults. problem persist...

i18n.js

module.exports = new NextI18Next({
  browserLanguageDetection: true,
  serverLanguageDetection:  true,
  defaultNS: 'common',
  defaultLanguage: 'en',
  ignoreRoutes: ['/_next/', '/static/'],
  otherLanguages: ['de, es, fr'],
  localeExtension:'json',
  localePath:   'locales',     //  Problem persist if i comment this line and use ./static/locales
  localeStructure: '{{lng}}/{{ns}}',
  localeSubpaths: {
    de: 'german',
    en: 'eng',
    es: 'esp',
    fr: 'french'
  }
})

Hi @HectorLS , did you solve the issue? It seems it's a common problem. next-18next often doesn't load other languages except for the default one.

Was this page helpful?
0 / 5 - 0 ratings