Ir para o conteúdo principal
Version: 2.1.0

i18n - Tutorial

This tutorial will walk you through the basics of the Docusaurus i18n system.

Nós iremos adicionar traduções de francês a um recém-inicializado site em Inglês Docusaurus.

Initialize a new site with npx [email protected] website classic (like this one).

Configure seu site

Modifique o docusaurus.config.js para adicionar o suporte do i18n para a língua francesa.

Configuração do site

Use a configuração i18n do site para declarar as localidades i18n:

docusaurus.config.js
module.exports = {
i18n: {
defaultLocale: 'en',
locales: ['en', 'fr', 'fa'],
localeConfigs: {
en: {
htmlLang: 'en-GB',
},
// You can omit a locale (e.g. fr) if you don't need to override the defaults
fa: {
direction: 'rtl',
},
},
},
};

The locale names are used for the translation files' locations, as well as your translated locales' base URL. When building all locales, only the default locale will have its name omitted in the base URL.

Docusaurus uses the locale names to provide sensible defaults: the <html lang="..."> attribute, locale label, calendar format, etc. You can customize these defaults with the localeConfigs.

Configuração do tema

Adicione um item da barra de navegação do tipo localeDropdown para que os usuários possam selecionar a localidade que quiserem:

docusaurus.config.js
module.exports = {
themeConfig: {
navbar: {
items: [
{
type: 'localeDropdown',
position: 'left',
},
],
},
},
};

Iniciar seu site

Inicie seu site localizado no modo de desenvolvimento, usando a localidade de sua escolha:

npm run start -- --locale fr

Your site is accessible at http://localhost:3000/fr/.

We haven't provided any translation yet, so the site is mostly untranslated.

tip

O Docusaurus fornece traduções padrão para nomes genéricos de temas, tais como "Próximo" e "Anterior" para a paginação.

Please help us complete those default translations.

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.

Traduzir o seu site

All translation data for the French locale is stored in website/i18n/fr. Each plugin sources its own translated content under the corresponding folder, while the code.json file defines all text labels used in the React code.

note

Depois de copiar os arquivos, reinicie seu site com npm run start - --locale fr. O hot-reload funcionará melhor ao editar arquivos existentes.

Translate your React code

For any React code you've written yourself: React pages, React components, etc., you will use the translation APIs.

Locate all text labels in your React code that will be visible to your users, and mark them with the translation APIs. There are two kinds of APIs:

  • The <Translate> component wraps a string as a JSX element;
  • The translate() callback takes a message and returns a string.

Use the one that better fits the context semantically. For example, the <Translate> can be used as React children, while for props that expect a string, the callback can be used.

caution

A JSX element is an object, not a string. Using it in contexts expecting strings (such as the children of <option>) would coerce it to a string, which returns "[object Object]". While we encourage you to use <Translate> as JSX children, only use the element form when it actually works.

src/pages/index.js
import React from 'react';
import Layout from '@theme/Layout';
import Link from '@docusaurus/Link';

export default function Home() {
return (
<Layout>
<h1>Welcome to my website</h1>
<main>
You can also visit my
<Link to="https://docusaurus.io/blog">blog</Link>
<img
src="/img/home.png"
alt="Home icon"
/>
</main>
</Layout>
);
}
info

Docusaurus fornece um tempo de execução de tradução muito baixo e leve propositalmente e só oferece suporte a interpolação de marcadores de posição, usando um subconjunto do Formato de mensagem ICU.

A maioria dos sites de documentação são geralmente estáticos e não precisam de recursos i18n avançados (plurais, gêneros, etc.). Use uma biblioteca como react-intl para casos de uso mais avançados.

The docusaurus write-translations command will statically analyze all React code files used in your site, extract calls to these APIs, and aggregate them in the code.json file. The translation files will be stored as maps from IDs to translation message objects (including the translated label and the description of the label). In your calls to the translation APIs (<Translate> or translate()), you need to specify either the default untranslated message or the ID, in order for Docusaurus to correctly correlate each translation entry to the API call.

text labels must be static

The docusaurus write-translations command only does static analysis of your code. It doesn't actually run your site. Therefore, dynamic messages can't be extracted, as the message is an expression, not a string:

const items = [
{id: 1, title: 'Hello'},
{id: 2, title: 'World'},
];

function ItemsList() {
return (
<ul>
{/* DON'T DO THIS: doesn't work with the write-translations command */}
{items.map((item) => (
<li key={item.id}>
<Translate>{item.title}</Translate>
</li>
))}
<ul>
);
}

This still behaves correctly at runtime. However, in the future, we may provide a "no-runtime" mechanism, allowing the translations to be directly inlined in the React code through Babel transformations, instead of calling the APIs at runtime. Therefore, to be future-proof, you should always prefer statically analyzable messages. For example, we can refactor the code above to:

const items = [
{id: 1, title: <Translate>Hello</Translate>},
{id: 2, title: <Translate>World</Translate>},
];

function ItemsList() {
return (
<ul>
{/* The titles are now already translated when rendering! */}
{items.map((item) => (
<li key={item.id}>{item.title}</li>
))}
<ul>
);
}

You can see the calls to the translation APIs as purely markers that tell Docusaurus that "here's a text label to be replaced with a translated message".

Pluralization

When you run write-translations, you will notice that some labels are pluralized:

i18n/en/code.json
{
// ...
"theme.blog.post.plurals": "One post|{count} posts"
// ...
}

Every language will have a list of possible plural categories. Docusaurus will arrange them in the order of ["zero", "one", "two", "few", "many", "other"]. For example, because English (en) has two plural forms ("one" and "other"), the translation message has two labels separated by a pipe (|). For Polish (pl) which has three plural forms ("one", "few", and "many"), you would provide three labels in that order, joined by pipes.

You can pluralize your own code's messages as well:

import {translate} from '@docusaurus/Translate';
import {usePluralForm} from '@docusaurus/theme-common';

function ItemsList({items}) {
// `usePluralForm` will provide the plural selector for the current locale
const {selectMessage} = usePluralForm();
// Select the appropriate pluralized label based on `items.length`
const message = selectMessage(
items.length,
translate(
{message: 'One item|{count} items'},
{count: items.length},
),
);
return (
<>
<h2>{message}</h2>
<ul>{items.map((item) => <li key={item.id}>{item.title}</li>)}<ul>
</>
);
}
note

Docusaurus uses Intl.PluralRules to resolve and select plural forms. It is important to provide the right number of plural forms in the right order for selectMessage to work.

Translate plugin data

JSON translation files are used for everything that is interspersed in your code:

  • React code, including the translated labels you have marked above
  • Navbar and footer labels in theme config
  • Docs sidebar category labels in sidebars.js
  • Blog sidebar title in plugin options
  • ...

Execute o comando write-translations:

npm run write-translations -- --locale fr

Ele irá extrair e inicializar os arquivos de tradução JSON que você precisa traduzir. The code.json file at the root includes all translation API calls extracted from the source code, which could either be written by you or provided by the themes, some of which may already be translated by default.

i18n/fr/code.json
{
// No ID for the <Translate> component: the default message is used as ID
"Welcome to my website": {
"message": "Welcome to my website"
},
"home.visitMyBlog": {
"message": "You can also visit my {blog}",
"description": "The homepage message to ask the user to visit my blog"
},
"homepage.visitMyBlog.linkLabel": {
"message": "Blog",
"description": "The label for the link to my blog"
},
"Home icon": {
"message": "Home icon",
"description": "The homepage icon alt message"
}
}

Plugins and themes will also write their own JSON translation files, such as:

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"
}
}

Traduza o atributomensagem nos arquivos JSON de i18n/fr, e o layout do seu site e a página inicial agora devem ser traduzidos.

Traduzir arquivos Markdown

Official Docusaurus content plugins extensively use Markdown/MDX files and allow you to translate them.

Traduzir os documentos

Copy your docs Markdown files from docs/ to i18n/fr/docusaurus-plugin-content-docs/current, and translate them:

mkdir -p i18n/fr/docusaurus-plugin-content-docs/current
cp -r docs/** i18n/fr/docusaurus-plugin-content-docs/current
info

Notice that the docusaurus-plugin-content-docs plugin always divides its content by versions. The data in ./docs folder will be translated in the current subfolder and current.json file. See the doc versioning guide for more information about what "current" means.

Traduzir o blog

Copie os arquivos Markdown do seu blog para i18n/fr/docusaurus-plugin-content-blog e traduza-os:

mkdir -p i18n/fr/docusaurus-plugin-content-blog
cp -r blog/** i18n/fr/docusaurus-plugin-content-blog

Traduzir as páginas

Copie os arquivos Markdown de suas páginas para i18n/fr/docusaurus-plugin-content-pages e traduza:

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 React pages are translated through JSON translation files already.

Use explicit heading IDs

By default, a Markdown heading ### Hello World will have a generated ID hello-world. Other documents can link it with [link](#hello-world). However, after translation, the 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:

- [link](#hello-world).
+ [link](#bonjour-le-monde)

For localized sites, it is recommended to use explicit heading IDs.

Deploy do seu site

You can choose to deploy your site under a single domain or use multiple (sub)domains.

Implementação de um domínio

Execute o seguinte comando:

npm run build

O Docusaurus irá construir uma aplicação única por localidade:

  • website/build: por padrão, língua inglesa
  • website/build/fr: para o idioma francês

Agora você pode fazer deploy e build na solução de hospedagem estática de sua escolha.

note

The Docusaurus v2 website uses this strategy:

tip

Static hosting providers generally redirect /unknown/url to /404.html by convention, always showing an English 404 page.

Localize suas páginas 404 configurando seu host para redirecionar /fr/* para /fr/404.html.

Isso nem sempre é possível e depende do seu host: as páginas do GitHub não podem fazer isso, [Netlify](https://docs.netlify.com/routing/redirects/redirect-options/#custom-404-page- manipulação) pode.

Deploy multi-domínio

Você também pode criar seu site para uma única localidade:

npm run build -- --locale fr

O Docusaurus não adicionará o prefixo URL /fr/.

No seu provedor de hospedagem estática:

  • crie uma implantação por localidade
  • configure o comando de compilação apropriado, usando a opção --locale
  • configure o (sub)domínio de sua escolha para cada implantação
caution

This strategy is not possible with GitHub Pages, as it is only possible to have a single deployment.

Híbrido

É possível ter alguns locais usando subcaminhos e outros usando subdomínios.

Também é possível implantar cada local como um subdomínio separado, montar os subdomínios em um único domínio unificado no nível de CDN:

  • Fazer deploy do seu site como fr.docusaurus.io
  • Configure um CDN para servi-lo a partir de docusaurus.io/fr

Managing translations

Docusaurus doesn't care about how you manage your translations: all it needs is that all translation files (JSON, Markdown, or other data files) are available in the file system during building. However, as site creators, you would need to consider how translations are managed so your translation contributors could collaborate well.

We will share two common translation collaboration strategies: using git and using Crowdin.