Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add initial i18n documentation #18067

Merged
merged 9 commits into from Oct 23, 2020
Merged
134 changes: 134 additions & 0 deletions docs/advanced-features/i18n-routing.md
@@ -0,0 +1,134 @@
# i18n (internationalize) Routing
ijjk marked this conversation as resolved.
Show resolved Hide resolved

<details>
<summary><b>Examples</b></summary>
<ul>
<li><a href="https://github.com/vercel/next.js/tree/canary/examples/i18n-routing">i18n routing</a></li>
ijjk marked this conversation as resolved.
Show resolved Hide resolved
</ul>
</details>

Next.js has built in support for i18n routing since v9.5.7. With the built-in support you can provide a list of locales you want to support, the default locale, and domain specific locales and Next.js will help handle the routing for these values.
ijjk marked this conversation as resolved.
Show resolved Hide resolved

The i18n routing support is currently meant to compliment existing i18n library solutions like react-intl, react-i18next, lingui, rosetta, and others by streamlining the routes and locale parsing aspects of i18n.
ijjk marked this conversation as resolved.
Show resolved Hide resolved

## How to get started
ijjk marked this conversation as resolved.
Show resolved Hide resolved

To get started you need to add the `i18n` config to your `next.config.js` file.
ijjk marked this conversation as resolved.
Show resolved Hide resolved

```js
module.exports = {
i18n: {
// These are all the locales you want to be able to support in
ijjk marked this conversation as resolved.
Show resolved Hide resolved
// your application
locales: ['en-US', 'fr', 'nl-NL'],
// This is the default locale you want to be used when visiting
// a non-local prefixed path e.g. `/hello`
defaultLocale: 'en-US',
// These are a list of locale domains and the default locale they
// should handle (these are not required)
domains: [
{
domain: 'example.com',
defaultLocale: 'en-US',
},
{
domain: 'example.nl',
defaultLocale: 'nl-NL',
},
{
domain: 'example.fr',
defaultLocale: 'fr',
},
],
},
}
```

## How are the routes handled

Using the above config when a user visits `/` Next.js will automatically try to detect which locale the user prefers with the [`Accept-Language`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Accept-Language) header and the current domain.
ijjk marked this conversation as resolved.
Show resolved Hide resolved

If a locale other than the default locale is detected the user will be redirected to either:
ijjk marked this conversation as resolved.
Show resolved Hide resolved

a) the domain with that locale specified as the default
ijjk marked this conversation as resolved.
Show resolved Hide resolved
b) the locale prefixed path if no domain matched
ijjk marked this conversation as resolved.
Show resolved Hide resolved

For example, if a user with the `Accept-Language` header `fr;q=0.9` visits `example.com` they will be redirected to `example.fr` since that domain handles the `fr` locale by default.
ijjk marked this conversation as resolved.
Show resolved Hide resolved

If we did not have the `example.fr` domain configured then the user would instead be redirected to `/fr`.
ijjk marked this conversation as resolved.
Show resolved Hide resolved

## Accessing the locale information

The detected locale information is provided in multiple places to ensure it's available where it might be needed.
Copy link
Member

Choose a reason for hiding this comment

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

Could probably drop this sentence?


On the `next/router` instance available via the [`useRouter()`](https://nextjs.org/docs/api-reference/next/router#userouter) hook we expose the active locale under `router.locale`, all of the supported locales under `router.locales`, and the current default locale under `router.defaultLocale`.
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
On the `next/router` instance available via the [`useRouter()`](https://nextjs.org/docs/api-reference/next/router#userouter) hook we expose the active locale under `router.locale`, all of the supported locales under `router.locales`, and the current default locale under `router.defaultLocale`.
On the `next/router` instance available via the [`useRouter()`](https://nextjs.org/docs/api-reference/next/router#userouter) hook, we expose the active locale under `router.locale`, all of the supported locales under `router.locales`, and the current default locale under `router.defaultLocale`.

Copy link
Member

Choose a reason for hiding this comment

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

This feels like it could be a bulleted list instead of using commas.


When prerendering pages with `getStaticProps` the locale information is provided in [the context](https://nextjs.org/docs/basic-features/data-fetching#getstaticprops-static-generation) provided to the function as `locale` for the active locale and `locales` for all supported locales.
Copy link
Member

Choose a reason for hiding this comment

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

Should we link to pre-rendering docs?

ijjk marked this conversation as resolved.
Show resolved Hide resolved

When leveraging `getStaticPaths`, the supported locales are also provided in the context provided to the function under `locales`.

## Transition between locales

To handle transitioning between locales you can either leverage `next/link` or the `next/router` methods directly.
ijjk marked this conversation as resolved.
Show resolved Hide resolved

For `next/link`, a `locale` prop can be provided to transition to a different locale from the currently active one. If no `locale` prop is provided the currently active `locale` is used during client-transitions. For example:
ijjk marked this conversation as resolved.
Show resolved Hide resolved

```jsx
import Link from 'next/link'

export default function IndexPage(props) {
return (
<Link href="/another" locale="fr">
<a>To /fr/another</a>
</Link>
)
}
```

When using the `next/router` methods directly you can specify the `locale` that should be used via the transition options. For example:
ijjk marked this conversation as resolved.
Show resolved Hide resolved

```jsx
import { useCallback } from 'react'
ijjk marked this conversation as resolved.
Show resolved Hide resolved
import { useRouter } from 'next/router'

export default function IndexPage(props) {
const router = useRouter()

return (
<div
onClick={() => {
router.push('/another', '/another', { locale: 'fr' })
}}
>
to /fr/another
</div>
)
}
```

## How does this work with static generation
ijjk marked this conversation as resolved.
Show resolved Hide resolved

### Automatically Statically Optimized Pages

For pages that are automatically statically optimized a version of the page will be generated for each locale. This ensures the `lang` HTML attribute and `router.locale` value have the correct initial values for each locale.
ijjk marked this conversation as resolved.
Show resolved Hide resolved

### Non-dynamic getStaticProps Pages

For non-dynamic `getStaticProps` pages a version is generated for each locale like above and `getStaticProps` is also called with each `locale` that is being rendered. If you would like to opt-out of a certain locale from being prerendered you can return `notFound: true` from `getStaticProps` and this variant of the page will not be generated.
ijjk marked this conversation as resolved.
Show resolved Hide resolved

### Dynamic getStaticProps Pages

For dynamic `getStaticProps` pages any locale variants of the page that is desired to be prerendered needs to be returned from [`getStaticPaths`](/docs/basic-features/data-fetching#getstaticpaths-static-generation). Along with the `params` object that can be returned for the `paths` you can now also return a `locale` field specifying which locale you want to render. For example:
ijjk marked this conversation as resolved.
Show resolved Hide resolved

```js
// pages/blog/[slug].js
export const getStaticPaths = ({ locales }) => {
return {
paths: [
{ params: { slug: 'post-1' }, locale: 'en-US' },
{ params: { slug: 'post-1' }, locale: 'fr' },
],
fallback: true,
}
}
```
3 changes: 3 additions & 0 deletions docs/basic-features/data-fetching.md
Expand Up @@ -54,11 +54,14 @@ The `context` parameter is an object containing the following keys:
- `params` contains the route parameters for pages using dynamic routes. For example, if the page name is `[id].js` , then `params` will look like `{ id: ... }`. To learn more, take a look at the [Dynamic Routing documentation](/docs/routing/dynamic-routes.md). You should use this together with `getStaticPaths`, which we’ll explain later.
- `preview` is `true` if the page is in the preview mode and `undefined` otherwise. See the [Preview Mode documentation](/docs/advanced-features/preview-mode.md).
- `previewData` contains the preview data set by `setPreviewData`. See the [Preview Mode documentation](/docs/advanced-features/preview-mode.md).
- `locale` contains the active locale (if enabled)
ijjk marked this conversation as resolved.
Show resolved Hide resolved
- `locales` contains all supported locales (if enabled)
ijjk marked this conversation as resolved.
Show resolved Hide resolved

`getStaticProps` should return an object with:

- `props` - A **required** object with the props that will be received by the page component. It should be a [serializable object](https://en.wikipedia.org/wiki/Serialization)
- `revalidate` - An **optional** amount in seconds after which a page re-generation can occur. More on [Incremental Static Regeneration](#incremental-static-regeneration)
- `notFound` - An **optional** boolean value specifying the page should handle as the 404 page returning the 404 status. More on [Incremental Static Regeneration](#incremental-static-regeneration)
ijjk marked this conversation as resolved.
Show resolved Hide resolved

> **Note**: You can import modules in top-level scope for use in `getStaticProps`.
> Imports used in `getStaticProps` will [not be bundled for the client-side](#write-server-side-code-directly).
Expand Down