An open API service indexing awesome lists of open source software.

https://github.com/moxystudio/next-intl

Library to integrate react-intl with Next.js.
https://github.com/moxystudio/next-intl

i18n intl l10n nextjs react

Last synced: 3 months ago
JSON representation

Library to integrate react-intl with Next.js.

Awesome Lists containing this project

README

          

# next-intl

[![NPM version][npm-image]][npm-url] [![Downloads][downloads-image]][npm-url] [![Build Status][build-status-image]][build-status-url] [![Coverage Status][codecov-image]][codecov-url] [![Dependency status][david-dm-image]][david-dm-url] [![Dev Dependency status][david-dm-dev-image]][david-dm-dev-url]

[npm-url]:https://npmjs.org/package/@moxy/next-intl
[downloads-image]:https://img.shields.io/npm/dm/@moxy/next-intl.svg
[npm-image]:https://img.shields.io/npm/v/@moxy/next-intl.svg
[build-status-url]:https://github.com/moxystudio/next-intl/actions
[build-status-image]:https://img.shields.io/github/workflow/status/moxystudio/next-intl/Node%20CI/master
[codecov-url]:https://codecov.io/gh/moxystudio/next-intl
[codecov-image]:https://img.shields.io/codecov/c/github/moxystudio/next-intl/master.svg
[david-dm-url]:https://david-dm.org/moxystudio/next-intl
[david-dm-image]:https://img.shields.io/david/moxystudio/next-intl.svg
[david-dm-dev-url]:https://david-dm.org/moxystudio/next-intl?type=dev
[david-dm-dev-image]:https://img.shields.io/david/dev/moxystudio/next-intl.svg

Library to integrate [`react-intl`](https://www.npmjs.com/package/react-intl) with Next.js.

## Installation

```sh
$ npm install --save @moxy/next-intl react-intl
```

> ℹ️ If you are running Node.js `< 13.1.0`, you must also install `full-icu` and start node with [`--icu-data-dir=node_modules/full-icu`](https://github.com/zeit/next.js/blob/5e6f79117fae59ec3a6a3260808f611862c53f0a/examples/with-react-intl/package.json#L5) or use `NODE_ICU_DATA=node_modules/full-icu`.

## Setup

### 1. Configure `next.config.js`

Please configure `i18n` as explained in the official Next.js [docs](https://nextjs.org/docs/advanced-features/i18n-routing#getting-started).

```js
// next.config.js
module.exports = {
i18n: {
locales: ['en', 'pt'],
defaultLocale: 'en',
},
};
```

### 2. Create a root folder named `intl` to hold translation files:

```
intl/
en.json
pt.json
```

The `intl/en.json` file contains the messages for the `en` locale, like so:

```json
{
"hello": "Hello World"
}
```

### 3. Wrap your app with `withIntlApp()` in `pages/_app.js`:

```js
// pages/_app.js
import React from 'react';
import App from 'next/app';
import { withIntlApp } from '@moxy/next-intl';

// The example below dynamically downloads translations from your JSON files,
// but you may load them from external sources, such as a CMS.
// Please note that the result will be cached on the client-side,
// to avoid fetching translations on every page change.
const loadLocale = async (locale) => {
const module = await import(/* webpackChunkName: "intl-messages" */ `../intl/${locale}.json`);

return module.default;
};

export default withIntlApp(loadLocale)(App);
```

Here's an example if you have a custom app:

```js
import React from 'react';
import { withIntlApp } from '@moxy/next-intl';
import Layout from '../components/layout';

const MyApp = ({ Component, pageProps }) => (



);

const loadLocale = async (locale) => {
const module = await import(/* webpackChunkName: "intl-messages" */ `../intl/${locale}.json`);

return module.default;
};

export default withIntlApp(loadLocale)(MyApp);
```

### 4. Use `getIntlProps()` in your pages.

```js
// pages/index.js
import React from 'react';
import { getIntlProps } from '@moxy/next-intl';

const Home = () => (



);

export const getStaticProps = async ({ locale }) => ({
props: await getIntlProps(locale),
});

export default Home;
```

If you already are using `getStaticProps` for something else:

```js
export const getServerSideProps = async ({ locale }) => {
const [foo, localeProps] = await Promise.all([
fetchFoo(),
getIntlProps(locale);
]);

return {
foo,
...localeProps,
};
};
```

> ℹ️ If you are using `getServerSideProps()`, then it works the same as the examples that use `getStaticProps()`.

## FAQ

### How can I use this `getIntlProps()` in my page's `getInitialProps()`?

```js
// pages/index.js
import React from 'react';
import { getIntlProps } from '@moxy/next-intl';
import { FormattedMessage } from 'react-intl';

const Home = () => (



);

Home.getInitialProps = async ({ locale }) => ({
...await getIntlProps(locale),
});

export default Home;
```

However, the `locale` parameter will be undefined in the `getInitialProps()` function above because Next.js doesn't pass it as of now, but there's an [open pull-request](https://github.com/vercel/next.js/pull/21930) to resolve it.

To circumvent this, you must override `pages/_app.js` like so:

```js
// pages/_app.js
import App from 'next/app';

const MyApp = (props) => ;

MyApp.getInitialProps = async (appCtx) => {
appCtx.ctx.locale = appCtx.router.locale;
appCtx.ctx.locales = appCtx.router.locales;
appCtx.ctx.defaultLocale = appCtx.router.defaultLocale;

const appProps = await App.getInitialProps(appCtx);

return appProps;
};

export default MyApp;
```

> ⚠️ Please note that adding `getInitialProps()` to your App will disable Automatic Static Optimization in pages without Static Generation.

### How do I avoid repeating `getIntlProps()` in all my pages?

You can use `getIntlProps()` once in your `pages/_app.js`, like so:

```js
// pages/_app.js
import App from 'next/app';

const MyApp = (props) => ;

MyApp.getInitialProps = async (appCtx) => {
const [intlProps, appProps] = await Promise.all([
getIntlProps(appCtx.router.locale),
App.getInitialProps(appCtx),
]);

return {
...intlProps,
...appProps,
};
};

export default MyApp;
```

> ⚠️ Please note that adding `getInitialProps()` to your App will disable Automatic Static Optimization in pages without Static Generation.

### How do I load `intl` polyfills?

In previous versions of this library, all polyfills were automatically downloaded. This is no longer the case. However, you may load any polyfills and locale data inside the `loadLocale()` function.

Here's an example that loads the [`@formatjs/intl-pluralrules`](https://formatjs.io/docs/polyfills/intl-pluralrules/) polyfill.

```js
// _app.js
import { shouldPolyfill as shouldPolyfillPluralRules } from '@formatjs/intl-pluralrules/should-polyfill';

// ...

const loadLocale = async (locale) => {
if (shouldPolyfillPluralRules()) {
await import(/* webpackChunkName: "intl-pluralrules" */ '@formatjs/intl-pluralrules/polyfill');
}

if (Intl.PluralRules.polyfilled) {
switch (locale) {
case 'pt':
await import(/* webpackChunkName: "intl-pluralrules-pt" */ '@formatjs/intl-pluralrules/locale-data/pt')
break;
default:
await import(/* webpackChunkName: "intl-pluralrules-en" */ '@formatjs/intl-pluralrules/locale-data/en')
break
}
}

const module = await import(/* webpackChunkName: "intl-messages" */ `../intl/${locale}.json`);

return module.default;
};

export default withIntlApp(loadLocale)(App);
```

## Tests

```sh
$ npm t
$ npm t -- --watch # To run watch mode
```

## License

Released under the [MIT License](https://opensource.org/licenses/mit-license.php).