appleboy / react-recaptcha

A react.js reCAPTCHA for Google
https://www.google.com/recaptcha/intro/index.html
BSD 3-Clause "New" or "Revised" License
634 stars 97 forks source link

Recaptcha Language Does Not Update When Site Language Changes #311

Open BurN-SN opened 2 years ago

BurN-SN commented 2 years ago

Hey there,

I am having an issue with ReCAPTCHA on a site that requires instant translation. I can use the hl prop to pass it a language, but if the user changes the language, the ReCaptcha remains in the initial language and does not update to reflect the user's selection.

I will try to distill the implementation.

<LanguageContext.Provider>         // Contains "language" for global consumption
    <Header/>                      // Contains toggle for user to translate page
    <FormThatContainsReCaptcha/>   // Contains recaptcha
</LanguageContext.Provider>

///// Form.jsx
const FormThatContainsReCaptcha = () => {
    const context = useContext(LanguageContext)

    const handleCaptcha = () => { }

    return (
        // ...form things
        <ReCAPTCHA
            sitekey={'112233_aabbcc'}
            render="explicit"
            verifyCallback={handleCaptcha}
            hl={language}
        />
    )
}

The context is working correctly. It is successfully translating the other form fields and other content on the page and console logs confirm that the language is in fact switching when user switches the language in the header. Additionally, all the language codes in question work correctly with the ReCaptcha if hard-coded or active on initial load (an invalid lang code is not the issue).

However, the ReCaptcha seems "stuck" on whatever language it has at initial load and will not update with context changes.

Attempted Solutions

I have tried various configurations around "explicit" render.

I have tried wrapping the ReCaptcha componenet in another component and passing the lang code as a prop in hopes that the props updating would trigger a rerender.

I have tried a switch() statement as a helper method that would run at render and return the appropriate ReCaptcha component, like so:

const getCaptchad = () => {
    switch (language) {
        case 'de':
            return <ReCAPTCHA
                sitekey={TEST_SITE_KEY}
                render="explicit"
                verifyCallback={handleCaptcha}
                hl='de'
            />
        case 'en':
            return <ReCAPTCHA
                sitekey={TEST_SITE_KEY}
                render="explicit"
                verifyCallback={handleCaptcha}
                hl='en'
            />
        default:
            return <ReCAPTCHA
                sitekey={TEST_SITE_KEY}
                render="explicit"
                verifyCallback={handleCaptcha}
                hl='en'
            />
      }
}

// and then in Form component
<Form>
    {getCaptchad()}
</Form>

I really hope someone here can help!

BurN-SN commented 2 years ago

I was able to solve this by conditionally rendering different ReCaptcha components like so:

        {/* SEPARATE RECAPTCHA INSTANCES NEEDED FOR EACH LANGUAGE TO ALLOW TOGGLING */}
        {language==="de" && (
          <ReCAPTCHA
            sitekey='xxxxxxxxxx'
            render="explicit"
            verifyCallback={handleCaptcha}
            hl='de'    
          />
        )}

        {language==="en" && (
          <ReCAPTCHA
            sitekey="xxxxxxxxxx"
            reneder="explicit"
            verifyCallback={handleCaptcha}
            hl='en'    
          />
        )}

I would still like to know if there is another solution to my problem out there. As our client expands into more language regions this will become very verbose and obviously repeated code is bug-prone and suboptimal

Thanks!

BurN-SN commented 2 years ago

I was able to solve this by conditionally rendering different ReCaptcha components like so:

        {/* SEPARATE RECAPTCHA INSTANCES NEEDED FOR EACH LANGUAGE TO ALLOW TOGGLING */}
        {language==="de" && (
          <ReCAPTCHA
            sitekey='xxxxxxxxxx'
            render="explicit"
            verifyCallback={handleCaptcha}
            hl='de'    
          />
        )}

        {language==="en" && (
          <ReCAPTCHA
            sitekey="xxxxxxxxxx"
            reneder="explicit"
            verifyCallback={handleCaptcha}
            hl='en'    
          />
        )}

I would still like to know if there is another solution to my problem out there. As our client expands into more language regions this will become very verbose and obviously repeated code is bug-prone and suboptimal

Thanks!

fbrcc commented 2 years ago

I found this other workaround.

lang is a valid language code string ("en", "es", "pt", etc). Passing it as key to the react component forces a remount when lang changes and the component successfully re-mounts with the value of lang in the hl prop.

       <ReCAPTCHA
            sitekey="xxxxxxxxxx"
            reneder="explicit"
            verifyCallback={handleCaptcha}
            hl={lang}
            key={lang}
        />
tungvv-vba commented 2 weeks ago

@fbrcc thank you so much. I solved my issue by this.