Skip to content

Commit

Permalink
Add interpolation doc + improve i18n doc
Browse files Browse the repository at this point in the history
  • Loading branch information
slorber committed Feb 26, 2021
1 parent 8968c77 commit 86e6b98
Show file tree
Hide file tree
Showing 3 changed files with 127 additions and 26 deletions.
112 changes: 96 additions & 16 deletions website/docs/docusaurus-core.md
Original file line number Diff line number Diff line change
Expand Up @@ -125,25 +125,61 @@ const MyComponent = () => {
};
```

### `<Interpolate/>`

A simple interpolation component for text containing dynamic placeholders.

The placeholders will be replaced with the provided dynamic values and JSX elements of your choice (strings, links, styled elements...).

#### Props

- `children`: text containing interpolation placeholders like `{placeholderName}`
- `values`: object containing interpolation placeholder values

```jsx
import React from 'react';
import Link from '@docusaurus/Link';
import Interpolate from '@docusaurus/Interpolate';

export default function VisitMyWebsiteMessage() {
return (
// highlight-start
<Interpolate
values={{
firstName: 'Sébastien',
website: (
<Link to="https://docusaurus.io" className="my-website-class">
website
</Link>
),
}}>
{'Hello, {firstName}! How are you? Take a look at my {website}'}
</Interpolate>
// highlight-end
);
}
```

### `<Translate/>`

When [localizing your site](./i18n/i18n-introduction.md), the `<Translate/>` component will allow providing **translation support to React components**, such as your homepage.
When [localizing your site](./i18n/i18n-introduction.md), the `<Translate/>` component will allow providing **translation support to React components**, such as your homepage. The `<Translate>` component supports [interpolation](#interpolate).

The translation strings will be extracted from your code with the [`docusaurus write-translations`](./cli.md#docusaurus-write-translations) CLI and create a `code.json` translation file in `website/i18n/<locale>`.

:::note

The `<Translate/>` props **must be hardcoded strings**.

It is **not possible to use variables**, or the extraction wouldn't work.
Apart the `values` prop used for interpolation, it is **not possible to use variables**, or the static extraction wouldn't work.

:::

#### Props

- `children`: untranslated string in the default site locale`
- `children`: untranslated string in the default site locale (can contain [interpolation placeholders](#interpolate))
- `id`: optional value to use as key in JSON translation files
- `description`: optional text to help the translator
- `values`: optional object containing interpolation placeholder values

#### Example

Expand All @@ -169,7 +205,9 @@ export default function Home() {
</h1>
<main>
{/* highlight-start */}
<Translate>My website content</Translate>
<Translate values={{firstName: 'Sébastien'}}>
{'Welcome, {firstName}! How are you?'}
</Translate>
{/* highlight-end */}
</main>
</Layout>
Expand Down Expand Up @@ -378,19 +416,58 @@ const MyComponent = () => {

## Functions

### `interpolate`

The imperative counterpart of the [`<Interpolate>`](#interpolate) component.

#### Signature

```ts
// Simple string interpolation
function interpolate(text: string, values: Record<string, string>): string;

// JSX interpolation
function interpolate(
text: string,
values: Record<string, ReactNode>,
): ReactNode;
```

#### Example

```jsx
// highlight-start
import {interpolate} from '@docusaurus/Interpolate';
// highlight-end

const message = interpolate('Welcome {firstName}', {firstName: 'Sébastien'});
```

### `translate`

The imperative counterpart of the [`<Translate>`](#translate) component.
The imperative counterpart of the [`<Translate>`](#translate) component. Also supporting [placeholders interpolation](#interpolate).

:::tip

Use the imperative API for the **rare cases** when a **component cannot be used**, such as:
Use the imperative API for the **rare cases** where a **component cannot be used**, such as:

- the `placeholder` props of form input
- the page `title` metadata
- the `placeholder` props of form inputs
- the `aria-label` props for accessibility

:::

#### Signature

```ts
function translate(
translation: {message: string; id?: string; description?: string},
values: Record<string, string>,
): string;
```

#### Example

```jsx title="src/index.js"
import React from 'react';
import Layout from '@theme/Layout';
Expand All @@ -406,16 +483,19 @@ export default function Home() {
title={translate({message: 'My page meta title'})}
// highlight-end
>
<input
type="text"
placeholder={
<img
src={'https://docusaurus.io/logo.png'}
aria-label={
// highlight-start
translate({
message: 'Some input placeholder',
// Optional
id: 'homepage.input.placeholder',
description: 'The homepage input placeholder',
})
translate(
{
message: 'The logo of site {siteName}',
// Optional
id: 'homepage.logo.ariaLabel',
description: 'The home page logo aria label',
},
{siteName: 'Docusaurus'},
)
// highlight-end
}
/>
Expand Down
7 changes: 4 additions & 3 deletions website/docs/i18n/i18n-introduction.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ 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)).
It is **easy to translate a Docusaurus website** with its internationalization ([i18n](https://en.wikipedia.org/wiki/Internationalization_and_localization)) support.

:::caution

Expand All @@ -15,7 +15,7 @@ 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.
It is important to 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).

Expand All @@ -27,13 +27,14 @@ The goals of the Docusaurus i18n system are:
- **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.
- **Low-overhead runtime**: documentation is mostly static and does not require a heavy JS library or polyfills.
- **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.
- **Default translations**: theme labels are translated for you in [many languages](https://github.com/facebook/docusaurus/tree/master/packages/docusaurus-theme-classic/codeTranslations).

### i18n goals (TODO)

Expand Down
34 changes: 27 additions & 7 deletions website/docs/i18n/i18n-tutorial.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,17 @@ Start your localized site in dev mode, using the locale of your choice:
npm run start -- --locale fr
```

Your site is accessible at **`http://localhost:3000/fr/`**, but **falls back to untranslated content**.
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/master/packages/docusaurus-theme-classic/codeTranslations)**.

:::

:::caution

Expand Down Expand Up @@ -94,6 +104,8 @@ Open the homepage, and use the [translation APIs](../docusaurus-core.md#translat
```jsx title="src/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
Expand All @@ -103,13 +115,19 @@ export default function Home() {
<Layout>
<h1>
{/* highlight-start */}
<Translate description="The homepage welcome message">
Welcome to my website
</Translate>
<Translate>Welcome to my website</Translate>
{/* highlight-end */}
</h1>
<main>
{/* highlight-start */}
<Translate
id="homepage.visitMyBlog"
description="The homepage message to ask the user to visit my blog"
values={{blog: <Link to="https://docusaurus.io/blog">blog</Link>}}>
{'You can also visit my {blog}'}
</Translate>
{/* highlight-end */}

<div>
<input
type="text"
placeholder={
Expand All @@ -121,15 +139,17 @@ export default function Home() {
// highlight-end
}
/>
</div>
</main>
</Layout>
);
}
```

:::caution

Docusaurus provides a **very simple and lightweight translation runtime**: documentation websites generally don't need advanced i18n features.
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**...). Use a library like [react-intl](https://www.npmjs.com/package/react-intl) for more advanced use-cases.

:::

Expand Down

0 comments on commit 86e6b98

Please sign in to comment.