Can I detect when a language is detected for the first time using i18next-browser-languageDetector?
I have a react app that I have translated into several languages, and also contains some date formatting functionality. I would like to for example, allow the user to change between 12h and 24h time, however when switching to German, automatically change that option to 24h (as Germany typically doesn't use 12h time).
I still want this option to be able to be changed by the user, and I also don't want it to be reset to 24h every time the page reloads.
I'm using i18next
and i18next-browser-languageDetector
to detect the browser language, and currently I have an event bound to i18next
for when the language is manually changed by the user, in order to set these default settings per language, and this works perfectly:
i18n.on('languageChanged', lang => {
// Language specific options
if (lang === 'de') {
store.setTimeFormat('24h');
}
if (lang === 'en') {
store.setTimeFormat('12h');
}
});
Now, the only problem is that this function is not triggered when first loading the app, i.e. when the browser detector first detects the user's language.
How can I determine when i18next-browser-languageDetector
initially detects the language, that is, not loading from localstorage, but a query string of lng=de
for example would trigger it, so that I can set these settings?
I managed to solve this issue by first checking if a language had been saved in localstorage, adding this to the i18next options object, then I could check this later to set the defaults.
import i18n from 'i18next';
import { initReactI18next } from 'react-i18next';
import LanguageDetector from 'i18next-browser-languagedetector';
import Backend from 'i18next-http-backend';
// Check the localstorage before i18next can
const storedLang = localStorage.getItem('i18nextLng');
i18n
.use(LanguageDetector)
.use(Backend)
.use(initReactI18next)
.init({
fallbackLng: 'en',
interpolation: {
escapeValue: false,
},
backend: {
loadPath: '/i18n/{{lng}}/{{ns}}.json',
},
storedLang, // Add it here
});
export default i18n;
Then in my component, I can put the following in the function:
import { useTranslation } from 'react-i18next';
import { mySettingsStore } from 'stores';
const setDefaults = (lang, store) => {
// Language specific options
if (lang === 'de') {
store.setTimeFormat('24h');
}
if (lang === 'en') {
store.setTimeFormat('12h');
}
// etc...
};
const Component = () => {
const store = mySettingsStore(); // zustand store
const { i18n } = useTranslation();
// If localstorage was empty: no language set
if (!i18n.options.storedLang) {
setDefaults(i18n.language, store);
i18n.options.storedLang = i18n.language;
}
// Language changed manually
i18n.on('languageChanged', lang => {
setDefaults(lang, store);
});
return (...);
};
export default Component;
This method doesn't however update the options if a language is set via query string, e.g. https://my.app?lng=de
, if a language is already set in the localstorage. This could be remedied by also checking the query string parameters in the same way, but it could quickly become cumbersome to maintain if more options are used, e.g. session storage, cookies, etc.