2.0.3 ā€¢ Published 1 year ago

@usertive/exportable-next-i18next v2.0.3

Weekly downloads
-
License
MIT
Repository
github
Last release
1 year ago

Translate your statically exported NextJs apps efficiently.

About this library

When using traditional next build option, Next.js takes care of routing & language detection. There are many useful libraries that provide the missing functionalities, including translations management, like next-i18next.

However, things get really messy when we export our Next.js app (next export):

  • Next.js no longer handles routing and language detection, as there is no Node.js server anymore.
  • Translations management libraries don't work with exported apps, because they simply don't support them.

To resolve these problems, exportable-next-i18next provides the missing functionality:

  • Routing (with little effort on the developer's part to setup)
  • Language detection (configurable)
  • Back-end translations management (configurable)
  • šŸ”„ Load required translations only for specified language and/or namespace

Because exportable-next-i18next is based on well known libraries (i18next, react-i18next), users of this beautiful library are dealing with ecosystem they know šŸ‘Øā€šŸŽ“ and love ā¤ļø, working on a simple facade, pre-configured but fully configurable.

Setup

1. Installation

yarn add @usertive/exportable-next-i18next

You need to have react and next installed.

2. Prepare the translation content

By default, the library expects your translations to be organised as such:

.
ā””ā”€ā”€ public
    ā””ā”€ā”€ locales
        ā”œā”€ā”€ en.json
        ā””ā”€ā”€ de.json

If you want to structure your translations/namespaces in a custom way, you will simply need to modify i18next's backend config (see next step).

3. Create config

Create exportable-next-i18next.config.ts file in the root directory of the project (or .js if not using TypeScript).

Note: You can name the config file however you want and place it wherever you want; later you will import the config by yourself.

Fill the config file accordingly, following the tips presented below ā¬‡ļø.

import {Config} from '@usertive/exportable-next-i18next';

export const config: Config = {
  // Pass those options ā¬‡ļø the same way you would do with a standard Next.js app
  nextJsOptions: {
    locales: ['en', 'de'],
    defaultLocale: 'en'
  },
  // Pass whatever option you want to i18next here
  i18nextOptions: {
    // Those options are mandatory ā¬‡ļø
    // See https://github.com/i18next/i18next-fs-backend for details
    backend: {
      addPath: `./public/locales/{{lng}}.missing.json`,
      loadPath: `./public/locales/{{lng}}.json`,
    },
  }
};

The presented sample configuration file ā¬†ļø shows only the necessary configuration options, but you can tweak almost all i18next options as you like.

Remember that you can't use Node.js's specific modules in the config file, because this file is shared between the client (browser) and the server (node.js). With a small exception for path module which has been already polyfilled.

4. <App> setup

Modify your _app.jsx/tsx component (or create a new one if you don't have it yet) and wrap your App with appWithTranslations Ad-hoc.

The second argument of appWithTranslations function is your config, imported manually.

import {config as i18nConfig} from '../../exportable-next-i18next.config';

function App({ Component, pageProps }) {
  return <Component {...pageProps} />
}

export default appWithTranslations(App, i18nConfig);

5. Setup static sites generation with translation content injection

For now we will simply create one page but this job has to be done for each new page you want to create.

Create the following pages structure:

 src
 ā””ā”€ā”€ pages
     ā”œā”€ā”€ [lang]
     |    ā””ā”€ā”€ index.tsx
     |    
     ā””ā”€ā”€ index.tsx

Configure getStaticPaths, getStaticProps in pages/[lang]/index.tsx file:

import {GetStaticPaths, GetStaticPathsContext} from 'next';
import {GetStaticPropsContext} from 'next/types';
import {serverSideTranslations} from '@usertive/exportable-next-i18next/dist/server';

import {config as i18nConfig} from '../../../exportable-next-i18next.config';

export const getStaticPaths: GetStaticPaths = function(_context: GetStaticPathsContext) {
  return {
    /**
     * Generate a page for each locale defined in the config file.
     * It's important to name the param `lang`, it won't work otherwise!
     */
    paths: i18nConfig.nextJsOptions.locales.map((locale: string) => ({params: {lang: locale}})),
    fallback: false
  };
};

export const getStaticProps = async (context: GetStaticPropsContext<{lang: string}>) => {
  // Get current locale (language code) from props generated by `getStaticPaths`.
  const locale: string = context.params!.lang;

  return {
    props: {
      /**
       * This is an async function that you need to include on your page-level components, via getStaticProps.
       * This function will take care of injecting translations into your front-end app.
       * The arguments are as follows:
       * 1. locale - current locale to inject translations for;
       * 2. namespaces - array of namespaces required for this page (`null` if you are not using namespaces);
       * 3. i18nConfig - manually imported config file.
       * 4. extra options - i.e. default namespace to use for this page
       */
      ...(await serverSideTranslations(locale, null, i18nConfig))
    }
  };
};

export default function Main() {...}

Re-export special <LangRouter> in /pages/index.tsx

export {LangRouter as default} from '@usertive/exportable-next-i18next/dist/client';

šŸ„³ Done!

Having troubles during setup? Don't worry, go to /examples/simple directory and see an example app already configured in exactly the same manner as in this setup guide.

Nice to know šŸ“˜

  1. There are out-of-the-box examples created to help you start quickly. Have a look at /examples directory.
  1. Using namespaces? Have a look at this example to learn how to use namespaces correctly.
  1. For your convenience this library is reexporting all hooks and components from react-i18next but you can use whatever import you like:
// It doesn't matter which one you choose
import {useTranslation} from '@usertive/exportable-next-i18next/dist/client';
import {useTranslation} from 'react-i18next';
  1. You can use all features from i18next and react-i18next, including namespaces, <Trans> component etc.
  1. Resources do not need to be located under /public directory, it's up to you. Just remember to change resource paths accordingly in the config file (i18nextOptions.backend.*).