Search code examples
reactjsnext.jsi18nextreact-i18next

How to properly load i18n resources in next-i18next from api endpoints?


I have a nextjs app, which I want to extend using i18next and next-i18next (https://github.com/isaachinman/next-i18next).

The default configuration is looking for json files under ./public/locales/{lng}/{ns}.json, where lng is the language and ns a namespace.

My requirement however is, that this should be served from an api endpoint. I am struggling to find the correct configuration, as next-i18next does ignore my settings right now and is not firing off any xhr requests to my backend.

next-i18next.config.js:

const HttpApi = require('i18next-http-backend')

module.exports = {
    i18n: {
        defaultLocale: 'de',
        locales: ['en', 'de'],
    },
    backend: {
        referenceLng: 'de',
        loadPath: `https://localhost:5001/locales/de/common`,
        parse: (data) => {
            console.log(data)
            return data 
        }
    },
    debug: true,
    ns: ['common', 'footer', 'second-page'], // the namespaces needs to be listed here, to make sure they got preloaded
    serializeConfig: false, // because of the custom use i18next plugin
    use: [HttpApi],
}

I am at a loss here. What am I doing wrong?


Solution

  • Eventually I cobbled it together.

    const I18NextHttpBackend = require('i18next-http-backend')
    
    module.exports = {
        i18n: {
            defaultLocale: 'de',
            locales: ['de'],
    
            backend: {
                loadPath: `${process.env.INTERNAL_API_URI}/api/locales/{{lng}}/{{ns}}`
            },
        },
        debug: true,
        ns: ["common", "employees", "projects"],
        serializeConfig: false,
        use: [I18NextHttpBackend]
    }
    

    You might be running into an error saying You are passing a wrong module! Please check the object you are passing to i18next.use(). If this is the case, you can force the http backend to load as commonjs, by using the following import:

    const I18NextHttpBackend = require('i18next-http-backend/cjs')
    

    The first one worked on webpack 5, while I had to use the cjs import on webpack 4. Although I could not find the reason for this.

    After this, its smooth sailing:

    _app.tsx:

    /*i18n */
    import { appWithTranslation } from 'next-i18next'
    import NextI18nextConfig from '../../next-i18next.config'
    
    const MyApp = ({ Component, pageProps }: AppProps) => {
      return (
        <>
          <MsalProvider instance={msalApp}>
            <PageLayout>
              <Component {...pageProps} />
            </PageLayout>
          </MsalProvider>
        </>
      )
    }
    
    export default appWithTranslation(MyApp, NextI18nextConfig)
    

    anypage.tsx:

    export const getServerSideProps: GetServerSideProps = async ({ locale }) => {
      return {
        props: {
          ...(await serverSideTranslations(locale, ['common', 'employees'])),
          // Will be passed to the page component as props
        },
      };
    }
    

    If you just need to locales to be fetched once, during build, you can use getStaticProps instead - that is up to you.