How can we use react query in i18next configuration

445 views Asked by At

I'm using i18next library to implement localisation in my react app, where I've to call an API to get the localisation in a response. But I want to use react query to call an API, and I know that react query being a hook can only be called in functional component, so I'm unable to use react query. Did anyone faced this error?

My i18next configuration.

export const getLocalisation = async (lng: string) => {
    try {
        const localisationResponse = await axios.get(
            `/localisation/${lng}`
        );
        return localisationResponse;
    } catch (err) {
        console.log('Error at getLocalisation: ', err);
    }
};
const backendOptions = {
    allowMultiLoading: true,
    loadPath: `/localisation/en`,
    request: (options: any, url: any, payload: any, callback: any) => {
        try {
            getLocalisation(EN).then((result) => {
                callback(null, {
                    data: result?.data,
                    status: STATUS_CODE_200
                });
            });
        } catch (e) {
            console.error(e);
            callback(e); // Passing `e` will handle error status code
        }
    }
};

i18n
    .use(HttpBackend)
    .use(LanguageDetector)
    .use(initReactI18next)
    .init({
        debug: false,
        fallbackLng: EN,
        supportedLngs: [EN],
        ns: [],
        partialBundledLanguages: true,
        interpolation: {
            escapeValue: false
        },
        backend: backendOptions
    });

export default i18n;

When using react query, getting following error/warning. enter image description here

1

There are 1 answers

0
3oax On

You could to something like this:

import i18n from "i18next";
import { useCallback, useLayoutEffect } from "react";
import { initReactI18next } from "react-i18next";
import { useI18nQuery } from "../hooks/useApiQueries";
import { APP_LANGUAGE_DEFAULT, APP_LANGUAGE_SUPPORTS } from "../utils/const";

i18n
  .use(initReactI18next)
  .init({
    partialBundledLanguages: true,
    interpolation: {
      escapeValue: false
    },
    fallbackLng: APP_LANGUAGE_DEFAULT, // 'en'
    supportedLngs: APP_LANGUAGE_SUPPORTS,  // ['en', 'de']
    ns: [],
    resources: {}
});

const AppTranslation: React.FC<{lang?: string, children?: React.ReactNode;}> = ({ lang, children }) => {
  
  const _lang = lang || 'en';
  const i18nQuery = useI18nQuery( _lang );

  const initLang = useCallback(() => {

    if( !i18nQuery.data ) return;

    i18n.addResourceBundle('de', 'app', i18nQuery.data.de);
    i18n.addResourceBundle('en', 'app', i18nQuery.data.en);
    i18n.setDefaultNamespace('app');

  }, [ i18nQuery.data ])

  const removeLang = useCallback(() => {

    if( !i18nQuery.data ) return;
    
    i18n.removeResourceBundle('de', 'app');
    i18n.removeResourceBundle('en', 'app');
    
  }, [ i18nQuery.data ])

  useLayoutEffect(() => {
    initLang();
    return () => {
      removeLang()
    };
  }, [ i18nQuery.isLoading ]);
  
  return children;
}

export default AppTranslation;

then in your index or where you load your app component:

...
<QueryClientProvider client={queryClient}>
  <AppTranslation />
  <App />
</QueryClientProvider>
...

and then you can just use the

const { t } = useTranslation()

hook where you want.