--- id: tutorial title: i18n - 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 create-docusaurus@latest website classic` (like [this one](https://github.com/facebook/docusaurus/tree/main/examples/classic)). ## Configure your site {#configure-your-site} Modify `docusaurus.config.js` to add the i18n support for the French language. ### Site configuration {#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'], }, }; ``` ### Theme configuration {#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-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/`**. We haven't provided any translation, and the site is **mostly untranslated**. :::tip Docusaurus provides **default translations** for generic theme labels, such as "Next" and "Previous" for the pagination. Please help us complete those **[default translations](https://github.com/facebook/docusaurus/tree/main/packages/docusaurus-theme-translations/locales)**. ::: :::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 {#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 {#use-the-translation-apis} Open the homepage, and use the [translation APIs](../docusaurus-core.md#translate): ```jsx title="src/pages/index.js" import React from 'react'; import Layout from '@theme/Layout'; import Link from '@docusaurus/Link'; // highlight-start import Translate, {translate} from '@docusaurus/Translate'; // highlight-end export default function Home() { return (

{/* highlight-start */} Welcome to my website {/* highlight-end */}

{/* highlight-start */} blog}}> {'You can also visit my {blog}'} {/* highlight-end */}
); } ``` :::caution Docusaurus provides a **very small and lightweight translation runtime** on purpose, and only supports basic [placeholders interpolation](../docusaurus-core.md#interpolate), using a subset of the [ICU Message Format](https://formatjs.io/docs/core-concepts/icu-syntax/). Most documentation websites are generally **static** and don't need advanced i18n features (**plurals**, **genders**, etc.). Use a library like [react-intl](https://www.npmjs.com/package/react-intl) for more advanced use-cases. ::: ### Translate JSON files {#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-sitedir) 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 {#translate-markdown-files} Official Docusaurus content plugins extensively use Markdown/MDX files, and allow you to translate them. #### Translate the docs {#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 {#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 {#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 src/pages/**.md i18n/fr/docusaurus-plugin-content-pages cp -r src/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. ::: ### Use explicit heading ids {#use-explicit-heading-ids} By default, a Markdown heading `### Hello World` will have a generated id `hello-world`. Other documents can target it with `[link](#hello-world)`. The translated heading becomes `### Bonjour le Monde`, with id `bonjour-le-monde`. Generated ids are not always a good fit for localized sites, as it requires you to localize all the anchor links: ```diff - [link](#hello-world). + [link](#bonjour-le-monde) ``` :::tip For localized sites, it is recommended to use **[explicit heading ids](../guides/markdown-features/markdown-features-headings.mdx#explicit-ids)**. ::: ## Deploy your site {#deploy-your-site} You can choose to deploy your site under a **single domain**, or use **multiple (sub)domains**. ### Single-domain deployment {#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://docusaurus.io](https://docusaurus.io) - [https://docusaurus.io/fr](https://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 {#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 {#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`