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

feat: Support providing a locale in i18n.ts instead of reading it from the pathname #1017

Merged
merged 25 commits into from
May 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
e8a502f
First draft of implementation
amannn Apr 24, 2024
7b858bd
Improve error message for missing context
amannn Apr 24, 2024
d5e4ea4
Provide example with test
amannn Apr 24, 2024
3fd46d4
Bump sizes
amannn Apr 24, 2024
2375929
Fix types
amannn Apr 24, 2024
f5cf6c7
Merge remote-tracking branch 'origin/main' into feat/960-provide-locale
amannn May 8, 2024
f41e170
Merge remote-tracking branch 'origin/main' into feat/960-provide-locale
amannn May 8, 2024
65d8547
Merge remote-tracking branch 'origin/main' into feat/960-provide-locale
amannn May 8, 2024
837384e
Rename example
amannn May 8, 2024
969bb3f
Updated lockfile
amannn May 8, 2024
1206272
Separate getting started guides
amannn May 8, 2024
c867b92
Custom cards and new app router getting started page
amannn May 9, 2024
df2e088
Arrow everywhere
amannn May 9, 2024
3065163
Wording
amannn May 9, 2024
86b6bdc
Remove index pages from toc
amannn May 9, 2024
ff6c168
Formatting for design principles
amannn May 9, 2024
793492f
Add hints to routing section
amannn May 9, 2024
0bde88c
Adapt docs where necessary
amannn May 10, 2024
a25ddda
Merge remote-tracking branch 'origin/main' into feat/960-provide-locale
amannn May 10, 2024
f102a87
Cleanup docs, error handling
amannn May 10, 2024
42a2676
Rename example
amannn May 10, 2024
efbd3e8
Mark external links as such for clarity. Also include a few minor wor…
amannn May 14, 2024
0962752
Merge remote-tracking branch 'origin/main' into feat/960-provide-locale
amannn May 14, 2024
45c6c3d
Avoid hard reload when navigating to getting started
amannn May 15, 2024
7d74607
Remove unnecessary checks
amannn May 15, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
39 changes: 39 additions & 0 deletions docs/components/Card.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import cx from 'clsx';
import NextLink from 'next/link';
import {ReactNode} from 'react';

type Props = {
children?: ReactNode;
title: string;
href: string;
};

export default function Card({children, href, title, ...props}: Props) {
return (
<NextLink
className={cx(
'group flex flex-col justify-start overflow-hidden rounded-lg border border-gray-200',
'text-current no-underline dark:shadow-none',
'hover:shadow-gray-100 dark:hover:shadow-none shadow-gray-100',
'active:shadow-sm active:shadow-gray-200',
'transition-all duration-200 hover:border-gray-300',
'bg-transparent shadow-sm dark:border-neutral-800 hover:bg-slate-50 hover:shadow-md dark:hover:border-neutral-700 dark:hover:bg-neutral-900 p-4'
)}
href={href}
{...props}
>
<span
className={cx(
'flex font-semibold items-start gap-2 text-gray-700 hover:text-gray-900',
'dark:text-neutral-200 dark:hover:text-neutral-50 flex items-center'
)}
>
{title}
<span className="transition-transform duration-75 group-hover:translate-x-[2px]">
</span>
</span>
{children && <div className="mt-3">{children}</div>}
</NextLink>
);
}
Copy link
Owner Author

Choose a reason for hiding this comment

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

Copied and forked from Nextra for customization (being able to add a description)

12 changes: 12 additions & 0 deletions docs/components/Cards.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import cx from 'clsx';
import type {ComponentProps} from 'react';

type Props = ComponentProps<'div'>;

export default function Cards({children, className, ...props}: Props) {
return (
<div className={cx('flex flex-col gap-4', className)} {...props}>
{children}
</div>
);
}
4 changes: 3 additions & 1 deletion docs/components/Hero.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,9 @@ export default function Hero({
</p>
<div className="mt-8 flex flex-col gap-4 md:flex-row lg:mt-10">
<div>
<LinkButton href="/docs">{getStarted}</LinkButton>
<LinkButton href="/docs/getting-started">
{getStarted}
</LinkButton>
</div>
<div>
<LinkButton
Expand Down
67 changes: 67 additions & 0 deletions docs/components/Logo.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
export default function Logo() {
return (
<svg
aria-label="next-intl logo"
className="h-8"
viewBox="0 0 1663.8 399"
xmlns="http://www.w3.org/2000/svg"
>
<g>
<path
d="M811.8,483V346.8c2-.8,6.4-1.7,13-2.7a164.81,164.81,0,0,1,23.9-1.5c8.6,0,15.8,1,21.5,3.1A28.62,28.62,0,0,1,884,356.1q5.25,7.2,7.5,18.6c1.5,7.6,2.2,16.9,2.2,27.9h0V483h19.5V396.3a131.41,131.41,0,0,0-3-29.1,61.1,61.1,0,0,0-10-22.7A45.29,45.29,0,0,0,881.3,330c-7.9-3.4-17.8-5.1-29.5-5.1q-21.3,0-36,3t-23.4,5.4h0V483Zm217.1,3.3a100.28,100.28,0,0,0,27.2-3.3c7.7-2.2,12.9-4.1,15.8-5.7h0l-3.6-16.8a105.18,105.18,0,0,1-13.5,5.1q-9.3,3-25.2,3-28.8,0-42-15.3t-14.1-43.8h108.9c.2-1.4.3-2.9.4-4.5s.2-3.2.2-4.8q0-38.7-17-57.3t-45.4-18.6a65.24,65.24,0,0,0-25,5A61.35,61.35,0,0,0,974,344.4a77.5,77.5,0,0,0-15.3,25.4c-3.9,10.1-5.8,22-5.8,35.5a119.68,119.68,0,0,0,4.2,32.6,66.21,66.21,0,0,0,13.5,25.6,62.29,62.29,0,0,0,23.7,16.8C1003.7,484.3,1015.3,486.3,1028.9,486.3Zm33.9-93.3H974a70.46,70.46,0,0,1,4-19.5,51.72,51.72,0,0,1,9.6-16.4,47.46,47.46,0,0,1,14.4-11.2,41,41,0,0,1,18.8-4.2q19.8,0,30.6,13.5t11.4,37.8Zm65.3,90c2.4-4.4,5.3-9.5,8.7-15.1s7.1-11.6,11.2-17.9,8.3-12.5,12.8-18.9,8.8-12.5,13.2-18.3c4.2,5.8,8.6,11.9,13.1,18.3s8.8,12.7,12.9,18.9,7.9,12.1,11.2,17.9,6.3,10.8,8.7,15.1h21c-3.8-7.4-8-14.9-12.5-22.5s-9.1-15-13.9-22-9.6-14-14.4-20.6-9.3-12.7-13.5-18.3h0l49.5-71.7h-21.3L1174,387.3l-40.2-59.4H1111l50.4,72.9q-14.1,19.2-27.6,39.2a474.65,474.65,0,0,0-25.8,43h20.1Zm195.2,3.3a72.65,72.65,0,0,0,22.8-3.4c7-2.3,11.9-4.4,14.7-6.1h0l-4.8-16.2a75.87,75.87,0,0,1-11.7,5.2c-5,1.8-11.6,2.9-19.8,2.9a54.4,54.4,0,0,1-13.2-1.5,20.45,20.45,0,0,1-10.2-6c-2.8-3-4.9-7.2-6.4-12.8s-2.2-12.6-2.2-21.5h0V344.4h61.8V327.9h-61.8V278.7l-19.5,3.6V425.1a132.63,132.63,0,0,0,2.4,27c1.6,7.6,4.3,13.9,8.2,19a34.92,34.92,0,0,0,15.6,11.4C1305.7,485,1313.7,486.3,1323.3,486.3Zm107.9-80.7V386.7h-67.8v18.9ZM1474,296.1a14.2,14.2,0,0,0,10.2-4.1c2.8-2.7,4.2-6.3,4.2-10.9s-1.4-8.2-4.2-11a14.11,14.11,0,0,0-10.2-4,14.53,14.53,0,0,0-10.2,4c-2.8,2.7-4.2,6.4-4.2,11s1.4,8.2,4.2,10.9A13.8,13.8,0,0,0,1474,296.1Zm9.9,186.9V327.9h-19.5V483Zm70.1,0V346.8c2-.8,6.3-1.7,13.1-2.7a163.34,163.34,0,0,1,23.8-1.5c8.6,0,15.8,1,21.4,3.1a28.62,28.62,0,0,1,13.8,10.4q5.25,7.2,7.5,18.6c1.5,7.6,2.2,16.9,2.2,27.9h0V483h19.5V396.3a131.41,131.41,0,0,0-3-29.1,58.17,58.17,0,0,0-10.1-22.7,45.29,45.29,0,0,0-18.9-14.5c-7.9-3.4-17.8-5.1-29.5-5.1q-21.3,0-36,3t-23.4,5.4h0V483Zm199.4,3.3a72.65,72.65,0,0,0,22.8-3.4c7-2.3,11.9-4.4,14.7-6.1h0l-4.8-16.2a75.87,75.87,0,0,1-11.7,5.2c-5,1.8-11.6,2.9-19.8,2.9a54.4,54.4,0,0,1-13.2-1.5,20.45,20.45,0,0,1-10.2-6c-2.8-3-4.9-7.2-6.4-12.8s-2.2-12.6-2.2-21.5h0V344.4h61.8V327.9h-61.8V278.7l-19.5,3.6V425.1a132.63,132.63,0,0,0,2.4,27c1.6,7.6,4.3,13.9,8.2,19a34.92,34.92,0,0,0,15.6,11.4C1735.8,485,1743.8,486.3,1753.4,486.3Zm105.2-.6,2.7-16.2a90.28,90.28,0,0,1-10.4-2.1,15.3,15.3,0,0,1-7-3.8,15.7,15.7,0,0,1-4.1-6.9,40.44,40.44,0,0,1-1.3-11.5h0v-195l-19.5,3.6v192c0,7.4.8,13.6,2.6,18.5a29.28,29.28,0,0,0,7.5,12,30.81,30.81,0,0,0,12.3,6.9,65.79,65.79,0,0,0,17.2,2.5Z"
fill="currentColor"
transform="translate(-197.5 -171.5)"
/>
<g>
<path
d="M528.8,509q-6.3,6-13.2,11.4a190,190,0,1,1,38-40.2"
fill="none"
stroke="#5fc3e7"
strokeWidth="18"
transform="translate(-197.5 -171.5)"
/>
<circle cx="329.2" cy="339.5" fill="#5fc3e7" r="9" />
<line
fill="none"
stroke="#5fc3e7"
strokeLinecap="square"
strokeWidth="18"
x1="40"
x2="353.5"
y1="105"
y2="105.5"
/>
<ellipse
cx="202"
cy="199.5"
fill="none"
rx="93.5"
ry="190.5"
stroke="#5fc3e7"
strokeWidth="18"
/>
<line
fill="none"
stroke="#5fc3e7"
strokeLinecap="square"
strokeWidth="18"
x1="49.5"
x2="353.5"
y1="304.5"
y2="304.5"
/>
<line
fill="none"
stroke="#5fc3e7"
strokeLinecap="square"
strokeWidth="18"
x1="9"
x2="389"
y1="206"
y2="206"
/>
</g>
</g>
</svg>
);
}
6 changes: 5 additions & 1 deletion docs/pages/docs/design-principles.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,15 @@ This page also links to planned improvements in order to act as a transparent re
Internationalization clearly requires flexibility from your codebase. However, even implementing a single language properly can already be a challenge by itself.

Using **dynamic text labels** is the most obvious aspect of internationalization, but supporting a language well also includes many other aspects:

1. **Pluralization rules**: While a language like English has only two plural forms (singular and plural), other languages have up to six different forms.
2. **Date and time formatting**: Different languages have different conventions for formatting dates and times. Even the year displayed can vary from country to country; for example, Thailand uses the Buddhist calendar, which is 543 years ahead of the Gregorian one.
3. **Number formatting**: Formatting conventions for numbers vary across different languages. For instance, when comparing English and German, the separators for thousands and decimals are flipped.
4. **List formatting**: Formatting lists like "HTML, CSS, and JavaScript" is not only a matter of assembling strings in the right order, but also of using language-specific conjunctions and punctuation marks.
5. **Text direction**: While most languages are written from left to right, some languages like Arabic are written from right to left and require a mirrored layout.

On top of this come typical app problems like:

1. **Rich text formatting**: Many apps need to support some way of rich text, e.g. to embed links into text labels ("Learn more in [the rich text docs](/docs/usage/messages#rich-text).").
2. **Time zones**: Displaying dates requires consistent handling of time zones across the server and client, potentially even customized based on a preference of the user.
3. **Relative time formatting**: Displaying relative times like "5 minutes ago" or "in 2 hours" requires special care to get the formatting right, and also to make sure the rendered result is in sync across the server and client. Potentially, you also need a mechanism to update the displayed time regularly.
Expand Down Expand Up @@ -91,6 +93,7 @@ Next.js has a rich ecosystem of libraries that can be used alongside `next-intl`
`next-intl` was designed with high-traffic sites in mind that need to deliver a fast and reliable user experience and has proven to work on complex e-commerce pages with outstanding Core Web Vitals.

To achieve this, `next-intl` primarly relies on these techniques currently:

1. **Splitting of messages**: By splitting messages by locale, and optionally also by server, client and component, we can reduce the amount of messages that are sent to the client. This is especially important for apps that support many languages and have a large amount of messages.
2. **Shortcuts**: By detecting plain messages, these messages can be returned immediately without having to parse them first.
3. **Caching**: Parsing and formatting of messages is cached across your app, therefore reducing the amount of necessary computation.
Expand All @@ -109,6 +112,7 @@ That being said, `next-intl` has a Next.js-agnostic core that can be used in any
We've all been there, technology moves on, and sometimes you need to move on as well. `next-intl` is designed to be a good citizen in your codebase, and to make it possible to migrate away from certain parts of your stack in case this becomes necessary.

If you ever feel like Next.js or `next-intl` is not the right fit for your project anymore, you have multiple options here:

1. **Moving away from Next.js**: If you decide to migrate away from Next.js, you can continue to use the core library [`use-intl`](/docs/environments/core-library) in any React app, e.g. allowing you to reuse existing components in [a Remix app](/examples#remix).
2. **Moving away from `next-intl`**: If you find that `next-intl` doesn't fit your needs anymore, you'll have to adapt app code that references the library, but you can still reuse your [standards-based](#standards-based) ICU messages and replace formatting APIs e.g. with direct calls to the [ECMAScript Internationalization API](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl).

Expand All @@ -118,4 +122,4 @@ That being said, we're doing our best to make `next-intl` a great fit for your p

---

Woah, this was a long read. Did you really read all of this? `next-intl` was created out of a lot of curiosity and passion for internationalization, seems like we share that. We're always curious to hear how `next-intl` is working out for you. If you have any feedback or questions, please don't hesitate to [reach out](https://github.com/amannn/next-intl/discussions)!
Woah, this was a long read. Did you really read all of this? `next-intl` was created out of a lot of curiosity and passion for internationalization, seems like we share that! We're always curious to hear how `next-intl` is working out for you. If you have any feedback or questions, please don't hesitate to [reach out](https://github.com/amannn/next-intl/discussions)!
Original file line number Diff line number Diff line change
@@ -1,30 +1,27 @@
import {Card} from 'nextra-theme-docs';
import Card from 'components/Card';
import Cards from 'components/Cards';

# Environments

The `next-intl` APIs are available in the following environments:

<div className="mt-8 flex flex-col gap-4 md:w-2/3">
<Cards className="mt-8 lg:w-1/2">
<Card
arrow
title="Server & Client Components"
href="/docs/environments/server-client-components"
/>
<Card
arrow
title="Metadata API & Route Handlers"
href="/docs/environments/metadata-route-handlers"
/>
<Card
arrow
title="Error files (e.g. not-found)"
href="/docs/environments/error-files"
/>
<Card
arrow
title="Core library (agnostic)"
href="/docs/environments/core-library"
/>
</div>
</Cards>

While modern browsers and server runtimes typically support all necessary JavaScript APIs that are required for `next-intl`, you can double check [the runtime requirements](/docs/environments/runtime-requirements).
1 change: 0 additions & 1 deletion docs/pages/docs/environments/_meta.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
{
"index": "Overview",
"server-client-components": "Server & Client Components",
"metadata-route-handlers": "Metadata & Route Handlers",
"error-files": "Error files (e.g. not-found)",
Expand Down
10 changes: 6 additions & 4 deletions docs/pages/docs/environments/core-library.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,17 @@ While `next-intl` is primarily intended to be used in Next.js apps, the core is
`next-intl` is based on a library called [`use-intl`](https://www.npmjs.com/package/use-intl) that is developed in parallel.

This core library contains most features of `next-intl`, but lacks the following Next.js-specific features:

1. [Routing APIs](/docs/routing)
2. [Awaitable APIs for the Metadata API and Route Handlers](/docs/environments/metadata-route-handlers)
3. [Server Components integration](/docs/environments/server-client-components) along with `i18n.ts`

In case Server Components establish themselves in React apps outside of Next.js, the support for Server Components might be moved to the core library in the future.

In contrast, `use-intl` contains all APIs that are necessary for handling i18n in regular React apps:

- [`useTranslations`](/docs/usage/messages) for translating messages
- `useFormatter` for formatting of [numbers](/docs/usage/numbers), [dates & times](/docs/usage/dates-times) and [lists](/docs/usage/lists)
- `useFormatter` for formatting [numbers](/docs/usage/numbers), [dates & times](/docs/usage/dates-times) and [lists](/docs/usage/lists)
- [Configuration APIs](/docs/usage/configuration) (note however that `NextIntlProvider` is called `IntlProvider` in `use-intl`)

This allows you to use the same APIs that you know from `next-intl` in other environments:
Expand All @@ -32,11 +34,11 @@ This allows you to use the same APIs that you know from `next-intl` in other env
import {IntlProvider, useTranslations} from 'use-intl';

// You can get the messages from anywhere you like. You can also
// fetch them from within a component and then render the provider
// fetch them from within a component and then render the provider
// along with your app once you have the messages.
const messages = {
"App": {
"hello": 'Hello {username}!'
App: {
hello: 'Hello {username}!'
}
};

Expand Down
27 changes: 14 additions & 13 deletions docs/pages/docs/environments/error-files.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,15 @@ The Next.js App Router's file convention provides two files that can be used for

This page provides practical guides for these cases.

<Callout>
Have a look at [the App Router
example](https://next-intl-example-app-router.vercel.app) to explore a working
app with error handling.
</Callout>
**Tip:** You can have a look at [the App Router example](/examples#app-router) to explore a working app with error handling.

## `not-found.js`

<Callout>
This section is only relevant if you're using [i18n
routing](/docs/getting-started/app-router).
</Callout>

Next.js renders the closest `not-found` page when a route segment calls the [`notFound` function](https://nextjs.org/docs/app/api-reference/functions/not-found). We can use this mechanism to provide a localized 404 page by adding a `not-found` file within the `[locale]` folder.

```tsx filename="app/[locale]/not-found.tsx"
Expand Down Expand Up @@ -104,11 +105,11 @@ When an `error` file is defined, Next.js creates [an error boundary within your
<figure>
<div className="w-full lg:w-[500px]">
```tsx
<LocaleLayout>
<RootLayout>
<ErrorBoundary fallback={<Error />}>
<Page />
</ErrorBoundary>
</LocaleLayout>
</RootLayout>
```
</div>

Expand All @@ -120,20 +121,20 @@ When an `error` file is defined, Next.js creates [an error boundary within your

Since the `error` file must be defined as a Client Component, you have to use [`NextIntlClientProvider`](/docs/usage/configuration#nextintlclientprovider) to provide messages in case the `error` file renders.

```tsx filename="app/[locale]/layout.tsx"
```tsx filename="layout.tsx"
import pick from 'lodash/pick';
import {NextIntlClientProvider} from 'next-intl';
import {getMessages} from 'next-intl/server';

export default async function LocaleLayout({children}) {
// ...
export default async function RootLayout(/* ... */) {
const messages = await getMessages();

return (
<html lang={locale}>
<body>
<NextIntlClientProvider
locale={locale}
// Make sure to provide at least the messages for `Error`
messages={pick(messages, 'Error')}
>
{children}
Expand All @@ -146,7 +147,7 @@ export default async function LocaleLayout({children}) {

Once `NextIntlClientProvider` is in place, you can use functionality from `next-intl` in the `error` file:

```tsx filename="app/[locale]/error.tsx"
```tsx filename="error.tsx"
'use client';

import {useTranslations} from 'next-intl';
Expand All @@ -163,9 +164,9 @@ export default function Error({error, reset}) {
}
```

Note that `error.tsx` is loaded right after your app has initialized. If your app is performance-senstive and you want to avoid loading translation functionality from `next-intl` as part of the initial bundle, you can export a lazy reference from your `error` file:
Note that `error.tsx` is loaded right after your app has initialized. If your app is performance-senstive and you want to avoid loading translation functionality from `next-intl` as part of this bundle, you can export a lazy reference from your `error` file:
Copy link
Owner Author

Choose a reason for hiding this comment

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

It's actually not the "initial bundle", but a lazy loaded one after init.


```tsx filename="app/[locale]/error.tsx"
```tsx filename="error.tsx"
'use client';

import {lazy} from 'react';
Expand Down
5 changes: 3 additions & 2 deletions docs/pages/docs/environments/metadata-route-handlers.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ There are a few places in Next.js apps where you can apply internationalization

To internationalize metadata like the page title, you can use functionality from `next-intl` in the [`generateMetadata`](https://nextjs.org/docs/app/api-reference/functions/generate-metadata#generatemetadata-function) function that can be exported from pages and layouts.

```tsx filename="app/[locale]/layout.tsx"
```tsx filename="layout.tsx"
import {getTranslations} from 'next-intl/server';

export async function generateMetadata({params: {locale}}) {
Expand All @@ -32,7 +32,8 @@ export async function generateMetadata({params: {locale}}) {
<Callout>
By passing an explicit `locale` to the awaitable functions from `next-intl`,
you can make the metadata handler eligible for [static
rendering](/docs/getting-started/app-router#static-rendering).
rendering](/docs/getting-started/app-router#static-rendering) if you're using
[i18n routing](/docs/getting-started/app-router).
</Callout>

### Open Graph images
Expand Down
9 changes: 5 additions & 4 deletions docs/pages/docs/environments/runtime-requirements.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -47,20 +47,21 @@ function IntlPolyfills() {
<Script
strategy="beforeInteractive"
src={
'https://cdnjs.cloudflare.com/polyfill/v3/polyfill.min.js?features=' + polyfills.join(',')
'https://cdnjs.cloudflare.com/polyfill/v3/polyfill.min.js?features=' +
polyfills.join(',')
}
/>
);
}
```

<Callout type="warning">
Note that the polyfill service doesn't support every locale. You can find a list of the
available polyfills in the [`polyfill-service` GitHub
Note that the polyfill service doesn't support every locale. You can find a
list of the available polyfills in the [`polyfill-service`
repository](https://github.com/cdnjs/polyfill-service/tree/main/polyfill-libraries/3.101.0/polyfills/__dist)
(e.g. search for `Intl.DateTimeFormat.~locale.de-AT`).
</Callout>

## Node
## Node.js

The minimum version to support all relevant `Intl` APIs is **Node.js 13**. Starting from this version, all required APIs are available.