Adyen / adyen-web

Adyen Web Drop-in and Components
https://docs.adyen.com/online-payments
MIT License
181 stars 129 forks source link

Problem with displaying correct translations #1672

Closed dzikiite closed 2 years ago

dzikiite commented 2 years ago

Describe the bug The problem is that the translations are not displayed correctly according to the specified locale parameter passed in the configuration object. The language specified in locale is mixed with English.

To Reproduce

  1. To the configuration object passed to AdyenCheckout add the locale parameter with the value pl-PL.
  2. Show adyen components on website (I use the web components approach).
  3. Select the payment method "Online Banking Poland" (The correct Polish translation is shown in bank select).
  4. Select different method
  5. Go Select "Online Banking Poland" once again. (The English translation of "Select your bank" is shown).

Expected behavior When passing a valid value for the locale parameter, all translations for the region should be shown.

Screenshots

https://user-images.githubusercontent.com/56672059/182381378-3907faf6-d52a-407e-a739-0ec29329f552.mov

Desktop:

Additional context: @adyen/adyen-web: 4.9.0

ribeiroguilherme commented 2 years ago

Hi @dzikiite ,

Thanks for reaching out. Can you explain how are you showing and removing the components in the screen?

From my understanding, you created your custom UI with radio buttons, and there is a certain logic to show/hide the payment methods according to what is selected. I'd like to know what you are doing there, so I can try to reproduce on my side.

dzikiite commented 2 years ago

Of course, I'm already explaining.

At the begining I'm fetching adyen payment methods, there are displaying as a radio button. The onClick event saves the selected method to the react state, which is then passed to adyen, which is responsible for displaying the component of the selected method.

The mounted component is created as follows:

const configuration = useMemo(() => {
  return {
      environment,
      locale,
      onChange: componentState => {
          paymentState.current = componentState;
      },
      onSubmit: componentState => {
          paymentState.current = componentState;
      },
      paymentMethodsResponse,
      showPayButton: false
  };
}, [environment, locale, paymentMethodsResponse, paymentState]);

useEffect(() => {
    (async () => {
        if (!selectedMethod || !paymentMethodsResponse || !clientKey) {
            return;
        }

        const methodConfiguration = {
            clientKey
        };

        if (selectedMethod === 'scheme') {
            methodConfiguration.onBrand = ({ brand }) => {
                paymentBrand.current = brand;
            };
        }

        const checkout = new AdyenCheckout(configuration);
        paymentComponent.current = checkout
            .create(
                selectedMethod === 'scheme' ? 'card' : selectedMethod,
                methodConfiguration
            )
            .mount(componentRef.current);
    })();
}, [clientKey, configuration, paymentMethodsResponse, selectedMethod]);

Key variables:

image

When displaying I simply use ref:

return <div className={classes.root} ref={componentRef} />;
ribeiroguilherme commented 2 years ago

I couldn't really spot where is the issue in your code snippet. Side note: I see that you are re-running the useEffect, creating the AdyenCheckout instance every time that you want to tweak the payment method. There is no need for that - you can create it once and reuse it.

I tried to reproduce the behavior that you want to achieve, using the version 4.9.0 and it worked fine. I managed with the following code:

const PaymentForm = (props) => {
    const [checkout, setCheckout] = useState(null);
    const htmlContainerRef = useRef(null);
    const checkoutComponentRef = useRef(null);

    const tweakComponent = useCallback((txVariant) => {
        if (checkout) {
            checkoutComponentRef.current?.unmount();
            checkoutComponentRef.current = checkout.create(txVariant).mount(htmlContainerRef.current);
        }
    }, [checkout]);

    useEffect(() => {
        const { currency, countryCode } = props.settings;
        const total = getTotal(props.products);
        const value = getAdjustedAmount(total, currency);
        const amount = { currency, value };

        getPaymentMethods({ amount, countryCode, shopperLocale: 'pl-PL' })
            .then(paymentMethodsResponse => {

                const checkout =  new AdyenCheckout({
                    locale: 'pl-PL',
                    paymentMethodsResponse,
                    clientKey: process.env.__CLIENT_KEY__,
                    environment: 'test',
                    paymentMethodsConfiguration: {
                        // add here payment method configs
                        card: {},
                        blik: {}
                    },
                    onSubmit: () => console.log('submit')
                    // other callbacks, .. props ...
                });
                setCheckout(checkout);
            });

    }, []);

    return (
        <Fragment>
            <button onClick={() => tweakComponent('dotpay')}>Online Banking</button>
            <button onClick={() => tweakComponent('blik')}>Blik</button>
            <button onClick={() => tweakComponent('scheme')}>Scheme Banking</button>

            <div ref={htmlContainerRef} />
        </Fragment>
    );
};

https://user-images.githubusercontent.com/7724351/185403317-863c6d76-f3c1-4106-ab90-03808d716aa9.mov

Let us know if this helps

dzikiite commented 2 years ago

Your "side note" proved to be crucial. Duplicating instances of AdyenCheckout caused a translation problem. This explains why your code above does not show the problem.

Thanks for help!

ribeiroguilherme commented 2 years ago

Glad it worked. Cheers!