user15030566
user15030566

Reputation:

Language Switcher with React and Next

My idea of switching between languages is to click on flag (when clicked, the flag will change as well as the language). I am doing well so far, flag is switching and url path too, but I can not make the switch between translations.

For handling url's I am using build in Next option i18n and for actual language translations I am using react-i18next.

My i18next file is pretty straight forward:

i18n.use(LanguageDetector)
    .use(initReactI18next)
    .init({
        resources: {
            en: {
                translation: translations_EN_homePage,
            },
            da: {
                translation: translations_DA_homePage,
            },},});

Changing language hook and handleOnclick function:

const [language, setLanguage] = useState('en');

const handleOnclick = (e) => {
    e.preventDefault();
    setLanguage(e.target.value);
    i18n.changeLanguage(e.target.value);
};

And finally solution for my button = flag

                    <button
                        value={language === 'en' ? 'da' : 'en'}
                        onClick={() => {
                            const locale = router.locale === 'en' ? 'da' : 'en';
                            setCookie(locale);
                            {handleOnclick}
                            router.push(
                                `/${locale}`,
                                `/${locale}`,
                                {locale: false,}}} >
                        {router.locale === 'en' ? (
                            <img
                                src={menuItems.data.body[5].items[0].image.url}/>
                        ) : (
                            <img src={menuItems.data.body[4].items[0].image.url} />
                        )}
                    </button>

Why the handleOnclick function is not working ? when I am using just 2 buttons for testing it is working totally fine with translating, so where is it conflicting ?

Example of working handleOnclick funtion, which I dont want to use:

               <button value="da" onClick={handleOnclick}>
                    Danish
                </button>
                <button value="en" onClick={handleOnclick}>
                    English
                </button>

Upvotes: 0

Views: 4438

Answers (1)

Linda Paiste
Linda Paiste

Reputation: 42248

You aren't actually calling handleOnclick. You just have {handleOnclick} which doesn't do anything. You need to call the function. To do that, your onClick callback must take the event e so that it can pass it on to handleOnclick. You are also missing an ending parenthesis ) for router.push.

This should work:

<button
    value={language === 'en' ? 'da' : 'en'}
    onClick={(e) => {
        const locale = router.locale === 'en' ? 'da' : 'en';
        setCookie(locale);
        handleOnclick(e);
        router.push(
            `/${locale}`,
            `/${locale}`,
            { locale: false, }
        );
    }}
>
    {router.locale === 'en' ? (
        <img src={menuItems.data.body[5].items[0].image.url} />
    ) : (
        <img src={menuItems.data.body[4].items[0].image.url} />
    )}
</button>

But it's strange to have some of your logic inline and some in a separate function. I would move it together.

You don't need to use e.target.value since the value is derived from language. It looks like you are just toggling between two options.

e.preventDefault isn't really needed here either because a button click doesn't have a default event that we need to prevent in the way that a link click or a form submission does.

I am not familiar with the react-i18next package so I don't know the types of your i18n or router variables. It seems like we don't even need a language state in this component since you are getting the language from router.locale.

const language = router.locale ?? 'en';

const handleOnclick = () => {
    const newLang = language === 'en' ? 'da' : 'en';
    i18n.changeLanguage(newLang);
    setCookie(newLang);
    router.push( // is this correct?
        `/${newLang}`,
        `/${newLang}`,
        { locale: false, }
    );
};

return (
    <button
        onClick={handleOnclick}
    >
        {language === 'en' ? ( // you could combine some logic here
            <img src={menuItems.data.body[5].items[0].image.url} />
        ) : (
            <img src={menuItems.data.body[4].items[0].image.url} />
        )}
    </button>
)

Upvotes: 1

Related Questions