'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
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.
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 |