Skip to content

Commit

Permalink
Merge branch 'canary' into with-mdx-remote-example
Browse files Browse the repository at this point in the history
  • Loading branch information
daneden authored Aug 28, 2020
2 parents bcb948c + 20a4928 commit 3d2eaaa
Show file tree
Hide file tree
Showing 46 changed files with 435 additions and 431 deletions.
2 changes: 1 addition & 1 deletion docs/basic-features/typescript.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ Next.js will automatically configure this file with default values. Providing yo

> Next.js uses Babel to handle TypeScript, which has some [caveats](https://babeljs.io/docs/en/babel-plugin-transform-typescript#caveats), and some [compiler options are handled differently](https://babeljs.io/docs/en/babel-plugin-transform-typescript#typescript-compiler-options).
Then, run `next` (normally `npm run dev`) and Next.js will guide you through the installation of the required packages to finish the setup:
Then, run `next` (normally `npm run dev` or `yarn dev`) and Next.js will guide you through the installation of the required packages to finish the setup:

```bash
npm run dev
Expand Down
4 changes: 3 additions & 1 deletion docs/getting-started.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ Install `next`, `react` and `react-dom` in your project:

```bash
npm install next react react-dom
# or
yarn add next react react-dom
```

Open `package.json` and add the following `scripts`:
Expand Down Expand Up @@ -71,7 +73,7 @@ function HomePage() {
export default HomePage
```

To start developing your application run `npm run dev`. This starts the development server on `http://localhost:3000`.
To start developing your application run `npm run dev` or `yarn dev`. This starts the development server on `http://localhost:3000`.

Visit `http://localhost:3000` to view your application.

Expand Down
10 changes: 10 additions & 0 deletions examples/with-react-intl/.babelrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"presets": ["next/babel"],
"plugins": [
["babel-plugin-react-intl", {
"ast": true,
"idInterpolationPattern": "[sha512:contenthash:base64:6]",
"extractFromFormatMessageCall": true
}]
]
}
1 change: 1 addition & 0 deletions examples/with-react-intl/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,4 @@ yarn-error.log*

# vercel
.vercel
compiled-lang
3 changes: 3 additions & 0 deletions examples/with-react-intl/.vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"editor.formatOnSave": true
}
49 changes: 6 additions & 43 deletions examples/with-react-intl/README.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
# Example app with [React Intl][]

This example app shows how to integrate [React Intl][] with Next.
This example app shows how to integrate [React Intl][] with Next.js.

## How to use

### Using `create-next-app`

Execute [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app) with [npm](https://docs.npmjs.com/cli/init) or [Yarn](https://yarnpkg.com/lang/en/docs/cli/create/) to bootstrap the example:

```bash
Expand All @@ -14,39 +12,21 @@ npx create-next-app --example with-react-intl with-react-intl-app
yarn create next-app --example with-react-intl with-react-intl-app
```

### Download manually

Download the example:

```bash
curl https://codeload.github.com/vercel/next.js/tar.gz/canary | tar -xz --strip=2 next.js-canary/examples/with-react-intl
cd with-react-intl
```

Install it and run:

```bash
npm install
npm run dev
# or
yarn
yarn dev
```

Deploy it to the cloud with [Vercel](https://vercel.com/import?filter=next.js&utm_source=github&utm_medium=readme&utm_campaign=next-example) ([Documentation](https://nextjs.org/docs/deployment)).

### Features of this example app
## Features of this example app

- Server-side language negotiation
- React Intl locale data loading via `pages/_document.js` customization
- React Intl integration with [custom App](https://github.com/vercel/next.js#custom-app) component
- `<IntlProvider>` creation with `locale`, `messages` props
- Default message extraction via `babel-plugin-react-intl` integration
- Default message extraction via `@formatjs/cli` integration
- Pre-compile messages into AST with `babel-plugin-react-intl` for performance
- Translation management via build script and customized Next server

### Translation Management

This app stores translations and default strings in the `lang/` dir. This dir has `.messages/` subdir which is where React Intl's Babel plugin outputs the default messages it extracts from the source code. The default messages (`en.json` in this example app) is also generated by the build script. This file can then be sent to a translation service to perform localization for the other locales the app should support.
This app stores translations and default strings in the `lang/` dir. The default messages (`en.json` in this example app) is also generated by the build script. This file can then be sent to a translation service to perform localization for the other locales the app should support.

The translated messages files that exist at `lang/*.json` are only used during production, and are automatically provided to the `<IntlProvider>`. During development the `defaultMessage`s defined in the source code are used. To prepare the example app for localization and production run the build script and start the server in production mode:

Expand All @@ -57,21 +37,4 @@ $ npm start

You can then switch your browser's language preferences to French and refresh the page to see the UI update accordingly.

### FormattedHTMLMessage support (react-intl pre-v4)

Out of the box, this example does not support the use of the `FormattedHTMLMessage` component on the server due to `DOMParser` not being present in a Node environment.
This functionality is deprecated and has been removed as of react-intl 4.0
If you still want to enable this feature, you should install a `DOMParser` implementation (e.g. `xmldom` or `jsdom`) and enable the polyfill in `server.js`:

```js
// Polyfill Node with `DOMParser` required by formatjs.
// See: https://github.com/vercel/next.js/issues/10533
const { DOMParser } = require('xmldom')
global.DOMParser = DOMParser
```

[react intl]: https://github.com/yahoo/react-intl

### Transpile react-intl

According to [react-intl docs](https://github.com/formatjs/react-intl/blob/53f2c826c7b1e50ad37215ce46b5e1c6f5d142cc/docs/Getting-Started.md#esm-build), react-intl and its underlying libraries must be transpiled to support older browsers (eg IE11). This is done by [next-transpile-modules](https://www.npmjs.com/package/next-transpile-modules) in next.config.js.
[react intl]: https://formatjs.io
29 changes: 0 additions & 29 deletions examples/with-react-intl/components/Layout.js

This file was deleted.

28 changes: 28 additions & 0 deletions examples/with-react-intl/components/Layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import * as React from 'react';
import {useIntl} from 'react-intl';
import Head from 'next/head';
import Nav from './Nav';

export default function Layout({title, children}) {
const intl = useIntl();

return (
<div>
<Head>
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>
{title ||
intl.formatMessage({
defaultMessage: 'React Intl Next.js Example',
})}
</title>
</Head>

<header>
<Nav />
</header>

{children}
</div>
);
}
Original file line number Diff line number Diff line change
@@ -1,20 +1,21 @@
import { FormattedMessage } from 'react-intl'
import Link from 'next/link'
import * as React from 'react';
import {FormattedMessage} from 'react-intl';
import Link from 'next/link';

export default function Nav() {
return (
<nav>
<li>
<Link href="/">
<a>
<FormattedMessage id="nav.home" defaultMessage="Home" />
<FormattedMessage defaultMessage="Home" />
</a>
</Link>
</li>
<li>
<Link href="/about">
<a>
<FormattedMessage id="nav.about" defaultMessage="About" />
<FormattedMessage defaultMessage="About" />
</a>
</Link>
</li>
Expand All @@ -29,5 +30,5 @@ export default function Nav() {
}
`}</style>
</nav>
)
);
}
10 changes: 5 additions & 5 deletions examples/with-react-intl/lang/en.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"title": "React Intl Next.js Example",
"nav.home": "Home",
"nav.about": "About",
"description": "An example app integrating React Intl with Next.js",
"greeting": "Hello, World!"
"11754": "An example app integrating React Intl with Next.js",
"65a8e": "Hello, World!",
"8cf04": "Home",
"8f7f4": "About",
"9c817": "React Intl Next.js Example"
}
10 changes: 5 additions & 5 deletions examples/with-react-intl/lang/fr.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"title": "React Intl Next.js Exemple",
"nav.home": "Accueil",
"nav.about": "À propos de nous",
"description": "Un exemple d'application intégrant React Intl avec Next.js",
"greeting": "Bonjour le monde!"
"11754": "Un exemple d'application intégrant React Intl avec Next.js",
"65a8e": "Bonjour le monde!",
"8cf04": "Accueil",
"8f7f4": "À propos de nous",
"9c817": "React Intl Next.js Exemple"
}
2 changes: 2 additions & 0 deletions examples/with-react-intl/next-env.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
/// <reference types="next" />
/// <reference types="next/types/global" />
10 changes: 0 additions & 10 deletions examples/with-react-intl/next.config.js

This file was deleted.

35 changes: 24 additions & 11 deletions examples/with-react-intl/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,28 +2,41 @@
"name": "with-react-intl",
"version": "1.0.0",
"scripts": {
"dev": "node --icu-data-dir=node_modules/full-icu server.js",
"build": "next build && npm run extract",
"extract": "node ./scripts/extract '{pages,components}/*.{js,ts,tsx}'",
"start": "NODE_ENV=production node --icu-data-dir=node_modules/full-icu server.js"
"dev": "NODE_ICU_DATA=node_modules/full-icu ts-node --project tsconfig.server.json server.ts",
"build": "npm run extract:i18n && npm run compile:i18n && next build && tsc -p tsconfig.server.json",
"extract:i18n": "formatjs extract '{pages,components}/*.{js,ts,tsx}' --format simple --out-file lang/en.json",
"compile:i18n": "formatjs compile-folder --ast --format simple lang/ compiled-lang/",
"start": "NODE_ENV=production NODE_ICU_DATA=node_modules/full-icu node dist/server"
},
"dependencies": {
"@formatjs/cli": "1.1.12",
"@formatjs/intl-relativetimeformat": "^2.8.2",
"@formatjs/intl-utils": "^0.6.1",
"@formatjs/cli": "^2.7.3",
"@formatjs/intl-datetimeformat": "^2.4.3",
"@formatjs/intl-getcanonicallocales": "^1.3.2",
"@formatjs/intl-numberformat": "^5.4.1",
"@formatjs/intl-pluralrules": "^3.4.0",
"@formatjs/intl-relativetimeformat": "^7.1.1",
"accepts": "^1.3.7",
"babel-plugin-react-intl": "^8.1.1",
"full-icu": "^1.3.0",
"glob": "^7.1.4",
"intl": "^1.2.5",
"intl-locales-supported": "1.8.4",
"next": "latest",
"react": "^16.9.0",
"react-dom": "^16.9.0",
"react-intl": "^3.1.12"
"react-intl": "^5.6.3"
},
"license": "ISC",
"devDependencies": {
"@types/accepts": "^1.3.5",
"cross-spawn": "7.0.3",
"next-transpile-modules": "^4.0.2"
"prettier": "2.0.5",
"ts-node": "8.0.0",
"typescript": "3.9.7"
},
"prettier": {
"singleQuote": true,
"trailingComma": "es5",
"bracketSpacing": false,
"endOfLine": "lf",
"arrowParens": "avoid"
}
}
36 changes: 0 additions & 36 deletions examples/with-react-intl/pages/_app.js

This file was deleted.

43 changes: 43 additions & 0 deletions examples/with-react-intl/pages/_app.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import * as React from 'react';
import {IntlProvider} from 'react-intl';
import {polyfill} from '../polyfills';
import App from 'next/app';

function MyApp({Component, pageProps, locale, messages}) {
return (
<IntlProvider locale={locale} messages={messages}>
<Component {...pageProps} />
</IntlProvider>
);
}

// We need to load and expose the translations on the request for the user's
// locale. These will only be used in production, in dev the `defaultMessage` in
// each message description in the source code will be used.
const getMessages = (locale: string = 'en') => {
switch (locale) {
default:
return import('../compiled-lang/en.json');
case 'fr':
return import('../compiled-lang/fr.json');
}
};

const getInitialProps: typeof App.getInitialProps = async appContext => {
const {
ctx: {req},
} = appContext;
const locale = (req as any)?.locale ?? 'en';

const [appProps, messages] = await Promise.all([
polyfill(locale),
getMessages(locale),
App.getInitialProps(appContext),
]);

return {...(appProps as any), locale, messages};
};

MyApp.getInitialProps = getInitialProps;

export default MyApp;
Loading

0 comments on commit 3d2eaaa

Please sign in to comment.