diff --git a/.circleci/config.yml b/.circleci/config.yml
index 94b29e9786e4..987f4b8674df 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -81,22 +81,22 @@ jobs:
if ! git diff-tree --no-commit-id --name-only -r HEAD | grep -E "(^docs\/.*)|(docusaurus-1\.x\/.*)|(website-1\.x\/.*)"; then
echo "Skipping deploy. No relevant v1 website files have changed"
elif [[ $CIRCLE_PROJECT_USERNAME == "facebook" && -z $CI_PULL_REQUEST && -z $CIRCLE_PR_USERNAME ]]; then
- echo "Deploying website..."
+ echo "Deploying website v1..."
+ cd website-1.x
+
# install Docusaurus and generate file of English strings
- cd website-1.x && yarn run write-translations
- # install Crowdin
- sudo apt-get update
- sudo apt-get install default-jre rsync
- wget https://artifacts.crowdin.com/repo/deb/crowdin.deb -O crowdin.deb
- sudo dpkg -i crowdin.deb
- sleep 5
+ yarn run write-translations
+
# upload translation strings and download translations
- yarn run crowdin-upload
+ yarn crowdin-upload
+
# download only enabled languages
- for lang in fr ko ru ro pt-BR zh-CN
- do
- yarn crowdin-download -l $lang
- done
+ yarn crowdin-download
+ # for lang in fr ko ru ro pt-BR zh-CN
+ # do
+ # yarn crowdin-download -l $lang
+ # done
+
# publish
GIT_USER=docusaurus-bot USE_SSH=false yarn run publish-gh-pages
else
@@ -119,4 +119,4 @@ workflows:
- deploy-website:
requires:
- tests
- filters: *filter-only-master
\ No newline at end of file
+ filters: *filter-only-master
diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json
new file mode 100644
index 000000000000..99227b6ce8aa
--- /dev/null
+++ b/.devcontainer/devcontainer.json
@@ -0,0 +1,10 @@
+{
+ "name": "Docusaurus Dev Container",
+ "image": "mcr.microsoft.com/vscode/devcontainers/typescript-node:0-10-buster",
+ "settings": {
+ "terminal.integrated.shell.linux": "/bin/bash"
+ },
+ "extensions": ["dbaeumer.vscode-eslint"],
+ "forwardPorts": [3000],
+ "postCreateCommand": "yarn install"
+}
diff --git a/.eslintignore b/.eslintignore
index c2a430de7e39..48ad73c29313 100644
--- a/.eslintignore
+++ b/.eslintignore
@@ -1,6 +1,7 @@
__fixtures__
dist
node_modules
+.yarn
build
coverage
jest.config.js
@@ -8,26 +9,15 @@ jest.transform.js
website-1.x/
website/
scripts
+
+packages/docusaurus/lib/
+packages/docusaurus-*/lib/*
+!packages/docusaurus-1.x/lib/*
+packages/docusaurus-1.x/lib/core/__tests__/split-tab.test.js
packages/docusaurus-1.x/lib/core/metadata.js
packages/docusaurus-1.x/lib/core/MetadataBlog.js
-packages/docusaurus-1.x/lib/core/__tests__/split-tab.test.js
-packages/docusaurus-utils/lib/
-packages/docusaurus-utils-validation/lib/
-packages/docusaurus/lib/
-packages/docusaurus-init/lib/
-packages/docusaurus-plugin-client-redirects/lib/
-packages/docusaurus-plugin-content-blog/lib/
-packages/docusaurus-plugin-content-docs/lib/
-packages/docusaurus-plugin-content-pages/lib/
-packages/docusaurus-plugin-debug/lib/
-packages/docusaurus-plugin-sitemap/lib/
-packages/docusaurus-plugin-ideal-image/lib/
+packages/docusaurus-*/lib-next/
packages/docusaurus-plugin-ideal-image/copyUntypedFiles.js
-packages/docusaurus-theme-common/lib/
-packages/docusaurus-theme-classic/lib/
-packages/docusaurus-theme-classic/lib-next/
-packages/docusaurus-theme-bootstrap/lib/
-packages/docusaurus-migrate/lib/
packages/docusaurus-1.x/.eslintrc.js
packages/docusaurus-init/templates/facebook/.eslintrc.js
diff --git a/.github/ISSUE_TEMPLATE/bug.md b/.github/ISSUE_TEMPLATE/bug.md
index 762a7816f9f9..b668bf2cd9cb 100644
--- a/.github/ISSUE_TEMPLATE/bug.md
+++ b/.github/ISSUE_TEMPLATE/bug.md
@@ -4,6 +4,18 @@ about: Submit a bug report to help us improve
labels: 'bug, needs triage'
---
+
+
## 🐛 Bug Report
(A clear and concise description of what the bug is)
@@ -14,6 +26,8 @@ labels: 'bug, needs triage'
## To Reproduce
+If possible, use https://new.docusaurus.io to create a CodeSandbox reproducible demo of the bug.
+
(Write your steps here:)
1. Step 1...
@@ -45,13 +59,17 @@ labels: 'bug, needs triage'
+- Public source code:
+- Public site url:
- Docusaurus version used:
- Environment name and version (e.g. Chrome 78.0.3904.108, Node.js 10.17.0):
- Operating system and version (desktop or mobile):
## Reproducible Demo
-(Paste the link to an example repo, including a `siteConfig.js`, and exact instructions to reproduce the issue.)
+If possible, use https://new.docusaurus.io to create a CodeSandbox reproducible demo of the bug.
+
+(Paste the link to an example repo, including a `docusaurus.config.js`, and exact instructions to reproduce the issue.)
diff --git a/website-1.x/blog/2021-01-19-docusaurus-2020-recap.md b/website-1.x/blog/2021-01-19-docusaurus-2020-recap.md
new file mode 100644
index 000000000000..aa27e5910086
--- /dev/null
+++ b/website-1.x/blog/2021-01-19-docusaurus-2020-recap.md
@@ -0,0 +1,139 @@
+---
+title: Docusaurus 2020 Recap
+author: Sébastien Lorber
+authorTitle: Docusaurus maintainer
+authorURL: https://sebastienlorber.com
+authorImageURL: https://github.com/slorber.png
+authorTwitter: sebastienlorber
+tags: [recap]
+image: /img/docusaurus-2020-recap.png
+---
+
+**2020 was great for Docusaurus**, despite [a regrettable start](https://docusaurus.io/blog/2020/01/07/tribute-to-endi) and a tumultuous year for everyone.
+
+We continued to invest in [Docusaurus 2](https://v2.docusaurus.io/), and made it reach **full feature parity** with [Docusaurus 1](https://v1.docusaurus.io/).
+
+We now **recommend Docusaurus 2** as the **default choice** to start a new Docusaurus project and encourage v1 users to [migrate to Docusaurus 2](https://v2.docusaurus.io/docs/migration).
+
+We are **still in alpha**, but expect **some good news very soon**!
+
+![Docusaurus v1 vs v2 npm trends](/img/blog/2020-recap/docusaurus-plushie-banner.jpeg)
+
+
+
+## Docusaurus 2 highlights
+
+We have worked on many features this year, and would like to highlight the most significant ones:
+
+- **i18n**: easily translate your Docusaurus site, released soon! ([preview](https://github.com/facebook/docusaurus/pull/3325), [doc](https://v2.docusaurus.io/docs/next/i18n/introduction))
+- **Version dropdown**: enable contextual version switch
+- **Versioning options**: solving the most common pain-points users had with versioning
+- **Contextual search**: search in the current version, use the brand-new DocSearch 3 experience
+- **Markdown pages**: use Markdown instead of React components to create standalone pages
+- **Better theme**: various UI, UX and accessibility improvements
+- **PWA**: add offline support to your site, and make it installable
+- **Fail-fast**: strict config validation, detect broken links, and prevent bad production deployments
+- **Multi-instance**: use the docs plugin twice on a single site (e.g. iOS/Android SDK docs)
+- **Migration CLI**: automate the upgrade from Docusaurus 1
+- **CodeSandbox**: assess Docusaurus easily from your browser with [new.docusaurus.io](https://new.docusaurus.io/)
+- **Canary releases**: use the `@canary` npm tag to use the upcoming release before anyone else
+- **TypeScript**: progressive adoption for internal code, and improve usage for users
+- **Publish Infima**: it is now [open-source](https://github.com/facebookincubator/infima)
+
+## Docusaurus 2 growth
+
+The plan to [rebuild Docusaurus from scratch in 2019](https://docusaurus.io/blog/2019/12/30/docusaurus-2019-recap) paid off: after a slow start, Docusaurus 2 has been widely adopted and has **already outgrown Docusaurus 1** usage.
+
+![Docusaurus v1 vs v2 npm trends](/img/blog/2020-recap/docusaurus-npm-trends.png)
+
+Notable **projects, startups, large companies, and individuals** adopted Docusaurus 2 ([showcase](https://v2.docusaurus.io/showcase)):
+
+- [Supabase](https://supabase.io)
+- [React Navigation](https://reactnavigation.org)
+- [React Redux](https://react-redux.js.org/)
+- [Vector](https://vector.dev)
+- [Algolia DocSearch](https://docsearch.algolia.com)
+- [SAP Cloud SDK](https://sap.github.io/cloud-sdk)
+- [Palo Alto Cortex XSOAR](https://xsoar.pan.dev)
+- [Quddús George's website](https://portfoliosaurus.now.sh)
+
+We helped **large scale Docusaurus 1 sites to upgrade**, ensuring a proper **migration path** and **feature parity**.
+
+[React Native](https://reactnative.dev/) was successfully upgraded to Docusaurus 2 ([archived v1 site](http://archive.reactnative.dev/)):
+
+![React Native screenshot](/img/blog/2020-recap/react-native-screenshot.png)
+
+Localized Docusaurus 1 sites (like **Jest**) will be able to upgrade too:
+
+![Jest in Japanese screenshot](/img/blog/2020-recap/jest-screenshot.png)
+
+We also saw the **[first right-to-left](https://datagit.ir/)** Docusaurus 2 site published:
+
+![Datagit screenshot](/img/blog/2020-recap/datagit-rtl-screenshot.png)
+
+## GitHub Activity
+
+- **Stars**: 14632 -> 20946 (+43.2% y/y)
+- **Total Contributors**: 303 -> 512 (+68.9% y/y). Most of which are non-Facebook contributors
+- **Weekly npm Downloads**: 2356 -> 25592 (+986% y/y)
+- **On GitHub**, Docusaurus 1 is used by 6311 projects (+62.9% y/y) while Docusaurus 2 is used by 5039 projects (+1940% y/y)
+
+## Collaboration with Major League Hacking
+
+We have welcomed [Major League Hacking](https://mlh.io/) (MLH) fellows for 2 seasons already.
+
+We are very thankful for the **various contributions** they made, such as:
+
+- Writing the foundations of the v1 to v2 migration CLI
+- Help migrate the React Native website from v1 to v2
+- Making the config validation more strict and exhaustive, returning helpful error messages
+- Adding CodeSandbox support
+- Improving the CI pipelines: build size and Lighthouse bots
+
+We look forward to continuing this collaboration in 2021.
+
+## Media
+
+Dmitry Vinnik (Developer Advocate @ Facebook) explains Docusaurus in [60 seconds](https://www.youtube.com/watch?v=_An9EsKPhp0) or [15min](https://www.youtube.com/watch?v=Yhyx7otSksg) videos.
+
+Rachel Nabors (Documentation Engineer @ Facebook) talked a bit about Docusaurus in [React Native Radio 178 (podcast)](https://reactnativeradio.com/episodes/178-documenting-react-native-with-rachel-nabors-gWxwySPl), and William Candillon the [React Native website migration (video)](https://www.youtube.com/watch?v=-zhjq2ECKq4).
+
+Many blog posts have been published:
+
+- [To the Makers of Docusaurus](https://portfoliosaurus.now.sh/blog/toTheMakers) by Quddus George
+- [Richer API documentation with Redoc and Docusaurus](https://davidgoss.co/blog/api-documentation-redoc-docusaurus/) by David Goss
+- [How to Build a Plugin for Docusaurus v2](https://aknapen.nl/blog/how-to-build-a-plugin-for-docusaurus-v2/) by Adriaan Knapen
+- [React Tracked Documentation Website with Docusaurus v2](https://blog.axlight.com/posts/react-tracked-documentation-website-with-docusaurus-v2/) by Daishi Kato
+- [Easy documentation with Docusaurus](https://blog.logrocket.com/easy-documentation-with-docusaurus/) by Anshul Goyal (MLH fellow)
+- [Build Beautiful Documentation Websites with Docusaurus](https://lo-victoria.com/build-beautiful-documentation-websites-with-docusaurus) by Victoria Lo
+
+## Community
+
+The Docusaurus community continues to grow, the [Discord](https://discord.gg/docusaurus) server is quite active, and [Stack Overflow questions](https://stackoverflow.com/questions/tagged/docusaurus) keep being posted.
+
+The **modular architecture** of Docusaurus 2 allowed the community to build and publish [third-party plugins](https://v2.docusaurus.io/community/resources#community-plugins-). As we would like to federate better our community, if you are building a plugin, please [let us know](https://github.com/facebook/docusaurus/discussions/4025).
+
+## What's next?
+
+As the **core features of Docusaurus 2** have finally been built, we will be able to dedicate more time to solve the pain points and bugs reported by the community, and make Docusaurus stable and convenient enough to enter the **beta and release-candidate phase**.
+
+With proper support for **i18n and versioning**, and **large scale migrations** such as **React Native** and **Jest**, we now have a clear migration path for all Docusaurus 1 sites.
+
+We still have a few **major features** that we would like to work on:
+
+- [Create a theme gallery](https://github.com/facebook/docusaurus/issues/3522), make it easy to switch from one another, and include **first-class Tailwind support**
+- [Upgrade to Webpack 5](https://github.com/facebook/docusaurus/issues/4027), improve performances and build times
+- [Better compatibility with CommonMark](https://github.com/facebook/docusaurus/issues/3018), as MDX and makes it harder for CommonMark-based sites to adopt Docusaurus
+- [Upgrade to MDX 2.0](https://github.com/facebook/docusaurus/issues/4029)
+- Other tasks that we might discover during 2021
+
+Huge thanks to the community for [their contributions in 2020](https://github.com/facebook/docusaurus/graphs/contributors?from=2020-01-01&to=2021-01-01&type=c), especially:
+
+- [Joel Marcey](https://github.com/JoelMarcey) for creating Docusaurus and supporting the project all this time
+- the core team - [Alexey Pyltsyn](https://github.com/lex111), [Sébastien Lorber](https://sebastienlorber.com), [Yangshun Tay](https://twitter.com/yangshunz)
+- the Major League Hacking and Facebook interns for their significant impact
+- the Algolia team for DocSearch 3 and their support
+- [Bartosz Kaszubowski](https://github.com/Simek) for his investment in the React Native migration
+- the whole community for their contributions, and providing support to each other
+
+Cheers to a great 2021! 🎉
diff --git a/website-1.x/core/Footer.js b/website-1.x/core/Footer.js
index df1529f901ee..15566b28eed6 100644
--- a/website-1.x/core/Footer.js
+++ b/website-1.x/core/Footer.js
@@ -123,6 +123,18 @@ class Footer extends React.Component {
rel="noreferrer noopener">
Terms
+
+ Data Policy
+
+
+ Cookie Policy
+
diff --git a/website-1.x/docs/getting-started-docker.md b/website-1.x/docs/getting-started-docker.md
index 3b0dd59d6bf0..61754da1f5c7 100644
--- a/website-1.x/docs/getting-started-docker.md
+++ b/website-1.x/docs/getting-started-docker.md
@@ -21,6 +21,8 @@ To run the local web server:
This will start a docker container with the image `docusaurus-doc`. To see more detailed container info run `docker ps` .
+To access Docusaurus from outside the docker container you must add the `--host` flag to the `docusaurus-start` command as described in: [API Commands](api-commands.md#docusaurus-start)
+
## Use docker-compose
We can also use `docker-compose` to configure our application. This feature of docker allows you to run the web server and any additional services with a single command.
diff --git a/website-1.x/docs/getting-started-installation.md b/website-1.x/docs/getting-started-installation.md
index 85ab673c64e0..9440a1b88b0e 100644
--- a/website-1.x/docs/getting-started-installation.md
+++ b/website-1.x/docs/getting-started-installation.md
@@ -6,7 +6,7 @@ description: Docusaurus was designed from the ground up to be easily installed a
Docusaurus was designed from the ground up to be easily installed and used to get your website up and running quickly.
-> **Important Note:** If you are setting up a new Docusaurus website for a Facebook Open Source project, we highly encourage you to use [Docusaurus 2](https://v2.docusaurus.io) instead.
+> **Important Note:** we highly encourage you to use [Docusaurus 2](https://v2.docusaurus.io) instead.
## Installing Docusaurus
diff --git a/website-1.x/languages.js b/website-1.x/languages.js
index 866a5224347a..3229aa38a61d 100644
--- a/website-1.x/languages.js
+++ b/website-1.x/languages.js
@@ -183,15 +183,20 @@ const languages = [
},
];
-const onlyEnglish = [
+const onlyEnglishAndFrench = [
{
enabled: true,
name: 'English',
tag: 'en',
},
+ {
+ enabled: true,
+ name: 'Français',
+ tag: 'fr',
+ },
];
// We want deploy previews to be fast
module.exports = require('./netlifyUtils').isDeployPreview
- ? onlyEnglish
+ ? onlyEnglishAndFrench
: languages;
diff --git a/website-1.x/package.json b/website-1.x/package.json
index 99c5196f7061..5bf8aca3794a 100644
--- a/website-1.x/package.json
+++ b/website-1.x/package.json
@@ -1,6 +1,6 @@
{
"name": "docusaurus-1-website",
- "version": "2.0.0-alpha.69",
+ "version": "2.0.0-alpha.70",
"private": true,
"scripts": {
"start": "docusaurus-start",
@@ -10,10 +10,11 @@
"write-translations": "docusaurus-write-translations",
"docusaurus-version": "docusaurus-version",
"rename-version": "docusaurus-rename-version",
- "crowdin-upload": "crowdin --config ../crowdin.yaml upload sources --auto-update -b master",
- "crowdin-download": "crowdin --config ../crowdin.yaml download -b master"
+ "crowdin-upload": "cd .. && crowdin upload sources --auto-update -b master --config crowdin-v1.yml",
+ "crowdin-download": "cd .. && crowdin download -b master --config crowdin-v1.yml",
+ "netlify:build": "yarn crowdin-download && yarn build"
},
"dependencies": {
- "docusaurus": "2.0.0-alpha.69"
+ "docusaurus": "2.0.0-alpha.70"
}
}
diff --git a/website-1.x/pages/en/versions.js b/website-1.x/pages/en/versions.js
index ca5bc8b8b6b3..cd79db68bd09 100644
--- a/website-1.x/pages/en/versions.js
+++ b/website-1.x/pages/en/versions.js
@@ -26,8 +26,24 @@ function Versions(props) {
;
+}
+```
+
+## Syntax highlighting
+
+Code blocks are text blocks wrapped around by strings of 3 backticks. You may check out [this reference](https://github.com/mdx-js/specification) for specifications of MDX.
+
+ ```jsx
+ console.log('Every repo must come with a mascot.');
+ ```
+
+
+
+Use the matching language meta string for your code block, and Docusaurus will pick up syntax highlighting automatically, powered by [Prism React Renderer](https://github.com/FormidableLabs/prism-react-renderer).
+
+```jsx
+console.log('Every repo must come with a mascot.');
+```
+
+By default, the Prism [syntax highlighting theme](https://github.com/FormidableLabs/prism-react-renderer#theming) we use is [Palenight](https://github.com/FormidableLabs/prism-react-renderer/blob/master/src/themes/palenight.js). You can change this to another theme by passing `theme` field in `prism` as `themeConfig` in your docusaurus.config.js.
+
+For example, if you prefer to use the `dracula` highlighting theme:
+
+```js {4} title="docusaurus.config.js"
+module.exports = {
+ themeConfig: {
+ prism: {
+ theme: require('prism-react-renderer/themes/dracula'),
+ },
+ },
+};
+```
+
+By default, Docusaurus comes with this subset of [commonly used languages](https://github.com/FormidableLabs/prism-react-renderer/blob/master/src/vendor/prism/includeLangs.js).
+
+To add syntax highlighting for any of the other [Prism supported languages](https://prismjs.com/#supported-languages), define it in an array of additional languages.
+
+For example, if you want to add highlighting for the `powershell` language:
+
+```js {5} title="docusaurus.config.js"
+module.exports = {
+ // ...
+ themeConfig: {
+ prism: {
+ additionalLanguages: ['powershell'],
+ },
+ // ...
+ },
+};
+```
+
+If you want to add highlighting for languages not yet supported by Prism, you can swizzle `prism-include-languages`:
+
+```bash npm2yarn
+npm run swizzle @docusaurus/theme-classic prism-include-languages
+```
+
+It will produce `prism-include-languages.js` in your `src/theme` folder. You can add highlighting support for custom languages by editing `prism-include-languages.js`:
+
+```js {8} title="src/theme/prism-include-languages.js"
+const prismIncludeLanguages = (Prism) => {
+ // ...
+
+ additionalLanguages.forEach((lang) => {
+ require(`prismjs/components/prism-${lang}`); // eslint-disable-line
+ });
+
+ require('/path/to/your/prism-language-definition');
+
+ // ...
+};
+```
+
+You can refer to [Prism's official language definitions](https://github.com/PrismJS/prism/tree/master/components) when you are writing your own language definitions.
+
+## Line highlighting
+
+You can bring emphasis to certain lines of code by specifying line ranges after the language meta string (leave a space after the language).
+
+ ```jsx {3}
+ function HighlightSomeText(highlight) {
+ if (highlight) {
+ return 'This text is highlighted!';
+ }
+
+ return 'Nothing highlighted';
+ }
+ ```
+
+```jsx {3}
+function HighlightSomeText(highlight) {
+ if (highlight) {
+ return 'This text is highlighted!';
+ }
+
+ return 'Nothing highlighted';
+}
+```
+
+To accomplish this, Docusaurus adds the `docusaurus-highlight-code-line` class to the highlighted lines. You will need to define your own styling for this CSS, possibly in your `src/css/custom.css` with a custom background color which is dependent on your selected syntax highlighting theme. The color given below works for the default highlighting theme (Palenight), so if you are using another theme, you will have to tweak the color accordingly.
+
+```css title="/src/css/custom.css"
+.docusaurus-highlight-code-line {
+ background-color: rgb(72, 77, 91);
+ display: block;
+ margin: 0 calc(-1 * var(--ifm-pre-padding));
+ padding: 0 var(--ifm-pre-padding);
+}
+
+/* If you have a different syntax highlighting theme for dark mode. */
+html[data-theme='dark'] .docusaurus-highlight-code-line {
+ background-color: ; /* Color which works with dark mode syntax highlighting theme */
+}
+```
+
+To highlight multiple lines, separate the line numbers by commas or use the range syntax to select a chunk of lines. This feature uses the `parse-number-range` library and you can find [more syntax](https://www.npmjs.com/package/parse-numeric-range) on their project details.
+
+ ```jsx {1,4-6,11}
+ import React from 'react';
+
+ function MyComponent(props) {
+ if (props.isBar) {
+ return
;
+}
+
+export default MyComponent;
+```
+
+You can also use comments with `highlight-next-line`, `highlight-start`, and `highlight-end` to select which lines are highlighted.
+
+ ```jsx
+ function HighlightSomeText(highlight) {
+ if (highlight) {
+ // highlight-next-line
+ return 'This text is highlighted!';
+ }
+
+ return 'Nothing highlighted';
+ }
+
+ function HighlightMoreText(highlight) {
+ // highlight-start
+ if (highlight) {
+ return 'This range is highlighted!';
+ }
+ // highlight-end
+
+ return 'Nothing highlighted';
+ }
+ ```
+
+```jsx
+function HighlightSomeText(highlight) {
+ if (highlight) {
+ // highlight-next-line
+ return 'This text is highlighted!';
+ }
+
+ return 'Nothing highlighted';
+}
+
+function HighlightMoreText(highlight) {
+ // highlight-start
+ if (highlight) {
+ return 'This range is highlighted!';
+ }
+ // highlight-end
+
+ return 'Nothing highlighted';
+}
+```
+
+Supported commenting syntax:
+
+| Language | Syntax |
+| ---------- | ------------------------ |
+| JavaScript | `/* ... */` and `// ...` |
+| JSX | `{/* ... */}` |
+| Python | `# ...` |
+| HTML | `` |
+
+If there's a syntax that is not currently supported, we are open to adding them! Pull requests welcome.
+
+## Interactive code editor
+
+(Powered by [React Live](https://github.com/FormidableLabs/react-live))
+
+You can create an interactive coding editor with the `@docusaurus/theme-live-codeblock` plugin.
+
+First, add the plugin to your package.
+
+```bash npm2yarn
+npm install --save @docusaurus/theme-live-codeblock
+```
+
+You will also need to add the plugin to your `docusaurus.config.js`.
+
+```js {3}
+module.exports = {
+ // ...
+ themes: ['@docusaurus/theme-live-codeblock'],
+ // ...
+};
+```
+
+To use the plugin, create a code block with `live` attached to the language meta string.
+
+ ```jsx live
+ function Clock(props) {
+ const [date, setDate] = useState(new Date());
+ useEffect(() => {
+ var timerID = setInterval(() => tick(), 1000);
+
+ return function cleanup() {
+ clearInterval(timerID);
+ };
+ });
+
+ function tick() {
+ setDate(new Date());
+ }
+
+ return (
+
+
It is {date.toLocaleTimeString()}.
+
+ );
+ }
+ ```
+
+The code block will be rendered as an interactive editor. Changes to the code will reflect on the result panel live.
+
+```jsx live
+function Clock(props) {
+ const [date, setDate] = useState(new Date());
+ useEffect(() => {
+ var timerID = setInterval(() => tick(), 1000);
+
+ return function cleanup() {
+ clearInterval(timerID);
+ };
+ });
+
+ function tick() {
+ setDate(new Date());
+ }
+
+ return (
+
+
It is {date.toLocaleTimeString()}.
+
+ );
+}
+```
+
+:::caution react-live and imports
+
+It is not possible to import components directly from the react-live code editor, you have to define available imports upfront.
+
+:::
+
+By default, all React imports are available. If you need more imports available, swizzle the react-live scope:
+
+```bash npm2yarn
+npm run swizzle @docusaurus/theme-live-codeblock ReactLiveScope
+```
+
+```jsx {3-15,21} title="src/theme/ReactLiveScope/index.js"
+import React from 'react';
+
+const ButtonExample = (props) => (
+
+);
+
+// Add react-live imports you need here
+const ReactLiveScope = {
+ React,
+ ...React,
+ ButtonExample,
+};
+
+export default ReactLiveScope;
+```
+
+The `ButtonExample` component is now available to use:
+
+```jsx live
+function MyPlayground(props) {
+ return (
+
+ alert('hey!')}>Click me
+
+ );
+}
+```
+
+## Multi-language support code blocks
+
+With MDX, you can easily create interactive components within your documentation, for example, to display code in multiple programming languages and switching between them using a tabs component.
+
+Instead of implementing a dedicated component for multi-language support code blocks, we've implemented a generic Tabs component in the classic theme so that you can use it for other non-code scenarios as well.
+
+The following example is how you can have multi-language code tabs in your docs. Note that the empty lines above and below each language block is **intentional**. This is a current limitation of MDX, you have to leave empty lines around Markdown syntax for the MDX parser to know that it's Markdown syntax and not JSX.
+
+````jsx
+import Tabs from '@theme/Tabs';
+import TabItem from '@theme/TabItem';
+
+
+
+
+```js
+function helloWorld() {
+ console.log('Hello, world!');
+}
+```
+
+
+
+
+```py
+def hello_world():
+ print 'Hello, world!'
+```
+
+
+
+
+```java
+class HelloWorld {
+ public static void main(String args[]) {
+ System.out.println("Hello, World");
+ }
+}
+```
+
+
+
+````
+
+And you will get the following:
+
+
+
+
+```js
+function helloWorld() {
+ console.log('Hello, world!');
+}
+```
+
+
+
+
+```py
+def hello_world():
+ print 'Hello, world!'
+```
+
+
+
+
+```java
+class HelloWorld {
+ public static void main(String args[]) {
+ System.out.println("Hello, World");
+ }
+}
+```
+
+
+
+
+You may want to implement your own `` abstraction if you find the above approach too verbose. We might just implement one in future for convenience.
+
+If you have multiple of these multi-language code tabs, and you want to sync the selection across the tab instances, refer to the [Syncing tab choices section](#syncing-tab-choices).
diff --git a/website/docs/guides/markdown-features/markdown-features-inline-toc.mdx b/website/docs/guides/markdown-features/markdown-features-inline-toc.mdx
new file mode 100644
index 000000000000..37303d948335
--- /dev/null
+++ b/website/docs/guides/markdown-features/markdown-features-inline-toc.mdx
@@ -0,0 +1,117 @@
+---
+id: inline-toc
+title: Inline TOC
+description: Using inline table-of-contents inside Docusaurus Markdown
+slug: /markdown-features/inline-toc
+---
+
+import BrowserWindow from '@site/src/components/BrowserWindow';
+
+Each markdown document displays a tab of content on the top-right corner.
+
+But it is also possible to display an inline table of contents directly inside a markdown document, thanks to MDX.
+
+## Full table of contents
+
+The `toc` variable is available in any MDX document, and contain all the top level headings of a MDX document.
+
+```jsx
+import TOCInline from '@theme/TOCInline';
+
+;
+```
+
+import TOCInline from '@theme/TOCInline';
+
+
+
+
+
+
+
+## Custom table of contents
+
+The `toc` props is just a list of table of contents items:
+
+```ts
+type TOCItem = {
+ value: string;
+ id: string;
+ children: TOCItem[];
+};
+```
+
+You can create this TOC tree manually, or derive a new TOC tree from the `toc` variable:
+
+```jsx
+import TOCInline from '@theme/TOCInline';
+
+;
+```
+
+
+
+
+
+
+
+---
+
+:::caution
+
+The underlying content is just an example to have more table-of-contents items available in current page.
+
+:::
+
+## Example Section 1
+
+Lorem ipsum
+
+### Example Subsection 1 a
+
+Lorem ipsum
+
+### Example Subsection 1 b
+
+Lorem ipsum
+
+### Example Subsection 1 c
+
+Lorem ipsum
+
+## Example Section 2
+
+Lorem ipsum
+
+### Example Subsection 2 a
+
+Lorem ipsum
+
+### Example Subsection 2 b
+
+Lorem ipsum
+
+### Example Subsection 2 c
+
+Lorem ipsum
+
+## Example Section 3
+
+Lorem ipsum
+
+### Example Subsection 3 a
+
+Lorem ipsum
+
+### Example Subsection 3 b
+
+Lorem ipsum
+
+### Example Subsection 3 c
+
+Lorem ipsum
diff --git a/website/docs/guides/markdown-features/markdown-features-intro.mdx b/website/docs/guides/markdown-features/markdown-features-intro.mdx
new file mode 100644
index 000000000000..28f215471c33
--- /dev/null
+++ b/website/docs/guides/markdown-features/markdown-features-intro.mdx
@@ -0,0 +1,23 @@
+---
+id: introduction
+title: Markdown Features introduction
+sidebar_label: Introduction
+description: Docusaurus uses GitHub Flavored Markdown (GFM). Find out more about Docusaurus-specific features when writing Markdown.
+slug: /markdown-features
+---
+
+Documentation is one of your product's interfaces with your users. A well-written and well-organized set of docs helps your users understand your product quickly. Our aligned goal here is to help your users find and understand the information they need, as quickly as possible.
+
+Docusaurus 2 uses modern tooling to help you compose your interactive documentations with ease. You may embed React components, or build live coding blocks where your users may play with the code on the spot. Start sharing your eureka moments with the code your audience cannot walk away from. It is perhaps the most effective way of attracting potential users.
+
+In this section, we'd like to introduce you to the tools we've picked that we believe will help you build a powerful documentation. Let us walk you through with an example.
+
+Markdown is a syntax that enables you to write formatted content in a readable syntax.
+
+The [standard Markdown syntax](https://daringfireball.net/projects/markdown/syntax) is supported, and we use [MDX](https://mdxjs.com/) as the parsing engine, which can do much more than just parsing Markdown, like rendering React components inside your documents.
+
+:::important
+
+This section assumes you are using the official Docusaurus content plugins.
+
+:::
diff --git a/website/docs/guides/markdown-features/markdown-features-plugins.mdx b/website/docs/guides/markdown-features/markdown-features-plugins.mdx
new file mode 100644
index 000000000000..514739fa8ad9
--- /dev/null
+++ b/website/docs/guides/markdown-features/markdown-features-plugins.mdx
@@ -0,0 +1,78 @@
+---
+id: plugins
+title: Plugins
+description: Using MDX plugins to expand Docusaurus Markdown functionalities
+slug: /markdown-features/plugins
+---
+
+You can expand the MDX functionalities, using plugins.
+
+Docusaurus content plugins support both [Remark](https://github.com/remarkjs/remark) and [Rehype](https://github.com/rehypejs/rehype) plugins that work with MDX.
+
+## Configuring plugins
+
+An MDX plugin is usually a npm package, so you install them like other npm packages using npm.
+
+First, install your [Remark](https://github.com/remarkjs/remark/blob/main/doc/plugins.md#list-of-plugins) and [Rehype](https://github.com/rehypejs/rehype/blob/main/doc/plugins.md#list-of-plugins) plugins.
+
+For example:
+
+```bash npm2yarn
+npm install --save remark-images
+npm install --save rehype-truncate
+```
+
+Next, import the plugins:
+
+```js
+const remarkImages = require('remark-images');
+const rehypeTruncate = require('rehype-truncate');
+```
+
+Finally, add them to the `@docusaurus/preset-classic` options in `docusaurus.config.js`:
+
+```js {10,11} title="docusaurus.config.js"
+module.exports = {
+ // ...
+ presets: [
+ [
+ '@docusaurus/preset-classic',
+ {
+ docs: {
+ sidebarPath: require.resolve('./sidebars.js'),
+ // ...
+ remarkPlugins: [remarkImages],
+ rehypePlugins: [rehypeTruncate],
+ },
+ },
+ ],
+ ],
+};
+```
+
+## Configuring plugin options
+
+Some plugins can be configured and accept their own options. In that case, use the `[plugin, pluginOptions]` syntax, like so:
+
+```jsx {10-13} title="docusaurus.config.js"
+module.exports = {
+ // ...
+ presets: [
+ [
+ '@docusaurus/preset-classic',
+ {
+ docs: {
+ sidebarPath: require.resolve('./sidebars.js'),
+ // ...
+ remarkPlugins: [
+ plugin1,
+ [plugin2, {option1: {...}}],
+ ],
+ },
+ },
+ ],
+ ],
+};
+```
+
+See more information in the [MDX documentation](https://mdxjs.com/advanced/plugins).
diff --git a/website/docs/guides/markdown-features/markdown-features-react.mdx b/website/docs/guides/markdown-features/markdown-features-react.mdx
new file mode 100644
index 000000000000..8fc9049e49ac
--- /dev/null
+++ b/website/docs/guides/markdown-features/markdown-features-react.mdx
@@ -0,0 +1,69 @@
+---
+id: react
+title: Using React
+description: Using the power of React in Docusaurus Markdown documents, thanks to MDX
+slug: /markdown-features/react
+---
+
+import BrowserWindow from '@site/src/components/BrowserWindow';
+
+Docusaurus has built-in support for [MDX](https://mdxjs.com/), which allows you to write JSX within your Markdown files and render them as React components.
+
+:::note
+
+While both `.md` and `.mdx` files are parsed using MDX, some of the syntax are treated slightly differently. For the most accurate parsing and better editor support, we recommend using the `.mdx` extension for files containing MDX syntax.
+
+:::
+
+Try this block here:
+
+```jsx
+export const Highlight = ({children, color}) => (
+
+ {children}
+
+);
+
+Docusaurus green and Facebook blue are my favorite colors.
+
+I can write **Markdown** alongside my _JSX_!
+```
+
+Notice how it renders both the markup from your React component and the Markdown syntax:
+
+export const Highlight = ({children, color}) => (
+
+ {children}
+
+);
+
+
+
+Docusaurus green
+{` `}and Facebook blue are my favorite colors.
+
+I can write **Markdown** alongside my _JSX_!
+
+
+
+
+
+You can also import your own components defined in other files or third-party components installed via npm! Check out the [MDX docs](https://mdxjs.com/) to see what other fancy stuff you can do with MDX.
+
+:::caution
+
+Since all doc files are parsed using MDX, any HTML is treated as JSX. Therefore, if you need to inline-style a component, follow JSX flavor and provide style objects. This behavior is different from Docusaurus 1. See also [Migrating from v1 to v2](../../migration/migration-manual.md#convert-style-attributes-to-style-objects-in-mdx).
+
+:::
diff --git a/website/docs/guides/markdown-features/markdown-features-tabs.mdx b/website/docs/guides/markdown-features/markdown-features-tabs.mdx
new file mode 100644
index 000000000000..65f7930763a8
--- /dev/null
+++ b/website/docs/guides/markdown-features/markdown-features-tabs.mdx
@@ -0,0 +1,218 @@
+---
+id: tabs
+title: Tabs
+description: Using tabs inside Docusaurus Markdown
+slug: /markdown-features/tabs
+---
+
+import Tabs from '@theme/Tabs';
+
+import TabItem from '@theme/TabItem';
+
+To show tabbed content within Markdown files, you can fall back on MDX. Docusaurus provides `` components out-of-the-box.
+
+```jsx
+import Tabs from '@theme/Tabs';
+import TabItem from '@theme/TabItem';
+
+
+ This is an apple 🍎
+ This is an orange 🍊
+ This is a banana 🍌
+;
+```
+
+And you will get the following:
+
+
+ This is an apple 🍎
+ This is an orange 🍊
+ This is a banana 🍌
+
+
+:::info
+
+By default, tabs are rendered eagerly, but it is possible to load them lazily by passing the `lazy` prop to the `Tabs` component.
+
+:::
+
+## Syncing tab choices
+
+You may want choices of the same kind of tabs to sync with each other. For example, you might want to provide different instructions for users on Windows vs users on macOS, and you want to changing all OS-specific instructions tabs in one click. To achieve that, you can give all related tabs the same `groupId` prop. Note that doing this will persist the choice in `localStorage` and all `` instances with the same `groupId` will update automatically when the value of one of them is changed. Note that `groupID` are globally-namespaced.
+
+```jsx {2,14}
+
+Use Ctrl + C to copy.
+Use Command + C to copy.
+
+
+
+Use Ctrl + V to paste.
+Use Command + V to paste.
+
+```
+
+
+ Use Ctrl + C to copy.
+ Use Command + C to copy.
+
+
+
+ Use Ctrl + V to paste.
+ Use Command + V to paste.
+
+
+For all tab groups that have the same `groupId`, the possible values do not need to be the same. If one tab group with chooses an value that does not exist in another tab group with the same `groupId`, the tab group with the missing value won't change its tab. You can see that from the following example. Try to select Linux, and the above tab groups doesn't change.
+
+```jsx
+
+ I am Windows.
+ I am macOS.
+ I am Linux.
+
+```
+
+
+ I am Windows.
+ I am macOS.
+ I am Linux.
+
+
+---
+
+Tab choices with different `groupId`s will not interfere with each other:
+
+```jsx {2,14}
+
+Windows in windows.
+macOS is macOS.
+
+
+
+Windows is windows.
+Unix is unix.
+
+```
+
+
+ Windows in windows.
+ macOS is macOS.
+
+
+
+ Windows is windows.
+ Unix is unix.
+
+
+## Customizing tabs
+
+You might want to customize the appearance of certain set of tabs. To do that you can pass the string in `className` prop and the specified CSS class will be added to the `Tabs` component:
+
+```jsx {5}
+import Tabs from '@theme/Tabs';
+import TabItem from '@theme/TabItem';
+
+
+ This is an apple 🍎
+ This is an orange 🍊
+ This is a banana 🍌
+;
+```
+
+
+ This is an apple 🍎
+ This is an orange 🍊
+ This is a banana 🍌
+
diff --git a/website/docs/i18n/i18n-crowdin.mdx b/website/docs/i18n/i18n-crowdin.mdx
new file mode 100644
index 000000000000..497a5bf77210
--- /dev/null
+++ b/website/docs/i18n/i18n-crowdin.mdx
@@ -0,0 +1,473 @@
+---
+id: crowdin
+title: i18n - Using Crowdin
+sidebar_label: Using Crowdin
+slug: /i18n/crowdin
+---
+
+The i18n system of Docusaurus is **decoupled from any translation software**.
+
+You can integrate Docusaurus with the **tools and SaaS of your choice**, as long as you put the **translation files at the correct location**.
+
+We document the usage of [Crowdin](http://crowdin.com/), as **one** possible **integration example**.
+
+:::caution
+
+This is **not an endorsement of Crowdin** as the unique choice to translate a Docusaurus site, but it is used successfully used by Facebook to translate documentation projects such as [Jest](https://jestjs.io/), [Docusaurus](https://docusaurus.io/) and [ReasonML](https://reasonml.github.io/).
+
+Refer to the **[Crowdin documentation](https://support.crowdin.com/)** and **[Crowdin support](mailto:support@crowdin.com)** for help.
+
+:::
+
+:::tip
+
+Use this **[community-driven GitHub issue](https://github.com/facebook/docusaurus/discussions/4052)** to discuss anything related to Docusaurus + Crowdin.
+
+:::
+
+## Crowdin overview
+
+Crowdin is a translation SaaS, offering a [free plan for open-source projects](https://crowdin.com/page/open-source-project-setup-request).
+
+We recommend the following translation workflow:
+
+- **Upload sources** to Crowdin (untranslated files)
+- Use Crowdin to **translate the content**
+- **Download translations** from Crowdin (localized translation files)
+
+Crowdin provides a [CLI](https://support.crowdin.com/cli-tool/) to **upload sources** and **download translations**, allowing you to automate the translation process.
+
+The [`crowdin.yml` configuration file](https://support.crowdin.com/configuration-file/) is convenient for Docusaurus, and permits to **download the localized translation files at the expected location** (in `i18n//..`).
+
+Read the **[official documentation](https://support.crowdin.com/)** to know more about advanced features and different translation workflows.
+
+## Crowdin tutorial
+
+This is a walk-through of using Crowdin to translate a newly initialized English Docusaurus website into French, and assume you already followed the [i18n tutorial](./i18n-tutorial.md).
+
+The end result can be seen at [docusaurus-crowdin-example.netlify.app](https://docusaurus-crowdin-example.netlify.app/) ([repository](https://github.com/slorber/docusaurus-crowdin-example)).
+
+### Prepare the Docusaurus site
+
+Initialize a new Docusaurus site:
+
+```bash
+npx @docusaurus/init@latest init website classic
+```
+
+Add the site configuration for the French language:
+
+```js title="docusaurus.config.js"
+module.exports = {
+ i18n: {
+ defaultLocale: 'en',
+ locales: ['en', 'fr'],
+ },
+ themeConfig: {
+ navbar: {
+ items: [
+ // ...
+ {
+ type: 'localeDropdown',
+ position: 'left',
+ },
+ // ...
+ ],
+ },
+ },
+ // ...
+};
+```
+
+Translate the homepage:
+
+```jsx title="src/index.js"
+import React from 'react';
+import Translate from '@docusaurus/Translate';
+import Layout from '@theme/Layout';
+
+export default function Home() {
+ return (
+
+
+
+ Welcome to my Docusaurus translated site!
+
+
+
+ );
+}
+```
+
+### Create a Crowdin project
+
+Sign up on [Crowdin](https://crowdin.com/), and create a project.
+
+Use English as source language, and French as target language.
+
+![Create a Crowdin project with english as source language, and french as target language](/img/crowdin/crowdin-create-project.png)
+
+Your project is created, but it is empty for now. We will upload the files to translate in the next steps.
+
+### Create the Crowdin configuration
+
+This configuration ([doc](https://support.crowdin.com/configuration-file/)) provides a mapping for the Crowdin CLI to understand:
+
+- Where to find the source files to upload (JSON and Markdown)
+- Where to download the files after translation (in `i18n/`).
+
+Create `crowdin.yml` in `website`:
+
+```yml title="crowdin.yml"
+project_id: '123456'
+api_token_env: 'CROWDIN_PERSONAL_TOKEN'
+preserve_hierarchy: true
+files: [
+ # JSON translation files
+ {
+ source: '/i18n/en/**/*',
+ translation: '/i18n/%two_letters_code%/**/%original_file_name%',
+ },
+ # Docs Markdown files
+ {
+ source: '/docs/**/*',
+ translation: '/i18n/%two_letters_code%/docusaurus-plugin-content-docs/current/**/%original_file_name%',
+ },
+ # Blog Markdown files
+ {
+ source: '/blog/**/*',
+ translation: '/i18n/%two_letters_code%/docusaurus-plugin-content-blog/**/%original_file_name%',
+ },
+ ]
+```
+
+Crowdin has its own syntax for declaring source/translation paths:
+
+- `**/*`: everything in a subfolder
+- `%two_letters_code%`: the 2-letters variant of Crowdin target languages (`fr` in our case)
+- `**/%original_file_name%`: the translations will preserve the original folder/file hierarchy
+
+:::info
+
+The Crowdin CLI warnings are not always easy to understand.
+
+We advise to:
+
+- change one thing at a time
+- re-upload sources after any configuration change
+- use paths starting with `/` (`./` does not work)
+- avoid fancy globbing patterns like `/docs/**/*.(md|mdx)` (does not work)
+
+:::
+
+#### Access token
+
+The `api_token_env` attribute defines the **env variable name** read by the Crowdin CLI.
+
+You can obtain a `Personal Access Token` on [your personal profile page](https://crowdin.com/settings#api-key).
+
+:::tip
+
+You can keep the default value `CROWDIN_PERSONAL_TOKEN`, and set this environment variable and on your computer and on the CI server to the generated access token.
+
+:::
+
+:::caution
+
+A Personal Access Tokens grant **read-write access to all your Crowdin projects**.
+
+You should **not commit** it, and it may be a good idea to create a dedicated **Crowdin profile for your company** instead of using a personal account.
+
+:::
+
+#### Other configuration fields
+
+- `project_id`: can be hardcoded, and is found on `https://crowdin.com/project//settings#api`.
+- `preserve_hierarchy`: preserve the folder's hierarchy of your docs on Crowdin UI instead of flattening everything.
+
+### Install the Crowdin CLI
+
+This tutorial use the CLI in version `3.5.2`, but we expect `3.x` releases to keep working.
+
+Install the Crowdin CLI as a NPM package to your Docusaurus site:
+
+```bash npm2yarn
+npm install @crowdin/cli@3
+```
+
+Add a `crowdin` script:
+
+```json title="package.json"
+{
+ "scripts": {
+ "crowdin": "crowdin"
+ }
+}
+```
+
+Test that you can run the Crowdin CLI:
+
+```bash npm2yarn
+npm run crowdin -- --version
+```
+
+Set the `CROWDIN_PERSONAL_TOKEN` env variable on your computer, to allow the CLI to authenticate with the Crowdin API.
+
+:::tip
+
+Temporarily, you can hardcode your personal token in `crowdin.yml` with `api_token: 'MY-TOKEN'`.
+
+:::
+
+### Upload the sources
+
+Generate the JSON translation files for the default language in `website/i18n/en`:
+
+```bash npm2yarn
+npm run write-translations
+```
+
+Upload all the JSON and Markdown translation files:
+
+```bash npm2yarn
+npm run crowdin upload
+```
+
+![Crowdin CLI uploading Docusaurus source files](/img/crowdin/crowdin-upload-sources-cli.png)
+
+Your source files are now visible on the Crowdin interface: `https://crowdin.com/project//settings#files`
+
+![Crowdin UI showing Docusaurus source files](/img/crowdin/crowdin-source-files.png)
+
+### Translate the sources
+
+On `https://crowdin.com/project/`, click on the French target language.
+
+![Crowdin UI showing French translation files](/img/crowdin/crowdin-french-translations.png)
+
+Translate some Markdown files.
+
+![Crowdin UI to translate a Markdown file](/img/crowdin/crowdin-translate-markdown.png)
+
+:::tip
+
+Use `Hide String` to make sure translators **don't translate things that should not be**:
+
+- Frontmatter: `id`, `slug`, `tags` ...
+- Admonitions: `:::`, `:::note`, `:::tip` ...
+
+![Crowdin UI hide string](/img/crowdin/crowdin-hide-string.png)
+
+:::
+
+Translate some JSON files.
+
+![Crowdin UI to translate a JSON file](/img/crowdin/crowdin-translate-json.png)
+
+:::info
+
+The `description` attribute of JSON translation files is visible on Crowdin to help translate the strings.
+
+:::
+
+:::tip
+
+**[Pre-translate](https://support.crowdin.com/pre-translation-via-machine/)** your site, and **fix pre-translation mistakes manually** (enable the Global Translation Memory in settings first).
+
+Use the `Hide String` feature first, as Crowdin is pre-translating things too optimistically.
+
+:::
+
+### Download the translations
+
+Use the Crowdin CLI to download the translated JSON and Markdown files.
+
+```bash npm2yarn
+npm run crowdin download
+```
+
+The translated content should be downloaded in `i18n/fr`.
+
+Start your site on the French locale:
+
+```bash npm2yarn
+npm run start -- --locale fr
+```
+
+Make sure that your website is now translated in French at `http://localhost:3000/fr/`
+
+### Automate with CI
+
+We will configure the CI to **download the Crowdin translations at build time**, and keep them outside of Git.
+
+Add `website/i18n` to `.gitignore`.
+
+Set the `CROWDIN_PERSONAL_TOKEN` env variable on your CI.
+
+Create a NPM script to `sync` Crowdin (extract sources, upload sources, download translations):
+
+```json title="package.json"
+{
+ "scripts": {
+ "crowdin:sync": "docusaurus write-translations && crowdin upload && crowdin download"
+ }
+}
+```
+
+Call the `npm run crowdin:sync` script in your CI, just before building the Docusaurus site.
+
+:::tip
+
+Keep your deploy-previews fast: don't download translations, and use `npm run build -- --locale en` for feature branches.
+
+:::
+
+:::caution
+
+Crowdin does not support well multiple concurrent uploads/downloads: it is preferable to only include translations to your production deployment, and keep deploy previews untranslated.
+
+:::
+
+## Advanced Crowdin topics
+
+### MDX
+
+:::warning
+
+Crowdin does not support the `.mdx` extension, and interpret these files as plain text instead of Markdown, producing a bad translation experience.
+
+:::
+
+We temporarily recommend using the `.md` extension (even if the document contains React code), and are in touch with Crowdin to get this solved.
+
+### Docs versioning
+
+Configure translation files for the `website/versioned_docs` folder.
+
+When creating a new version, the source strings will generally be quite similar to the current version (`website/docs`), and you don't want to translate the new version docs again and again.
+
+Crowdin provides a `Duplicate Strings` setting.
+
+![Crowdin Duplicate Strings option setting](/img/crowdin/crowdin-settings-duplicate-strings.png)
+
+We recommend using `Hide`, but the ideal setting depends on how much your versions are different.
+
+:::caution
+
+Not using `Hide` leads to a much larger amount of `source strings` in quotas, and will affect the pricing.
+
+:::
+
+### Multi-instance plugins
+
+You need to configure translation files for each plugin instance.
+
+If you have a docs plugin instance with `id=ios`, you will need to configure those source files as well
+
+- `website/ios`
+- `website/ios_versioned_docs` (if versioned)
+
+### Maintaining your site
+
+Sometimes, you will **remove or rename a source file** on Git, and Crowdin will display CLI warnings:
+
+![Crowdin CLI: download translation warning](/img/crowdin/crowdin-download-translations-warning.png)
+
+When your sources are refactored, you should use the Crowdin UI to **update your Crowdin files manually**:
+
+![Crowdin UI: renaming a file](/img/crowdin/crowdin-files-rename.png)
+
+### Git / VCS integrations
+
+Crowdin has multiple VCS integrations for [GitHub](https://support.crowdin.com/github-integration/), GitLab, BitBucket...
+
+:::warning
+
+We recommend avoiding them.
+
+:::
+
+It could have been helpful to be able to edit the translations in both Git and Crowdin, and have a **bi-directional sync** between the 2 systems.
+
+In practice, **it didn't work very reliably** for a few reasons:
+
+- The Crowdin -> Git sync works fine (with a pull-request)
+- The Git -> Crowdin sync is manual (you have to press a button)
+- The heuristics used by Crowdin to match existing Markdown translations to existing Markdown sources are not 100% reliable, and you have to verify the result on Crowdin UI after any sync from Git
+- 2 users concurrently editing on Git and Crowdin can lead to a translation loss
+- It requires the `crowdin.yml` file to be at the root of the repository
+
+### In-Context localization
+
+Crowdin has an [In-Context localization](https://support.crowdin.com/in-context-localization/) feature.
+
+:::caution
+
+Unfortunately, it does not work yet for technical reasons, but we have good hope it can be solved.
+
+Crowdin replaces markdown strings with technical ids such as `crowdin:id12345`, but it does so too aggressively, including hidden strings, and mess-up with the frontmatter, admonitions, jsx...
+
+:::
+
+### Localize edit urls
+
+When the user is browsing a page at `/fr/doc1`, the edit button will link by default to the unlocalized doc at `website/docs/doc1.md`.
+
+You may prefer the edit button to link to the Crowdin interface instead, and can use the `editUrl` function to customize the edit urls on a per-locale basis.
+
+```js title="docusaurus.config.js"
+const DefaultLocale = 'en';
+
+module.exports = {
+ presets: [
+ [
+ '@docusaurus/preset-classic',
+ {
+ docs: {
+ // highlight-start
+ editUrl: ({locale, versionDocsDirPath, docPath}) => {
+ // Link to Crowdin for French docs
+ if (locale !== DefaultLocale) {
+ return `https://crowdin.com/project/docusaurus-v2/${locale}`;
+ }
+ // Link to Github for English docs
+ return `https://github.com/facebook/docusaurus/edit/master/website/${versionDocsDirPath}/${docPath}`;
+ },
+ // highlight-end
+ },
+ blog: {
+ // highlight-start
+ editUrl: ({locale, blogDirPath, blogPath}) => {
+ if (locale !== DefaultLocale) {
+ return `https://crowdin.com/project/docusaurus-v2/${locale}`;
+ }
+ return `https://github.com/facebook/docusaurus/edit/master/website/${blogDirPath}/${blogPath}`;
+ },
+ // highlight-start
+ },
+ },
+ ],
+ ],
+};
+```
+
+:::note
+
+It is currently **not possible to link to a specific file** in Crowdin.
+
+:::
+
+### Example configuration
+
+The **Docusaurus v2 configuration file** is a good example of using versioning and multi-instance:
+
+import CrowdinConfigV2 from '!!raw-loader!@site/../crowdin-v2.yaml';
+import CodeBlock from '@theme/CodeBlock';
+
+
+ {CrowdinConfigV2.split('\n')
+ // remove comments
+ .map((line) => !line.startsWith('#') && line)
+ .filter(Boolean)
+ .join('\n')}
+
diff --git a/website/docs/i18n/i18n-git.md b/website/docs/i18n/i18n-git.md
new file mode 100644
index 000000000000..e28809c921ef
--- /dev/null
+++ b/website/docs/i18n/i18n-git.md
@@ -0,0 +1,181 @@
+---
+id: git
+title: i18n - Using git
+sidebar_label: Using Git
+slug: /i18n/git
+---
+
+A **possible translation strategy** is to **version control the translation files** to Git (or any other [VCS](https://en.wikipedia.org/wiki/Version_control)).
+
+## Tradeoffs
+
+This strategy has advantages:
+
+- **Easy to get started**: just add the `i18n` folder to Git
+- **Easy for developers**: Git, GitHub and pull-requests are mainstream developer tools
+- **Free** (or without any additional cost, assuming you already use Git)
+- **Low friction**: does not require signing-up to an external tool
+- **Rewarding**: contributors are happy to have a nice contribution history
+
+Using Git also present some shortcomings:
+
+- **Hard for non-developers**: they do not master Git and pull-requests
+- **Hard for professional translations**: they are used to SaaS translation softwares and advanced features
+- **Hard to maintain**: you have to keep the translated files **in sync** with the untranslated files
+
+:::note
+
+Some **large-scale technical projects** (ReactJS, VueJS, Gatsby, TypeScript, Nuxt...) use Git for translations.
+
+Refer to the [Docusaurus i18n RFC](https://github.com/facebook/docusaurus/issues/3317) for our notes and links studying these systems.
+
+:::
+
+## Git tutorial
+
+This is a walk-through of using Git to translate a newly initialized English Docusaurus website into French, and assume you already followed the [i18n tutorial](./i18n-tutorial.md).
+
+### Prepare the Docusaurus site
+
+Initialize a new Docusaurus site:
+
+```bash
+npx @docusaurus/init@latest init website classic
+```
+
+Add the site configuration for the French language:
+
+```js title="docusaurus.config.js"
+module.exports = {
+ i18n: {
+ defaultLocale: 'en',
+ locales: ['en', 'fr'],
+ },
+ themeConfig: {
+ navbar: {
+ items: [
+ // ...
+ {
+ type: 'localeDropdown',
+ position: 'left',
+ },
+ // ...
+ ],
+ },
+ },
+ // ...
+};
+```
+
+Translate the homepage:
+
+```jsx title="src/index.js"
+import React from 'react';
+import Translate from '@docusaurus/Translate';
+import Layout from '@theme/Layout';
+
+export default function Home() {
+ return (
+
+
+
+ Welcome to my Docusaurus translated site!
+
+
+
+ );
+}
+```
+
+### Initialize the `i18n` folder
+
+Use the [write-translations](../cli.md#docusaurus-write-translations) CLI command to initialize the JSON translation files for the French locale:
+
+```bash npm2yarn
+npm run write-translations -- --locale fr
+
+ 1 translations written at i18n/fr/code.json
+ 11 translations written at i18n/fr/docusaurus-theme-classic/footer.json
+ 4 translations written at i18n/fr/docusaurus-theme-classic/navbar.json
+ 3 translations written at i18n/fr/docusaurus-plugin-content-docs/current.json
+```
+
+:::tip
+
+Use the `--messagePrefix '(fr) '` option to make the untranslated strings stand out.
+
+`Hello` will appear as `(fr) Hello` and makes it clear a translation is missing.
+
+:::
+
+Copy your untranslated Markdown files to the French folder:
+
+```
+mkdir -p i18n/fr/docusaurus-plugin-content-docs/current
+cp -r docs/** i18n/fr/docusaurus-plugin-content-docs/current
+
+mkdir -p i18n/fr/docusaurus-plugin-content-blog
+cp -r blog/** i18n/fr/docusaurus-plugin-content-blog
+
+mkdir -p i18n/fr/docusaurus-plugin-content-pages
+cp -r pages/**.md i18n/fr/docusaurus-plugin-content-pages
+cp -r pages/**.mdx i18n/fr/docusaurus-plugin-content-pages
+```
+
+Add all these files to Git.
+
+### Translate the files
+
+Translate the Markdown and JSON files in `i18n/fr` and commit the translation.
+
+You should now be able to start your site in French and see the translations:
+
+```bash npm2yarn
+npm run start -- --locale fr
+```
+
+You can also build the site locally or on your CI:
+
+```bash npm2yarn
+npm run build
+# or
+npm run build -- --locale fr
+```
+
+### Repeat
+
+Follow the same process for each locale you need to support.
+
+## Maintain the translations
+
+Keeping translated files **consistent** with the originals **can be challenging**, in particular for Markdown documents.
+
+### Markdown translations
+
+When an untranslated Markdown document is edited, it is **your responsibility to maintain the respective translated files**, and we unfortunately don't have a good way to help you do so.
+
+To keep your translated sites consistent, when the `website/docs/doc1.md` doc is edited, you need **backport these edits** to `i18n/fr/docusaurus-plugin-content-docs/current/doc1.md`.
+
+### JSON translations
+
+To help you maintain the JSON translation files, it is possible to run again the [write-translations](../cli.md#docusaurus-write-translations) CLI command:
+
+```bash npm2yarn
+npm run write-translations -- --locale fr
+```
+
+New translation will be appended, and existing ones will not be overridden.
+
+:::tip
+
+Reset your translations with the `--override` option.
+
+:::
+
+### Localize edit urls
+
+When the user is browsing a page at `/fr/doc1`, the edit button will link by default to the unlocalized doc at `website/docs/doc1.md`.
+
+Your translations are on Git, and you can use the `editLocalizedFiles: true` option of the docs and blog plugins.
+
+The edit button will link to the localized doc at `i18n/fr/docusaurus-plugin-content-docs/current/doc1.md`.
diff --git a/website/docs/i18n/i18n-introduction.md b/website/docs/i18n/i18n-introduction.md
new file mode 100644
index 000000000000..3c67091be19a
--- /dev/null
+++ b/website/docs/i18n/i18n-introduction.md
@@ -0,0 +1,154 @@
+---
+id: introduction
+title: i18n - Introduction
+sidebar_label: Introduction
+slug: /i18n/introduction
+---
+
+It is possible to translate a Docusaurus website through its internationalization support (abbreviated as [i18n](https://en.wikipedia.org/wiki/Internationalization_and_localization)).
+
+:::caution
+
+i18n is a new feature (released early 2021), please report any bug you find.
+
+:::
+
+## Goals
+
+This section should help you understand the design decisions behind the Docusaurus i18n support.
+
+For more context, you can read the initial [RFC](https://github.com/facebook/docusaurus/issues/3317) and [PR](https://github.com/facebook/docusaurus/pull/3325).
+
+### i18n goals
+
+The goals of the Docusaurus i18n system are:
+
+- **Simple**: just put the translated files in the correct file-system location.
+- **Flexible translation workflows**: based on Git (monorepo, forks or submodules), SaaS software, FTP...
+- **Flexible deployment options**: single or multiple domains.
+- **Modular**: allow plugin author to provide i18n support.
+- **Low-overhead runtime**: static json/markdown content does not require a heavy i18n JS library.
+- **Acceptable build-times**: allow building and deploying localized sites independently.
+- **Localize assets**: an image of your site might contain text that should be translated.
+- **No coupling**: not forced to use any SaaS, yet the integration is possible.
+- **Easy to use with [Crowdin](http://crowdin.com/)**: multiple Docusaurus v1 sites use Crowdin, and should be able to migrate to v2.
+- **Good SEO defaults**: setting useful SEO headers like [`hreflang`](https://developers.google.com/search/docs/advanced/crawling/localized-versions) for you.
+- **RTL support**: locales reading right-to-left (Arabic, Hebrew...) should be easy to use.
+
+### i18n goals (TODO)
+
+Features that are **not yet implemented**:
+
+- **Contextual translations**: reduce friction to contribute to the translation effort.
+- **Anchor links**: linking should not break when you localize headings.
+- **Advanced configuration options**: customize route paths, file-system paths.
+
+### i18n non-goals
+
+We don't provide support for:
+
+- **Automatic locale detection**: opinionated, and best done on the [server](../deployment.mdx).
+- **Translation SaaS software**: you are responsible to understand the external tools of your choice.
+- **Translation of slugs**: technically complicated, little SEO value.
+
+## Translation workflow
+
+### Overview
+
+Overview of the workflow to create a translated Docusaurus website:
+
+- **Configure**: declare the default locale and alternative locales in `docusaurus.config.js`.
+- **Translate**: put the translation files at the correct file-system location.
+- **Deploy**: build and deploy your site using a single or multi-domain strategy.
+
+### Translation files
+
+You will have to work with 2 kind of translation files.
+
+#### Markdown files
+
+This is the main content of your Docusaurus website.
+
+Markdown and MDX documents are translated as a whole, to fully preserve the translation context, instead of splitting each sentence as a separate string.
+
+#### JSON files
+
+JSON is used to translate:
+
+- your React code: using the `` component
+- your theme: the navbar, footer...
+- your plugins: the docs sidebar category labels...
+
+The JSON format used is called **Chrome i18n**:
+
+```json
+{
+ "myTranslationKey1": {
+ "message": "Translated message 1",
+ "description": "myTranslationKey1 is used on the homepage"
+ },
+ "myTranslationKey2": {
+ "message": "Translated message 2",
+ "description": "myTranslationKey2 is used on the FAQ page"
+ }
+}
+```
+
+The choice was made for 2 reasons:
+
+- **Description attribute**: to help translators with additional context.
+- **Widely supported**: [Chrome extensions](https://developer.chrome.com/docs/extensions/mv2/i18n-messages/), [Crowdin](https://support.crowdin.com/file-formats/chrome-json/), [Transifex](https://docs.transifex.com/formats/chrome-json), [Phrase](https://help.phrase.com/help/chrome-json-messages), [Applanga](https://www.applanga.com/docs/formats/chrome_i18n_json)...
+
+### Translation files location
+
+The translation files should be created at the correct file-system location.
+
+Each locale and plugin has its own `i18n` subfolder:
+
+```
+website/i18n///...
+```
+
+:::note
+
+For multi-instance plugins, the path is `website/i18n//-/...`.
+
+:::
+
+Translating a very simple Docusaurus site in French would lead to the following tree:
+
+```bash
+website/i18n
+└── fr
+ ├── code.json
+ │
+ ├── docusaurus-plugin-content-blog
+ │ └── 2020-01-01-hello.md
+ │
+ ├── docusaurus-plugin-content-docs
+ │ ├── current #
+ │ │ ├── doc1.md
+ │ │ └── doc2.mdx
+ │ └── current.json
+ │
+ └── docusaurus-theme-classic
+ ├── footer.json
+ └── navbar.json
+```
+
+The JSON files are initialized with the [`docusaurus write-translations`](../cli.md#docusaurus-write-translations) CLI command.
+
+The `code.json` file is extracted from React components using the `` api.
+
+:::info
+
+Notice that the `docusaurus-plugin-content-docs` plugin has a `current` subfolder and a `current.json` file, useful for the **docs versioning feature**.
+
+:::
+
+Each content plugin or theme is different, and **define its own translation files location**:
+
+- [Docs i18n](../api/plugins/plugin-content-docs.md#i18n)
+- [Blog i18n](../api/plugins/plugin-content-blog.md#i18n)
+- [Pages i18n](../api/plugins/plugin-content-pages.md#i18n)
+- [Themes i18n](../api/themes/theme-configuration.md#i18n)
diff --git a/website/docs/i18n/i18n-tutorial.md b/website/docs/i18n/i18n-tutorial.md
new file mode 100644
index 000000000000..1cf830d2744b
--- /dev/null
+++ b/website/docs/i18n/i18n-tutorial.md
@@ -0,0 +1,304 @@
+---
+id: tutorial
+title: i18n - Tutorial
+sidebar_label: Tutorial
+slug: /i18n/tutorial
+---
+
+This tutorial will walk you through the basis of the **Docusaurus i18n system**.
+
+We will add **French** translations to a **newly initialized English Docusaurus website**.
+
+Initialize a new site with `npx @docusaurus/init@latest init website classic` (like [this one](https://github.com/facebook/docusaurus/tree/master/examples/classic)).
+
+## Configure your site
+
+Modify `docusaurus.config.js` to add the i18n support for the French language.
+
+### Site configuration
+
+Use the [site i18n configuration](./../api/docusaurus.config.js.md#i18n) to declare the i18n locales:
+
+```js title="docusaurus.config.js"
+module.exports = {
+ i18n: {
+ defaultLocale: 'en',
+ locales: ['en', 'fr'],
+ localeConfigs: {
+ en: {
+ label: 'English',
+ },
+ fr: {
+ label: 'Français',
+ },
+ },
+ },
+};
+```
+
+### Theme configuration
+
+Add a **navbar item** of type `localeDropdown` so that users can select the locale they want:
+
+```js title="docusaurus.config.js"
+module.exports = {
+ themeConfig: {
+ navbar: {
+ items: [
+ // highlight-start
+ {
+ type: 'localeDropdown',
+ position: 'left',
+ },
+ // highlight-end
+ ],
+ },
+ },
+};
+```
+
+### Start your site
+
+Start your localized site in dev mode, using the locale of your choice:
+
+```bash npm2yarn
+npm run start -- --locale fr
+```
+
+Your site is accessible at **`http://localhost:3000/fr/`**, but **falls back to untranslated content**.
+
+:::caution
+
+Each locale is a **distinct standalone single-page-application**: it is not possible to start the Docusaurus sites in all locales at the same time.
+
+:::
+
+## Translate your site
+
+The French translations will be added in `website/i18n/fr`.
+
+Docusaurus is modular, and each content plugin has its own subfolder.
+
+:::note
+
+After copying files around, restart your site with `npm run start -- --locale fr`.
+
+Hot-reload will work better when editing existing files.
+
+:::
+
+### Use the translation APIs
+
+Open the homepage, and use the [translation APIs](../docusaurus-core.md#translate):
+
+```jsx title="src/index.js"
+import React from 'react';
+import Layout from '@theme/Layout';
+// highlight-start
+import Translate, {translate} from '@docusaurus/Translate';
+// highlight-end
+
+export default function Home() {
+ return (
+
+
+ {/* highlight-start */}
+
+ Welcome to my website
+
+ {/* highlight-end */}
+
+
+
+
+
+
+ );
+}
+```
+
+:::caution
+
+Docusaurus provides a **very simple and lightweight translation runtime**: documentation websites generally don't need advanced i18n features.
+
+:::
+
+### Translate JSON files
+
+JSON translation files are used for everything that is not contained in a Markdown document:
+
+- React/JSX code
+- Layout navbar and footer labels
+- Docs sidebar category labels
+- ...
+
+Run the [write-translations](../cli.md#docusaurus-write-translations) command:
+
+```bash npm2yarn
+npm run write-translations -- --locale fr
+```
+
+It will extract and initialize the JSON translation files that you need to translate.
+
+The homepage translations are statically extracted from React source code:
+
+```json title="i18n/fr/code.json"
+{
+ "Welcome to my website": {
+ "message": "Welcome to my website",
+ "description": "The homepage welcome message"
+ },
+ "Hello": {
+ "message": "Hello",
+ "description": "The homepage input placeholder"
+ }
+}
+```
+
+Plugins and themes will also write their own **JSON translation files**, such as:
+
+```json title="i18n/fr/docusaurus-theme-classic/navbar.json"
+{
+ "title": {
+ "message": "My Site",
+ "description": "The title in the navbar"
+ },
+ "item.label.Docs": {
+ "message": "Docs",
+ "description": "Navbar item with label Docs"
+ },
+ "item.label.Blog": {
+ "message": "Blog",
+ "description": "Navbar item with label Blog"
+ },
+ "item.label.GitHub": {
+ "message": "GitHub",
+ "description": "Navbar item with label GitHub"
+ }
+}
+```
+
+Translate the `message` attribute in the JSON files of `i18n/fr`, and your site layout and homepage should now be translated.
+
+### Translate Markdown files
+
+Official Docusaurus content plugins extensively use Markdown/MDX files, and allow you to translate them.
+
+#### Translate the docs
+
+Copy your docs Markdown files to `i18n/fr/docusaurus-plugin-content-docs/current`, and translate them:
+
+```bash
+mkdir -p i18n/fr/docusaurus-plugin-content-docs/current
+cp -r docs/** i18n/fr/docusaurus-plugin-content-docs/current
+```
+
+:::info
+
+`current` is needed for the docs versioning feature: each docs version has its own subfolder.
+
+:::
+
+#### Translate the blog
+
+Copy your blog Markdown files to `i18n/fr/docusaurus-plugin-content-blog`, and translate them:
+
+```bash
+mkdir -p i18n/fr/docusaurus-plugin-content-blog
+cp -r blog/** i18n/fr/docusaurus-plugin-content-blog
+```
+
+#### Translate the pages
+
+Copy your pages Markdown files to `i18n/fr/docusaurus-plugin-content-pages`, and translate them:
+
+```bash
+mkdir -p i18n/fr/docusaurus-plugin-content-pages
+cp -r pages/**.md i18n/fr/docusaurus-plugin-content-pages
+cp -r pages/**.mdx i18n/fr/docusaurus-plugin-content-pages
+```
+
+:::caution
+
+We only copy `.md` and `.mdx` files, as pages React components are translated through JSON translation files already.
+
+:::
+
+## Deploy your site
+
+You can choose to deploy your site under a **single domain**, or use **multiple (sub)domains**.
+
+### Single-domain deployment
+
+Run the following command:
+
+```bash npm2yarn
+npm run build
+```
+
+Docusaurus will build **one single-page application per locale**:
+
+- `website/build`: for the default, English language
+- `website/build/fr`: for the French language
+
+You can now [deploy](../deployment.mdx) the `build` folder to the static hosting solution of your choice.
+
+:::note
+
+The Docusaurus v2 website use this strategy:
+
+- [https://v2.docusaurus.io](https://v2.docusaurus.io)
+- [https://v2.docusaurus.io/fr](https://v2.docusaurus.io/fr)
+
+:::
+
+:::tip
+
+Static hosting providers generally redirect `/unknown/urls` to `/404.html` by convention, always showing an **English 404 page**.
+
+**Localize your 404 pages** by configuring your host to redirect `/fr/*` to `/fr/404.html`.
+
+This is not always possible, and depends on your host: GitHub Pages can't do this, [Netlify](https://docs.netlify.com/routing/redirects/redirect-options/#custom-404-page-handling) can.
+
+:::
+
+### Multi-domain deployment
+
+You can also build your site for a single locale:
+
+```bash npm2yarn
+npm run build -- --locale fr
+```
+
+Docusaurus will not add the `/fr/` url prefix.
+
+On your [static hosting provider](../deployment.mdx):
+
+- create one deployment per locale
+- configure the appropriate build command, using the `--locale` option
+- configure the (sub)domain of your choice for each deployment
+
+:::caution
+
+This strategy is **not possible** with Github Pages, as it is only possible to **have a single deployment**.
+
+:::
+
+### Hybrid
+
+It is possible to have some locales using sub-paths, and others using subdomains.
+
+It is also possible to deploy each locale as a separate subdomain, assemble the subdomains in a single unified domain at the CDN level:
+
+- Deploy your site as `fr.docusaurus.io`
+- Configure a CDN to serve it from `docusaurus.io/fr`
diff --git a/website/docs/installation.md b/website/docs/installation.md
index af54db190019..88e2d69677ce 100644
--- a/website/docs/installation.md
+++ b/website/docs/installation.md
@@ -5,10 +5,16 @@ title: Installation
Docusaurus is essentially a set of npm [packages](https://github.com/facebook/docusaurus/tree/master/packages) that can be installed over npm.
+:::tip
+
+Use **[new.docusaurus.io](https://new.docusaurus.io)** to test Docusaurus immediately in CodeSandbox.
+
+:::
+
## Requirements
- [Node.js](https://nodejs.org/en/download/) version >= 10.15.1 or above (which can be checked by running `node -v`). You can use [nvm](https://github.com/nvm-sh/nvm) for managing multiple Node versions on a single machine installed
-- [Yarn](https://yarnpkg.com/en/) version >= 1.5 (which can be checked by running `yarn version`). Yarn is a performant package manager for JavaScript and replaces the `npm` client. It is not strictly necessary but highly encouraged.
+- [Yarn](https://yarnpkg.com/en/) version >= 1.5 (which can be checked by running `yarn --version`). Yarn is a performant package manager for JavaScript and replaces the `npm` client. It is not strictly necessary but highly encouraged.
## Scaffold project website
@@ -32,12 +38,18 @@ If you do not specify `name` or `template`, it will prompt you for them. We reco
npx @docusaurus/init@latest init my-website facebook
```
-**[Experimental]:** If you want setting up a new website using [bootstrap](https://getbootstrap.com/), use the `bootstrap` template, like the following::
+**[Experimental]:** If you want setting up a new website using [bootstrap](https://getbootstrap.com/), use the `bootstrap` template, like the following:
```bash
npx @docusaurus/init@latest init my-website bootstrap
```
+If you want to skip installing dependencies, use the `--skip-install` option, like the following:
+
+```bash
+npx @docusaurus/init@latest init my-website classic --skip-install
+```
+
## Project structure
Assuming you chose the classic template and named your site `my-website`, you will see the following files generated under a new directory `my-website/`:
@@ -71,7 +83,7 @@ my-website
### Project structure rundown
- `/blog/` - Contains the blog Markdown files. You can delete the directory if you do not want/need a blog. More details can be found in the [blog guide](blog.md).
-- `/docs/` - Contains the Markdown files for the docs. Customize the order of the docs sidebar in `sidebars.js`. More details can be found in the [docs guide](markdown-features.mdx).
+- `/docs/` - Contains the Markdown files for the docs. Customize the order of the docs sidebar in `sidebars.js`. More details can be found in the [docs guide](./guides/docs/docs-markdown-features.mdx).
- `/src/` - Non-documentation files like pages or custom React components. You don't have to strictly put your non-documentation files in here but putting them under a centralized directory makes it easier to specify in case you need to do some sort of linting/processing
- `/src/pages` - Any files within this directory will be converted into a website page. More details can be found in the [pages guide](guides/creating-pages.md).
- `/static/` - Static directory. Any contents inside here will be copied into the root of the final `build` directory.
@@ -100,7 +112,7 @@ Docusaurus is a modern static website generator so we need to build the website
npm run build
```
-and contents will be generated within the `/build` directory, which can be copied to any static file hosting service like [GitHub pages](https://pages.github.com/), [Vercel](https://vercel.com/) or [Netlify](https://www.netlify.com/). Check out the docs on [deployment](deployment.mdx)) for more details.
+and contents will be generated within the `/build` directory, which can be copied to any static file hosting service like [GitHub pages](https://pages.github.com/), [Vercel](https://vercel.com/) or [Netlify](https://www.netlify.com/). Check out the docs on [deployment](deployment.mdx) for more details.
## Updating your Docusaurus version
@@ -126,7 +138,7 @@ Then, in the directory containing `package.json`, run your package manager's ins
npm install
```
-To check that that the update occurred successfully, run:
+To check that the update occurred successfully, run:
```bash npm2yarn
npx docusaurus --version
diff --git a/website/docs/introduction.md b/website/docs/introduction.md
index 9df13d66e91e..02c983b68166 100644
--- a/website/docs/introduction.md
+++ b/website/docs/introduction.md
@@ -13,22 +13,28 @@ We highly encourage you to **use Docusaurus v2 over Docusaurus v1**.
Most users are already using v2 ([trends](https://www.npmtrends.com/docusaurus-vs-@docusaurus/core)), including [React Native](https://reactnative.dev), [Redux](https://redux.js.org/) and [many others](/showcase).
-**Use **Docusaurus v2** if:**
+**Use Docusaurus v2 if:**
- :white_check_mark: You want a modern Jamstack documentation site
- :white_check_mark: You want a single-page application (SPA) with client-side routing
- :white_check_mark: You want the full power of React and MDX
- :white_check_mark: You do not need support for IE11
+:::tip
+
+Use **[new.docusaurus.io](https://new.docusaurus.io)** to test Docusaurus immediately in CodeSandbox.
+
+:::
+
**Use [Docusaurus v1](https://docusaurus.io/) if:**
- :x: You don't want a single-page application (SPA)
-- :x: You prefer stability over modernity (try [Docusaurus 1](https://docusaurus.io/) instead)
+- :x: You prefer stability over modernity
- :x: You need support for IE11
## A better Docusaurus is coming to town
-
+![Docusaurus Slash Introduction](/img/slash-introducing.svg)
Docusaurus 1 used to be a pure documentation site generator. In Docusaurus 2, we rebuilt it from the ground up, allowing for more customizability but preserved the best parts of Docusaurus 1 - easy to get started, versioned docs, and i18n (_coming soon_).
diff --git a/website/docs/lifecycle-apis.md b/website/docs/lifecycle-apis.md
index a97d1cc09359..c41b3ac9143a 100644
--- a/website/docs/lifecycle-apis.md
+++ b/website/docs/lifecycle-apis.md
@@ -346,6 +346,45 @@ module.exports = function (context, options) {
Read the [webpack-merge strategy doc](https://github.com/survivejs/webpack-merge#merging-with-strategies) for more details.
+## `configurePostCss(options)`
+
+Modifies [`postcssOptions` of `postcss-loader`](https://webpack.js.org/loaders/postcss-loader/#postcssoptions) during the generation of the client bundle.
+
+Should return the mutated `postcssOptions`.
+
+By default, `postcssOptions` looks like this:
+
+```js
+const postcssOptions = {
+ ident: 'postcss',
+ plugins: [
+ require('postcss-preset-env')({
+ autoprefixer: {
+ flexbox: 'no-2009',
+ },
+ stage: 4,
+ }),
+ ],
+};
+```
+
+Example:
+
+```js title="docusaurus-plugin/src/index.js"
+module.exports = function (context, options) {
+ return {
+ name: 'docusaurus-plugin',
+ // highlight-start
+ configurePostCss(postcssOptions) {
+ // Appends new PostCSS plugin.
+ postcssOptions.plugins.push(require('postcss-import'));
+ return postcssOptions;
+ },
+ // highlight-end
+ };
+};
+```
+
## `postBuild(props)`
Called when a (production) build finishes.
@@ -362,20 +401,23 @@ type Props = {
postBodyTags: string;
routesPaths: string[];
plugins: Plugin[];
+ stats: Stats.ToJsonOutput;
};
```
Example:
-```js {4-9} title="docusaurus-plugin/src/index.js"
+```js {4-11} title="docusaurus-plugin/src/index.js"
module.exports = function (context, options) {
return {
name: 'docusaurus-plugin',
- async postBuild({siteConfig = {}, routesPaths = [], outDir}) {
+ async postBuild({siteConfig = {}, routesPaths = [], outDir, stats}) {
// Print out to console all the rendered routes.
routesPaths.map((route) => {
console.log(route);
});
+ // Print out to console all the webpack stats.
+ console.log(stats);
},
};
};
diff --git a/website/docs/migration/migration-automated.md b/website/docs/migration/migration-automated.md
index 7c1f8de1196b..d2cab3de01d5 100644
--- a/website/docs/migration/migration-automated.md
+++ b/website/docs/migration/migration-automated.md
@@ -61,7 +61,7 @@ You can add option flags to the migration CLI to automatically migrate Markdown
```bash
# example using options
-npx docusaurus-migrate migrate --mdx --page ./v1-website ./v2-website
+npx @docusaurus/migrate migrate --mdx --page ./v1-website ./v2-website
```
:::danger
diff --git a/website/docs/migration/migration-manual.md b/website/docs/migration/migration-manual.md
index 7a4390bfca76..e27f0c4d76a8 100644
--- a/website/docs/migration/migration-manual.md
+++ b/website/docs/migration/migration-manual.md
@@ -4,7 +4,7 @@ title: Manual migration
slug: /migration/manual
---
-This manual migration process should be run after the [automated migration prcess](./migration-automated.md), to complete the missing parts, or debug issues in the migration CLI output.
+This manual migration process should be run after the [automated migration process](./migration-automated.md), to complete the missing parts, or debug issues in the migration CLI output.
## Project setup
@@ -208,6 +208,8 @@ We recommend using [ColorBox](https://www.colorbox.io/) to find the different sh
Alteratively, use the following tool to generate the different shades for your website and copy the variables into `src/css/custom.css`.
+import ColorGenerator from '@site/src/components/ColorGenerator';
+
#### `footerIcon`, `copyright`, `ogImage`, `twitterImage`, `docsSideNavCollapsible`
@@ -453,7 +455,7 @@ If you want to keep the `.html` extension as the canonical url of a page, docs c
### Sidebar
-In previous version, nested sidebar category is not allowed and sidebar category can only contain doc id. However, v2 allows infinite nested sidebar and we have many types of [Sidebar Item](docs.md#sidebar-item) other than document.
+In previous version, nested sidebar category is not allowed and sidebar category can only contain doc id. However, v2 allows infinite nested sidebar and we have many types of [Sidebar Item](../guides/docs/sidebar.md#understanding-sidebar-items) other than document.
You'll have to migrate your sidebar if it contains category type. Rename `subcategory` to `category` and `ids` to `items`.
@@ -501,7 +503,7 @@ In Docusaurus v1, pages received the `siteConfig` object as props.
In Docusaurus v2, get the `siteConfig` object from `useDocusaurusContext` instead.
-In v2, you have to apply the theme layout around each page. The Layout component takes metadata props (`permalink` is important, as it defines the canonical url of your page).
+In v2, you have to apply the theme layout around each page. The Layout component takes metadata props.
`CompLibrary` is deprecated in v2, so you have to write your own React component or use Infima styles (Docs will be available soon, sorry about that! In the meanwhile, inspect the V2 website or view https://facebookincubator.github.io/infima/ to see what styles are available).
@@ -513,16 +515,12 @@ Here's a typical Docusaurus v2 page:
import React from 'react';
import Link from '@docusaurus/Link';
import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
-import useBaseUrl from '@docusaurus/useBaseUrl';
import Layout from '@theme/Layout';
const MyPage = () => {
const {siteConfig} = useDocusaurusContext();
return (
-
+