payloadcms / payload

Payload is the open-source, fullstack Next.js framework, giving you instant backend superpowers. Get a full TypeScript backend and admin panel instantly. Use Payload as a headless CMS or for building powerful applications.
https://payloadcms.com
MIT License
24.73k stars 1.57k forks source link

Translation not working in UI field component #3182

Closed cbratschi closed 1 year ago

cbratschi commented 1 year ago

Link to reproduction

private repo

To Reproduce

The following UI field:

{
            //summary (UI field)
            name: 'summary',
            type: 'ui',

            admin: {
                position: 'sidebar',

                components: {
                    Field: CategorySummary
                }
            }
        }

Uses:

import { useTranslation } from 'react-i18next';

export default function CategorySummary({}) {
    const { t, i18n } = useTranslation('custom');

    //debug
    console.log('i18n:');
    console.dir(t); //FIXME notReadyT()
    console.dir(i18n);
    console.dir(i18n.language); //FIXME undefined
    console.dir(i18n.options?.resources); //FIXME undefined

    return (
        <h4>{t('loading')}</h4>
    );
}

The Payload settings are:

    i18n: {
        fallbackLng: 'en',
        debug: true, //FIXME

        //see https://payloadcms.com/docs/configuration/i18n#configuration-options
        resources: {
            en: {
                custom: {
                    loading: 'loading...'
                }
            },
            de: {
                custom: {
                    loading: 'Lade...'
                }
            }
        }
    },

The JavaScript console shows the following error:

react-i18next:: You will need to pass in an i18next instance by using initReactI18next

It seems the i18n context is not available in custom components.

Describe the Bug

The i18n context should be available in all components but it is not initialized in a UI component.

Init occurs here: https://github.com/payloadcms/payload/blob/c154eb7e2baec44688859e0902b1ea949868b859/src/admin/components/utilities/I18n/index.tsx#L20

And gets used in the root element: https://github.com/payloadcms/payload/blob/c154eb7e2baec44688859e0902b1ea949868b859/src/admin/Root.tsx#L29

The code looks fine, I could not find any reason so far.

Some config changes are proposed here: https://stackoverflow.com/questions/67894982/react-i18next-you-will-need-to-pass-in-an-i18next-instance-by-using-initreacti

Payload Version

1.13.4

cbratschi commented 1 year ago

The custom string are available and i18next gets initialized (shown in debug mode):

i18next: languageChanged de
i18next: initialized 

But fails in the component:

[HMR] connected
react-i18next:: You will need to pass in an i18next instance by using initReactI18next

I am using a standalone Payload instance running on a different port than the Next.js app. So there are no side effects with Next.js.

cbratschi commented 1 year ago

It strongly looks like a problem with suspense: https://react.i18next.com/latest/using-with-hooks

cbratschi commented 1 year ago

I tried to workarounds this by using the useLocale() hook but the hook always returns 'en' but the active language is 'de'.

import { useLocale, useDocumentInfo } from 'payload/components/utilities';

...

//in React component
    const locale = useLocale();

    //debug FIXME always en
    console.log('i18n: ' + locale);

Edit: useLocale() returns the current edited language, not the user's language.

AlessioGr commented 1 year ago

Hey @cbratschi

I've tried reproducing it here, but it works just fine for me.

I'd appreciate it if you can create a reproduction. Feel free to PR one, targeting that reproduction/3182 branch :)

cbratschi commented 1 year ago

Still an issue with the latest Payload version. Will try to add it to the demo project.

cbratschi commented 1 year ago

Well I integrated my code into https://github.com/cbratschi/public-demo/tree/master but it's not reproducible there. I could not find any issue in our code yet. Difficult case...

AlessioGr commented 1 year ago

Well I integrated my code into https://github.com/cbratschi/public-demo/tree/master but it's not reproducible there. I could not find any issue in our code yet. Difficult case...

This might be an issue with the way you've installed payload in your project. Maybe it's using different / duplicated versions of react-i18n or something like that (try aliasing it in webpack!). Might be worth looking into

cbratschi commented 1 year ago

We are using the latest version 13.1.2 and your project uses 11.18.6. However, all other components work fine.

Will have a look how Payload uses Webpack. A solution could also be you add an additional context which returns your react-18next instance to avoid us to load incompatible versions.

cbratschi commented 1 year ago

Downgraded react-i18next to 11.18.6 but still getting the same error.

cbratschi commented 1 year ago

I tried to completely remove the locally installed react-i18next version which is anyway only used for our Payload components. Unfortunately this made no difference either.

Is there a way to access req.i18n in a custom component?

cbratschi commented 1 year ago

Forgot to remove the package in the npm workspace of the monorepos. Now it works fine and uses the Payload dependency.

reiv commented 1 year ago

Sorry for bumping a closed issue, but I'm running into this as well. I'm using pnpm so importing transitive dependencies doesn't work and the locally installed package, despite having the same version, appears to be isolated from the one Payload pulls in - I assume this is because it's not declared as a peer dependency.

@AlessioGr as a workaround, would it be possible to re-export useTranslation as a utility from the payload package?

NetroScript commented 11 months ago

@reiv

Sorry for bumping a closed issue, but I'm running into this as well. I'm using pnpm so importing transitive dependencies doesn't work and the locally installed package, despite having the same version, appears to be isolated from the one Payload pulls in - I assume this is because it's not declared as a peer dependency.

@AlessioGr as a workaround, would it be possible to re-export useTranslation as a utility from the payload package?

Its by now another month later, but I encountered the same issue while using pnpm.

For me it works when shamefully hoisting the related modules for pnpm and redoing the install.

Specifically I have the following .npmrc for the modules I also need access to:

public-hoist-pattern[]=react
public-hoist-pattern[]=sharp
public-hoist-pattern[]=pino
public-hoist-pattern[]=pino-pretty
public-hoist-pattern[]=react-i18next

However I agree it would be better if this would not be necessary, as I am using multiple workspaces and hoisting can only be configured for all workspaces.

Especially because this also affect other cases, such as for example using the element for redirects from react-router-dom.

github-actions[bot] commented 1 month ago

This issue has been automatically locked. Please open a new issue if this issue persists with any additional detail.