@usertive/exportable-next-i18next v2.0.3
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-i18nextYou 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.jsonIf 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
pathmodule 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.tsxConfigure 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 š
- There are out-of-the-box examples created to help you start quickly. Have a look at /examples directory.
- Using namespaces? Have a look at this example to learn how to use namespaces correctly.
- For your convenience this library is reexporting all hooks and components from
react-i18nextbut 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';- You can use all features from
i18nextandreact-i18next, includingnamespaces,<Trans>component etc.
- Resources do not need to be located under
/publicdirectory, it's up to you. Just remember to change resource paths accordingly in the config file (i18nextOptions.backend.*).