Skip to content

Commit

Permalink
fix: Add v8 migration documentation (#1254)
Browse files Browse the repository at this point in the history
* init

* fix-issue-#1040

* fix: issue-#1040

* fix: init
  • Loading branch information
samfromaway authored Jun 13, 2021
1 parent 336ed9c commit e76d9b0
Show file tree
Hide file tree
Showing 2 changed files with 89 additions and 42 deletions.
91 changes: 49 additions & 42 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# next-i18next

[![npm version](https://badge.fury.io/js/next-i18next.svg)](https://badge.fury.io/js/next-i18next)
[![CircleCI](https://circleci.com/gh/isaachinman/next-i18next.svg?style=shield)](https://circleci.com/gh/isaachinman/next-i18next)
[![Package Quality](https://npm.packagequality.com/shield/next-i18next.svg)](https://packagequality.com/#?package=next-i18next)
Expand All @@ -23,7 +24,7 @@ Easy to set up, easy to use: setup only takes a few steps, and configuration is

No other requirements: `next-i18next` simplifies internationalisation for your [NextJs](https://nextjs.org/) app without extra dependencies.

Production ready: `next-i18next` supports passing translations and configuration options into pages as props with SSG/SSR support.
Production ready: `next-i18next` supports passing translations and configuration options into pages as props with SSG/SSR support.

## How does it work?

Expand All @@ -47,6 +48,7 @@ You need to also have `react` and `next` installed.
### 2. Translation content

By default, `next-i18next` expects your translations to be organised as such:

```
.
└── public
Expand All @@ -63,7 +65,7 @@ If you want to structure your translations/namespaces in a custom way, you will

### 3. Project setup

First, create a `next-i18next.config.js` file in the root of your project. The syntax for the nested `i18n` object [comes from NextJs directly](https://nextjs.org/docs/advanced-features/i18n-routing).
First, create a `next-i18next.config.js` file in the root of your project. The syntax for the nested `i18n` object [comes from NextJs directly](https://nextjs.org/docs/advanced-features/i18n-routing).

This tells `next-i18next` what your `defaultLocale` and other locales are, so that it can preload translations on the server:

Expand All @@ -75,19 +77,19 @@ module.exports = {
defaultLocale: 'en',
locales: ['en', 'de'],
},
}
};
```

Now, create or modify your `next.config.js` file, by passing the `i18n` object into your `next.config.js` file, to enable localised URL routing:

#### [`next.config.js`](https://nextjs.org/docs/api-reference/next.config.js/introduction)

```js
const { i18n } = require('./next-i18next.config')
const { i18n } = require('./next-i18next.config');

module.exports = {
i18n,
}
};
```

There are three functions that `next-i18next` exports, which you will need to use to translate your project:
Expand All @@ -97,11 +99,11 @@ There are three functions that `next-i18next` exports, which you will need to us
This is a HOC which wraps your [`_app`](https://nextjs.org/docs/advanced-features/custom-app):

```tsx
import { appWithTranslation } from 'next-i18next'
import { appWithTranslation } from 'next-i18next';

const MyApp = ({ Component, pageProps }) => <Component {...pageProps} />
const MyApp = ({ Component, pageProps }) => <Component {...pageProps} />;

export default appWithTranslation(MyApp)
export default appWithTranslation(MyApp);
```

The `appWithTranslation` HOC is primarily responsible for adding a [`I18nextProvider`](https://react.i18next.com/latest/i18nextprovider).
Expand All @@ -111,15 +113,15 @@ The `appWithTranslation` HOC is primarily responsible for adding a [`I18nextProv
This is an async function that you need to include on your page-level components, via either [`getStaticProps`](https://nextjs.org/docs/basic-features/data-fetching#getstaticprops-static-generation) or [`getServerSideProps`](https://nextjs.org/docs/basic-features/data-fetching#getserversideprops-server-side-rendering) (depending on your use case):

```tsx
import { serverSideTranslations } from 'next-i18next/serverSideTranslations'
import { serverSideTranslations } from 'next-i18next/serverSideTranslations';

export async function getStaticProps({ locale }) {
return {
props: {
...(await serverSideTranslations(locale, ['common', 'footer'])),
// Will be passed to the page component as props
}
}
},
};
}
```

Expand All @@ -134,20 +136,17 @@ The `serverSideTranslations` HOC is primarily responsible for passing translatio
This is the hook which you'll actually use to do the translation itself. The `useTranslation` hook [comes from `react-i18next`](https://react.i18next.com/latest/usetranslation-hook), but can be imported from `next-i18next` directly:

```tsx
import { useTranslation } from 'next-i18next'
import { useTranslation } from 'next-i18next';

export const Footer = () => {

const { t } = useTranslation('footer')
const { t } = useTranslation('footer');

return (
<footer>
<p>
{t('description')}
</p>
<p>{t('description')}</p>
</footer>
)
}
);
};
```

### 4. Declaring namespace dependencies
Expand All @@ -160,21 +159,20 @@ Note: `useTranslation` provides namespaces to the component that you use it in.

### 5. Advanced configuration


#### Passing other config options

If you need to modify more advanced configuration options, you can pass them via `next-i18next.config.js`. For example:

```js
const path = require('path')
const path = require('path');

module.exports = {
i18n: {
defaultLocale: 'en',
locales: ['en', 'de'],
},
localePath: path.resolve('./my/custom/path')
}
localePath: path.resolve('./my/custom/path'),
};
```

#### Unserialisable configs
Expand All @@ -191,42 +189,52 @@ Reason: `function` cannot be serialized as JSON. Please only return JSON seriali
To fix this, you'll need to set `config.serializeConfig` to `false`, and manually pass your config into `appWithTranslation`:

```tsx
import { appWithTranslation } from 'next-i18next'
import nextI18NextConfig from '../next-i18next.config.js'
import { appWithTranslation } from 'next-i18next';
import nextI18NextConfig from '../next-i18next.config.js';

const MyApp = ({ Component, pageProps }) => <Component {...pageProps} />
const MyApp = ({ Component, pageProps }) => <Component {...pageProps} />;

export default appWithTranslation(MyApp, nextI18NextConfig)
export default appWithTranslation(MyApp, nextI18NextConfig);
```

```tsx
import { serverSideTranslations } from 'next-i18next/serverSideTranslations'
import { serverSideTranslations } from 'next-i18next/serverSideTranslations';

import nextI18NextConfig from '../next-i18next.config.js'
import nextI18NextConfig from '../next-i18next.config.js';

export const getStaticProps = async ({ locale }) => ({
props: {
...await serverSideTranslations(locale, ['common', 'footer'], nextI18NextConfig),
}
})
...(await serverSideTranslations(
locale,
['common', 'footer'],
nextI18NextConfig
)),
},
});
```

#### Options

| Key | Default value |
| ------------- | ------------- |
| `defaultNS` | `'common'` |
| `localeExtension` | `'json'` |
| `localePath` | `'./public/locales'` |
| `localeStructure` | `'{{lng}}/{{ns}}'` |
| `serializeConfig` | `true` |
| `strictMode` | `true` |
| `use` (for plugins) | `[]` |
| Key | Default value |
| ------------------- | -------------------- |
| `defaultNS` | `'common'` |
| `localeExtension` | `'json'` |
| `localePath` | `'./public/locales'` |
| `localeStructure` | `'{{lng}}/{{ns}}'` |
| `serializeConfig` | `true` |
| `strictMode` | `true` |
| `use` (for plugins) | `[]` |

All other [i18next options](https://www.i18next.com/overview/configuration-options) can be passed in as well.

## Migration to v8

To migrate from previous versions to the version 8, check out the [v8-migration guide](https://github.com/isaachinman/next-i18next/tree/master/docs/v8-migration.md)

## Notes

For Docker deployment, note that if you use the `Dockerfile` from [Next.js docs](https://nextjs.org/docs/deployment#docker-image) do not forget to copy `next.config.js` and `next-i18next.config.js` into the Docker image.

```
COPY --from=builder /app/next.config.js ./next.config.js
COPY --from=builder /app/next-i18next.config.js ./next-i18next.config.js
Expand All @@ -252,4 +260,3 @@ This project follows the [all-contributors](https://github.com/kentcdodds/all-co
<a href="https://www.browserstack.com/" target="_blank">
<img src="https://miro.medium.com/max/560/0*dLdslKvNsmtaH2uQ.png" width="240px">
</a>

40 changes: 40 additions & 0 deletions docs/v8-migration.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# Migration Guide v7 to v8

Please read the [full documentation](https://github.com/isaachinman/next-i18next/blob/master/README.md), before migrating from previous versions to v8.

This is a guide which will cover most use cases to migrate from v7 to v8.
We advise migrating as soon as possible, as new versions of NextJs won't be compatible with the v7 of this package `next-i18next`.

#### What is new?

This package, `next-i18next`, has changed a lot because it now is _not_ providing internationalised routing anymore, as [NextJs has first class support for it.](https://nextjs.org/docs/advanced-features/i18n-routing)

Before the translation functionality was initialised on a global level, in `_app.js`. Now, you must use a new method, called `serverSideTranslations` on*each* page in your `pages` directory.

The object `i18n` which was imported directly from `i18n.js` in `next-i18next@<8` suppored only client-side-rendering. Now in the v8 the `i18n` object also supports server-side rendering. So you can use the `i18n.language` for server-side rendered elements.

#### What is the same?

1. `appWithTranslation` still wraps the App in `_app.js`
2. `withTranslation` works the same way
3. `useTranslation` works the same way
4. The [translation content structure](https://github.com/isaachinman/next-i18next/blob/master/README.md#2-translation-content) remains the same

#### Step By Step Migration Guide

1. Remove `i18n.js` and add `next-i18next.config.js` as described in [the docs](https://github.com/isaachinman/next-i18next#3-project-setup) to your `next.config.js` file
2. Replace `import { appWithTranslation } from 'i18n'` with `import { appWithTranslation } from 'next-i18next'`
3. Replace all instances of `import { withTranslation } from 'i18n` to `import { withTranslation } from 'next-i18next'`
4. Replace all instances of `import { useTranslation } from 'i18n` to `import { useTranslation } from 'next-i18next'`
5. Add to `getServerSideProps` or `getInitialProps` in the return as props`...(await serverSideTranslations(locale, [<YOUR_NAMESPACES>]))` in every single page where you have translations. Note that if you have a component in `_app` that needs translations, you will have to do this for _all_ pages. Follow [the docs.](https://github.com/isaachinman/next-i18next#serversidetranslations)
6. Remove `namespacesRequired: ['common'],` in `_app.js` (not used anymore)
7. To change language imperatively, you can now do: `router.push(router.asPath, undefined, { locale: <YOUR_LOCALE>, });`

#### Optional

1. Add to the custom 404 page the `...(await serverSideTranslations(locale, [<YOUR_NAMESPACES>])),` as a return in props in `getStaticProps` so the 404 page works with translations as well
2. Add to the custom 500 page the `...(await serverSideTranslations(locale, [<YOUR_NAMESPACES>])),` as a return in props in `getStaticProps` so the 404 page works with translations as well
3. Add set cookie `NEXT_LOCALE` for language recognition. More about that in [the NextJs docs](https://nextjs.org/docs/advanced-features/i18n-routing#leveraging-the-next_locale-cookie)
4. Adjust the Jest test settings to mock `withTranslation`,`useTranslation`, and `t()` or/and `i18n` in props.

More info in the [full documentation](https://github.com/isaachinman/next-i18next/blob/master/README.md), or in the [next.js documentation.](https://nextjs.org/docs/advanced-features/i18n-routing)

1 comment on commit e76d9b0

@vercel
Copy link

@vercel vercel bot commented on e76d9b0 Jun 13, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.