miuosh
miuosh

Reputation: 906

i18next-browser-languageDetector path not working

I have a problem with detecting language based on path i.e. http://localhost:3000/en or http://localhost:3000/en/subpage should translate my page to English. I can translate it by clicking the button and invoke i18n.changeLanguage('en') but detector seems not working.

import i18n from "i18next";
import { reactI18nextModule } from "react-i18next";
import LngDetector from "i18next-browser-languagedetector";
import backend from "i18next-xhr-backend";


const detectionOptions = {
    order: ['path', 'cookie', 'navigator', 'localStorage', 'subdomain', 'queryString', 'htmlTag'],
    lookupFromPathIndex: 0

}


i18n
    .use(LngDetector)
    .use(backend)
    .use(reactI18nextModule) // passes i18n down to react-i18next
    .init({
        ns: ['translation', 'main'],
        defaultNS: 'translation',
        lng: "pl",
        fallbackLng: 'pl',
        detection: detectionOptions,
        keySeparator: false, // we do not use keys in form messages.welcome

        interpolation: {
            escapeValue: false // react already safes from xss
        },
        debug: true,
        react: {
            wait: true
        }
    }, (err, t) => {
        if (err)
            console.error(err)
    });


export default i18n;

Upvotes: 3

Views: 16036

Answers (5)

Mitch
Mitch

Reputation: 160

I also still have trouble with the order option of i18next-browser-languagedetector. It will not work properly when enabling the queryString and the path optoin together. It will alsways read the path and ignore the query part.

My code looks like this. But I guess it's a plugin issue?

import i18next from "i18next";
import LanguageDetector from "i18next-browser-languagedetector";

const detectionOptions = {
  order: ["queryString", "path", "cookie"],
  lookupFromPathIndex: 0,
  lookupQuerystring: "lng",
  lookupCookie: "meine_nanny_i18next",
};

i18next.use(LanguageDetector).init({
  fallbackLng: "de",
  resources: {
    de: {
      common: require("../locales/de/common.json"),
    },
    en: {
      common: require("../locales/en/common.json"),
    },
  },
  ns: ["common"],
  defaultNS: "common",
  detection: detectionOptions,
  returnObjects: true,
  debug: process.env.NODE_ENV === "development",
  interpolation: {
    escapeValue: false, // not needed for react!!
  },
  react: {
    wait: true,
  },
});

i18next.languages = ["de", "en"];

export default i18next;

Upvotes: 1

Marzieh Mousavi
Marzieh Mousavi

Reputation: 1624

I had same issue and my code was exactly like original example, then i realized i didn't have 'i18next-browser-languagedetector' so i simply do this and problem solved!

npm i i18next-browser-languagedetector

Upvotes: 0

Dimitriy
Dimitriy

Reputation: 135

Path option sometimes doesn't work, because your previous value of language is stored in browser cache and continues to be used. For resolve this trouble you should clean the cache. You can see it in Application -> Local Storage. In my case I set the following option in i18n.tsx and all work fine.

detection: {
  order: ['path'],
  caches: [],
}

This line cleans the cache :

caches: []

Upvotes: 0

taco_friday
taco_friday

Reputation: 609

Hopefully this helps someone in the future. The documentation doesn't exactly give you the full picture of how to set up detection, and then I found a closed Github issue where several people were asking a reasonable question, and the maintainers were kinda rude in their responses but also happened to supply a link that should have been in the documentation. It cleared up my issue with a few small adjustments from what the current documentation states to do.

I was then able to get language detection in my url with https:www.domain.com?lng=es as well as when using a browser extension that let me change the browser language.

Heres my working i18n.ts file:

import i18n from 'i18next'
import LanguageDetector from 'i18next-browser-languagedetector'
import { initReactI18next } from 'react-i18next'
import XHR from "i18next-http-backend" // <---- add this

import commonDe from './locales/de/common.json'
import commonEn from './locales/en/common.json'
import commonEs from './locales/es/common.json'
import commonFr from './locales/fr/common.json'

const resources = {
  de: { common: commonDe },
  en: { common: commonEn },
  es: { common: commonEs },
  fr: { common: commonFr }
}

const options = {
  order: ['querystring', 'navigator'],
  lookupQuerystring: 'lng'
}

i18n
  .use(XHR) // <---- add this
  .use(LanguageDetector)
  .use(initReactI18next)
  .init({
    // lng: 'en' // <--- turn off for detection to work
    detection: options,
    resources,
    ns: ['common'],
    defaultNS: 'common',
    fallbackLng: 'en',
    supportedLngs: ['de', 'en', 'es', 'fr'],
    interpolation: {
      escapeValue: false,
    },
    debug: false,
  })

export default i18n

(bonus help - if theres anyone jammed up on this part)

I am working in a Next.js project, and the above file was loaded in the project-root/pages/_app.tsx file like this:

import React from 'react'
import { AppProps } from 'next/app'
import '../i18n/i18n'

import '../public/styles.css'

const TacoFridayApp = ({ Component, pageProps}: AppProps): JSX.Element => {
  
  return <Component {...pageProps} />
}

export default TacoFridayApp

Upvotes: 7

miuosh
miuosh

Reputation: 906

Solution: i18n.lng property should not be set to when using language detector

Upvotes: 16

Related Questions