'Detect browser's language with i18next-browser-languagedetector for reactJs web app

I have a reactJs application and I want to add localization to it. I have never used i18next before but I am trying to get used to it. My problem is, I cannot detect user's browser's in use language. This is my code could you please help me with some code, I have searched all documents and answers for this topic but I could not find any solution.

This is my i18n.js file and I am importing this in files that I want to use

import i18next from 'i18next';
import languageDetector from 'i18next-browser-languagedetector';
i18next
    .use(languageDetector)
    .init({
        debug: true,
        fallbackLng: "en",
        resources: {
            en: {
                translation: {
                    "table": {
                        "fortuneId": "FortuneId",
                        "name": "Name",
                        "age": "Age",
                        "date": "Date",
                        "relationship": "Relationship",
                        "note": "Note",
                        "topic": "Topic",
                        "question": "Question",
                        "gender": "Gender",
                        "rejected": "Rejected"
                    },

                    "auth": {
                        "signIn": "Sign In",
                        "signOut": "Sign Out",
                        "joinUs": "Join Us",
                        "goBack": "Go Back",
                        "email": "E-mail",
                        "username": "Username",
                        "password": "Password",
                    },

                    "admin": {
                        "employee": "Employees",
                        "moderator": "Moderator",
                        "admin": "Admin",
                        "refreshCounters": "Refresh Counters",
                        "refreshCounter": "Refresh Counter",
                        "setAsEmployee": "Set as Employee",
                        "setAsAdmin": "Set as Admin",
                        "setAsModerator": "Set as Moderator",
                        "email": "E-mail",
                        "password": "Password",
                        "answeredFortunes": "Answered Fortunes",
                        "controlledFortunes": "Controlled Fortunes",
                    },

                    "moderator": {
                        "approve": "Approve",
                        "reject": "Reject",
                        "topic": "Topic",
                        "name": "Name",
                        "age": "Age",
                        "date": "Date",
                        "relationship": "Relationship",
                        "gender": "Gender",
                        "answer": "Answer"
                    },

                    "answer": {
                        "fortuneId": "FortuneId",
                        "name": "Name",
                        "age": "Age",
                        "date": "Date",
                        "relationship": "Relationship",
                        "note": "Note",
                        "topic": "Topic",
                        "question": "Question",
                        "gender": "Gender",
                        "send": "Send",
                        "rejectionReason": "Rejection Reason",
                        "rejection": "Rejection",
                        "rejectedAnswer": "Rejected Answer",
                        "unassign": "Unassign"
                    },

                    "modal": {
                        "fortuneId": "FortuneId",
                        "name": "Name",
                        "age": "Age",
                        "date": "Date",
                        "relationship": "Relationship",
                        "note": "Note",
                        "topic": "Topic",
                        "question": "Question",
                        "gender": "Gender",
                        "assignToMe": "Assign to Me",
                        "cancel": "Cancel"
                    },

                    "profile": {
                        "name": "Name",
                        "age": "Age",
                        "email": "E-mail",
                        "answeredFortunes": "Answered Fortunes",
                        "controlledFortunes": "Controlled Fortunes",
                        "employeeTypeAdmin": "Admin",
                        "employeeTypeModerator": "Moderator",
                        "employeeTypeEmployee": "Employee",
                    },

                    "errors": {},
                }
            },
            tr: {
                translation: {
                    "table": {
                        "fortuneId": "FalId",
                        "name": "Ad",
                        "age": "Yaş",
                        "date": "Tarih",
                        "relationship": "İlişki Durumu",
                        "note": "Not",
                        "topic": "Konu",
                        "question": "Soru",
                        "gender": "Cinsiyet",
                        "rejected": "Reddedildi"
                    },

                    "auth": {
                        "signIn": "Giriş Yap",
                        "signOut": "Çıkış Yap",
                        "joinUs": "Bize Katıl",
                        "goBack": "Geri Dön",
                        "email": "E-mail",
                        "username": "Kullanıcı Adı",
                        "password": "Şifre",
                    },

                    "admin": {
                        "employee": "Yorumcu",
                        "moderator": "Moderatör",
                        "admin": "Admin",
                        "refreshCounters": "Sayaçları Sıfırla",
                        "refreshCounter": "Sayacı Sıfırla",
                        "setAsEmployee": "Yorumcu Yap",
                        "setAsAdmin": "Admin Yap",
                        "setAsModerator": "Moderatör Yap",
                        "email": "E-mail",
                        "password": "Şifre",
                        "answeredFortunes": "Gönderilen Fallar",
                        "controlledFortunes": "Kontrol Edilen Fallar",
                    },

                    "moderator": {
                        "approve": "Onayla",
                        "reject": "Reddet",
                        "topic": "Konu",
                        "name": "Ad",
                        "age": "Yaş",
                        "date": "Tarih",
                        "relationship": "İlişki Durumu",
                        "gender": "Cinsiyet",
                        "answer": "Fal Gönderi"
                    },

                    "answer": {
                        "fortuneId": "FalId",
                        "name": "Ad",
                        "age": "Yaş",
                        "date": "Tarih",
                        "relationship": "İlişki Durumu",
                        "note": "Not",
                        "topic": "Konu",
                        "question": "Soru",
                        "gender": "Cinsiyet",
                        "send": "Gönder",
                        "rejectionReason": "Reddedilme Nedeni",
                        "rejection": "Reddedilme",
                        "rejectedAnswer": "Reddedilen Gönder",
                        "unassign": "Fal'ı Bırak"
                    },

                    "modal": {
                        "fortuneId": "FalId",
                        "name": "Ad",
                        "age": "Yaş",
                        "date": "Tarih",
                        "relationship": "İlişki Durumu",
                        "note": "Not",
                        "topic": "Konu",
                        "question": "Soru",
                        "gender": "Yaş",
                        "assignToMe": "Bana Ata",
                        "cancel": "İptal"
                    },

                    "profile": {
                        "name": "Ad",
                        "age": "Yaş",
                        "email": "E-mail",
                        "answeredFortunes": "Gönderilen Fallar",
                        "controlledFortunes": "Kontrol Edilen Fallar",
                        "employeeTypeAdmin": "Admin",
                        "employeeTypeModerator": "Moderatör",
                        "employeeTypeEmployee": "Yorumcu",
                    },

                    "errors": {},
                }
            }
        }
    });

export default i18next;

In those files I use this like

   import i18next from "../../Localization/i18n";
   <div>
     {i18next.t('table.question')}
   </div>

This shows me "Question" in web page but if I change my google chrome browser to Turkish, it is still in english. I do not know what I am missing.

Thank you for your help



Solution 1:[1]

Hopefully this helps someone in the future. I tried @Ergin 's answer above but that didn't work, and Typescript was throwing errors about passing 0 params when I used this suggestion:

//*** call without param to use language detector
i18n.changeLanguage()

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

Solution 2:[2]

ran into this issue myself, changing my browser's default language does nothing enter image description here

But everything make sense after I look into the documentation https://github.com/i18next/i18next-browser-languageDetector

// order and from where user language should be detected
  order: ['querystring', 'cookie', 'localStorage', 'sessionStorage', 'navigator', 'htmlTag', 'path', 'subdomain'],

The i18next language detector first check queryString, that's why using http://localhost:3000?lng=es work, since it is the first thing it check.

Then next check cookie, then next I check localStorage and found english is stored. enter image description here

Deleting this value and refresh the page, I see the page is updated to the new language

Solution 3:[3]

this helped me.

(thanks to: https://velog.io/@hyounglee/TIL-80)

 import i18n from "i18next";
import { initReactI18next } from "react-i18next";
import XHR from "i18next-http-backend";
import LanguageDetector from "i18next-browser-languagedetector";

import translationEn from "../src/lang/translation.en.json";
import translationKo from "../src/lang/translation.ko.json";

const languages = ["en", "ko"]; // (*)

const resource = {
  en: {
    translation: translationEn,
  },
  ko: {
    translation: translationKo,
  },
};

i18n
  .use(XHR)
  .use(initReactI18next)
  .use(LanguageDetector)
  .init({
    // detection: options,
    detection: { order: ["path", "navigator"] },
    fallbackLng: "en",
    resources: resource,
    whitelist: languages,
    //lng: "ko",
    // ns: ['translation'],
    // defaultNS: "translation",
    debug: true,

    keySeparator: false, // we do not use keys in form messages.welcome
    interpolation: {
      escapeValue: false, // react already safes from xss
    },
  });

export default i18n;

Solution 4:[4]

A little late to the game but hopefully can benefit the community, I've started working with react-i18next recently and also ran into this problem. I found this post which has a sublink which points to this line in the source:

https://github.com/i18next/i18next/blob/ee3afd8e5d958e8d703a208194e59fa5228165fd/src/i18next.js#L189

if (!lng && this.services.languageDetector) lng = this.services.languageDetector.detect();

This shows that if you call changeLanguage() without any arguments it will attempt to do language detection based on the priority you have configured. So to get this working I do the following:

i18n
  .use(LanguageDetector)
  .use(initReactI18next) // passes i18n down to react-i18next
  .init({
    resources,
    lng: "en",
    detection: detectOptions,
    interpolation: {
      escapeValue: false // react already safes from xss
    }
  });

//*** call without param to use language detector
i18n.changeLanguage()

After doing this the URL query parameter now works, for example:

www.example.com/route/?lng=tr

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 BabyishTank
Solution 3 Dharman
Solution 4 Ergin