Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Next.js 10 + sub-routing, how to access locale in custom app on server-side

I'm migrating a project from next.js 7 to 10. It uses react-intl for translations and was written in TypeScript.

In the previous version I had a custom server.js and handled sub-routing (/de, /fr, etc.) for multilingual purposes in it. And in custom app component, through the getInitialProps, I was getting locale from req and passed it as a prop to my component. So the whole picture was something like this:
Custom app:

static async getInitialProps({ Component, ctx }) {
    let pageProps = {}

    const { req } = ctx;
    const { locale, messages } = req || (window as any).__NEXT_DATA__.props;
    const initialNow = Date.now();

    if (Component.getInitialProps) {
        pageProps = await Component.getInitialProps(ctx)
    }
    return { pageProps, locale, messages, initialNow }
}

And the component

render() {
        const { Component, pageProps, locale, messages, initialNow } = (this.props as any);
        return (
            <Container>
                <IntlProvider locale={locale} messages={messages} initialNow={initialNow}>
                    <Component {...pageProps} />
                </IntlProvider>
            </Container>
        )
    }

Now since I'm using next.js 10, for many reasons I removed the custom server.js and did the sub-routing through i18n, so I added this in next.config.js:

module.exports = {
   i18n: {
        locales: ["en", "de", "fr"],
        defaultLocale: "en",
    },
}

The only thing is that I need to pass the locale to IntlProvider of react-intl in server-side and for all the pages. So I suppose I should do it in custom app and getInitialProps returns a wrong value for locale (always default). And we can't use getServerSideProps or getStaticProps in custom _app.

So finally! the question is: How can I access the locale on server-side in one place for all of my pages? Or is there a better approach to solve this issue?

(I can't remove intl and work fully with i18n for now, it needs so much time for this particular project and we don't have it atm!)

like image 437
Ali Afsahnoudeh Avatar asked Dec 24 '20 09:12

Ali Afsahnoudeh


1 Answers

You can access the locale in your custom app's getInitialProps through the router prop.

static async getInitialProps({ Component, ctx, router }) {
    let pageProps = {}

    const { req } = ctx;
    const { locale } = router; // Will return `fr` for `/fr/*` pages
    const { messages } = req || (window as any).__NEXT_DATA__.props;
    const initialNow = Date.now();

    if (Component.getInitialProps) {
        pageProps = await Component.getInitialProps(ctx)
    }
    return { pageProps, locale, messages, initialNow }
}

When using getServerSideProps/getStaticProps, outside custom app pages, the active locale can be accessed directly from the context object.

export async function getServerSideProps({ locale }) {
    console.log(locale) // Logs current locale    
    // ...
}
export async function getStaticProps({ locale }) {
    console.log(locale) // Logs current locale    
    // ...
}

For more details check Next.js i18n routing documentation .

like image 190
juliomalves Avatar answered Nov 02 '22 23:11

juliomalves