mirror of
https://github.com/facebook/docusaurus.git
synced 2025-06-06 12:52:31 +02:00
docs(v2): Add missing i18n docs: API lifecycles + Crowdin migration guide (#4470)
* Add the missing i18n docs: Crowdin migration + i18n lifecycle APIs * fix heading ids * fix doc typo
This commit is contained in:
parent
80e40c36e5
commit
dd5e5098b8
4 changed files with 288 additions and 15 deletions
|
@ -7,12 +7,6 @@ slug: /i18n/introduction
|
|||
|
||||
It is **easy to translate a Docusaurus website** with its internationalization ([i18n](https://en.wikipedia.org/wiki/Internationalization_and_localization)) support.
|
||||
|
||||
:::caution
|
||||
|
||||
i18n is a new feature (released early 2021), please report any bug you find.
|
||||
|
||||
:::
|
||||
|
||||
## Goals {#goals}
|
||||
|
||||
It is important to understand the **design decisions** behind the Docusaurus i18n support.
|
||||
|
|
|
@ -606,6 +606,121 @@ For example, the in docusaurus-plugin-content-docs:
|
|||
In contentLoaded, for each doc Markdown file, a route is created: /doc/installation, /doc/getting-started, etc.
|
||||
-->
|
||||
|
||||
## i18n lifecycles {#i18n-lifecycles}
|
||||
|
||||
### `getTranslationFiles()` {#get-translation-files}
|
||||
|
||||
Plugins declare the JSON translation files they want to use.
|
||||
|
||||
Returns translation files `{path: string, content: ChromeI18nJSON}`:
|
||||
|
||||
- Path: relative to the plugin localized folder `i18n/<locale>/pluginName`. Extension `.json` is not necessary.
|
||||
- Content: using the Chrome i18n JSON format
|
||||
|
||||
These files will be written by the [`write-translations` CLI](./cli.md#docusaurus-write-translations-sitedir) to the plugin i18n subfolder, and will be read in the appropriate locale before calling [`translateContent()`](#translate-content) and [`translateThemeConfig()`](#translate-theme-config)
|
||||
|
||||
Example:
|
||||
|
||||
```js
|
||||
module.exports = function (context, options) {
|
||||
return {
|
||||
name: 'my-plugin',
|
||||
// highlight-start
|
||||
async getTranslationFiles() {
|
||||
return [
|
||||
{
|
||||
path: 'sidebar-labels',
|
||||
content: {
|
||||
someSidebarLabel: {
|
||||
message: 'Some Sidebar Label',
|
||||
description: 'A label used in my plugin in the sidebar',
|
||||
},
|
||||
},
|
||||
},
|
||||
];
|
||||
},
|
||||
// highlight-end
|
||||
};
|
||||
};
|
||||
```
|
||||
|
||||
### `translateContent({content,translationFiles})` {#translate-content}
|
||||
|
||||
Translate the plugin content, using the localized translation files.
|
||||
|
||||
Returns the localized plugin content.
|
||||
|
||||
The `contentLoaded()` lifecycle will be called with the localized plugin content returned by `translateContent()`.
|
||||
|
||||
Example:
|
||||
|
||||
```js
|
||||
module.exports = function (context, options) {
|
||||
return {
|
||||
name: 'my-plugin',
|
||||
// highlight-start
|
||||
translateContent({content, translationFiles}) {
|
||||
const myTranslationFile = translationFiles.find(
|
||||
(f) => f.path === 'myTranslationFile',
|
||||
);
|
||||
return {
|
||||
...content,
|
||||
someContentLabel: myTranslationFile.someContentLabel.message,
|
||||
};
|
||||
},
|
||||
// highlight-end
|
||||
};
|
||||
};
|
||||
```
|
||||
|
||||
### `translateThemeConfig({themeConfig,translationFiles})` {#translate-theme-config}
|
||||
|
||||
Translate the site `themeConfig` labels, using the localized translation files.
|
||||
|
||||
Returns the localized `themeConfig`.
|
||||
|
||||
Example:
|
||||
|
||||
```js
|
||||
module.exports = function (context, options) {
|
||||
return {
|
||||
name: 'my-theme',
|
||||
// highlight-start
|
||||
translateThemeConfig({themeConfig, translationFiles}) {
|
||||
const myTranslationFile = translationFiles.find(
|
||||
(f) => f.path === 'myTranslationFile',
|
||||
);
|
||||
return {
|
||||
...themeConfig,
|
||||
someThemeConfigLabel: myTranslationFile.someThemeConfigLabel.message,
|
||||
};
|
||||
},
|
||||
// highlight-end
|
||||
};
|
||||
};
|
||||
```
|
||||
|
||||
### `async getDefaultCodeTranslationMessages()` {#get-default-code-translation-messages}
|
||||
|
||||
Themes using the `<Translate>` API can provide default code translation messages.
|
||||
|
||||
It should return messages in `Record<string,string`>, where keys are translation ids and values are messages (without the description) localized using the site current locale.
|
||||
|
||||
Example:
|
||||
|
||||
```js
|
||||
module.exports = function (context, options) {
|
||||
return {
|
||||
name: 'my-theme',
|
||||
// highlight-start
|
||||
async getDefaultCodeTranslationMessages() {
|
||||
return readJsonFile(`${context.i18n.currentLocale}.json`);
|
||||
},
|
||||
// highlight-end
|
||||
};
|
||||
};
|
||||
```
|
||||
|
||||
## Example {#example}
|
||||
|
||||
Here's a mind model for a presumptuous plugin implementation.
|
||||
|
@ -687,6 +802,22 @@ module.exports = function (context, opts) {
|
|||
injectHtmlTags() {
|
||||
// Inject head and/or body HTML tags.
|
||||
},
|
||||
|
||||
async getTranslationFiles() {
|
||||
// Return translation files
|
||||
},
|
||||
|
||||
translateContent({content, translationFiles}) {
|
||||
// translate the plugin content here
|
||||
},
|
||||
|
||||
translateThemeConfig({themeConfig, translationFiles}) {
|
||||
// translate the site themeConfig here
|
||||
},
|
||||
|
||||
async getDefaultCodeTranslationMessages() {
|
||||
// return default theme translations here
|
||||
},
|
||||
};
|
||||
};
|
||||
```
|
||||
|
|
|
@ -4,12 +4,6 @@ title: Migration overview
|
|||
slug: /migration
|
||||
---
|
||||
|
||||
:::caution
|
||||
|
||||
For v1 translated sites, the migration doc is not available yet.
|
||||
|
||||
:::
|
||||
|
||||
This doc guides you through migrating an existing Docusaurus 1 site to Docusaurus 2.
|
||||
|
||||
We try to make this as easy as possible, and provide a migration cli.
|
||||
|
|
|
@ -4,10 +4,164 @@ title: Translated sites
|
|||
slug: /migration/translated-sites
|
||||
---
|
||||
|
||||
:::warning
|
||||
This page explains how migrate a translated Docusaurus v1 site to Docusaurus v2.
|
||||
|
||||
We don't provide yet a migration path for v1 translated sites.
|
||||
## i18n differences {#i18n-differences}
|
||||
|
||||
v2 i18n support is a [work in progress](https://github.com/facebook/docusaurus/pull/3325), and will be added before the end of 2020 with a migration guide to help you migrate from v1 + Crowdin to v2 + Crowdin.
|
||||
Docusaurus v2 i18n is conceptually quite similar to Docusaurus v1 i18n with a few differences.
|
||||
|
||||
It is not tightly coupled to Crowdin, and you can use Git or another SaaS instead.
|
||||
|
||||
### Different filesystem paths {#different-filesystem-paths}
|
||||
|
||||
On Docusaurus v2, localized content is generally found at `website/i18n/<locale>`.
|
||||
|
||||
Docusaurus v2 is modular based on a plugin system, and each plugin is responsible to manage its own translations.
|
||||
|
||||
Each plugin has its own i18n subfolder, like: `website/i18n/fr/docusaurus-plugin-content-blog`
|
||||
|
||||
### Updated translation APIs {#updated-translation-apis}
|
||||
|
||||
With Docusaurus v1, you translate your pages with `<translate>`:
|
||||
|
||||
```jsx
|
||||
const translate = require('../../server/translate.js').translate;
|
||||
|
||||
<h2>
|
||||
<translate desc="the header description">
|
||||
This header will be translated
|
||||
</translate>
|
||||
</h2>;
|
||||
```
|
||||
|
||||
On Docusaurus v2, you translate your pages with `<Translate>`
|
||||
|
||||
```jsx
|
||||
import Translate from '@docusaurus/Translate';
|
||||
|
||||
<h2>
|
||||
<Translate id="header.translation.id" description="the header description">
|
||||
This header will be translated
|
||||
</Translate>
|
||||
</h2>;
|
||||
```
|
||||
|
||||
:::note
|
||||
|
||||
The `write-translations` CLI still works to extract translations from your code.
|
||||
|
||||
The code translations are now added to `i18n/<lang>/code.json` using Chrome i18n JSON format.
|
||||
|
||||
:::
|
||||
|
||||
### Stricter Markdown parser {#stricter-markdown-parser}
|
||||
|
||||
Docusaurus v2 is using [MDX](https://mdxjs.com/) to parse Markdown files.
|
||||
|
||||
MDX compiles Markdown files to React components, is stricter than the Docusaurus v1 parser, and will make your build fail on error instead of rendering some bad content.
|
||||
|
||||
Also, the HTML elements must be replaced by JSX elements.
|
||||
|
||||
This is particularly important for i18n because if your translations are not good on Crowdin and use invalid Markup, your v2 translated site might fail to build: you may need to do some translation cleanup to fix the errors.
|
||||
|
||||
## Migration strategies {#migration-strategies}
|
||||
|
||||
This section will help you figure out how to **keep your existing v1 translations after you migrate to v2**.
|
||||
|
||||
There are **multiple possible strategies** to migrate a Docusaurus v1 site using Crowdin, with different tradeoffs.
|
||||
|
||||
:::caution
|
||||
|
||||
This documentation is a best-effort to help you migrate, please help us improve it if you find a better way!
|
||||
|
||||
:::
|
||||
|
||||
Before all, we recommend to:
|
||||
|
||||
- Migrate your v1 Docusaurus site to v2 without the translations
|
||||
- Get familiar with the [new i18n system of Docusaurus v2](../i18n/i18n-introduction.md) an
|
||||
- Make Crowdin work for your v2 site, using a new and untranslated Crowdin project and the [Crowdin tutorial](../i18n/i18n-crowdin.mdx)
|
||||
|
||||
:::danger
|
||||
|
||||
Don't try to migrate without understanding both Crowdin and Docusaurus v2 i18n.
|
||||
|
||||
:::
|
||||
|
||||
### Create a new Crowdin project {#create-a-new-crowdin-project}
|
||||
|
||||
To avoid any **risk of breaking your v1 site in production**, one possible strategy is to duplicate the original v1 Crowdin project.
|
||||
|
||||
:::info
|
||||
|
||||
This strategy was used to [upgrade the Jest website](https://jestjs.io/blog/2021/03/09/jest-website-upgrade).
|
||||
|
||||
:::
|
||||
|
||||
Unfortunately, Crowdin does not have any "Duplicate/clone Project" feature, which makes things complicated.
|
||||
|
||||
- Download the translation memory of your original project in `.tmx` format (`https://crowdin.com/project/<ORIGINAL_PROJECT>/settings#tm` > `View Records`)
|
||||
- Upload the translation memory to your new project (`https://crowdin.com/project/<NEW_PROJECT>/settings#tm` > `View Records`)
|
||||
- Reconfigure `crowdin.yml` for Docusaurus v2 according to the i18n docs
|
||||
- Upload the Docusaurus v2 source files with the Crowdin CLI to the new project
|
||||
- Mark sensitive strings like `id` or `slug` as "hidden string" on Crowdin
|
||||
- On the "Translations" tab, click on "Pre-Translation > via TM" (`https://crowdin.com/project/<NEW_PROJECT>/settings#translations`)
|
||||
- Try first with "100% match" (more content will be translated than "Perfect"), and pre-translate your sources
|
||||
- Download the Crowdin translations locally
|
||||
- Try to run/build your site and see if there are any errors
|
||||
|
||||
You will likely have errors on your first-try: the pre-translation might try to translate things that it should not be translated (frontmatter, admonition, code blocks...), and the translated md files might be invalid for the MDX parser.
|
||||
|
||||
You will have to fix all the errors until your site builds. You can do that by modifying the translated md files locally, and fix your site for one locale at a time using `docusaurus build --locale fr`.
|
||||
|
||||
There is no ultimate guide we could write to fix these errors, but common errors are due to:
|
||||
|
||||
- Not marking enough strings as "hidden strings" in Crowdin, leading to pre-translation trying to translate these strings.
|
||||
- Having bad v1 translations, leading to invalid markup in v2: bad html elements inside translations and unclosed tags
|
||||
- Anything rejected by the MDX parser, like using HTML elements instead of JSX elements (use the [MDX plaground](https://mdxjs.com/playground/) for debugging)
|
||||
|
||||
You might want to repeat this pre-translation process, eventually trying the "Perfect" option and limiting pre-translation only some languages/files.
|
||||
|
||||
:::tip
|
||||
|
||||
Use [`mdx-code-block`](../i18n/i18n-crowdin.mdx#mdx-solutions) around problematic markdown elements: Crowdin is less likely mess things up with code blocks.
|
||||
|
||||
:::
|
||||
|
||||
:::note
|
||||
|
||||
You will likely notice that some things were translated on your old project, but are now untranslated in your new project.
|
||||
|
||||
The Crowdin Markdown parser is evolving other time and each Crowdin project has a different parser version, which can lead to pre-translation not being able to pre-translate all the strings.
|
||||
|
||||
This parser version is undocumented, and you will have to ask the Crowdin support to know your project's parser version and fix one specific version.
|
||||
|
||||
Using the same cli version and parser version across the 2 Crowdin projects might give better results.
|
||||
|
||||
:::
|
||||
|
||||
:::danger
|
||||
|
||||
Crowdin has an "upload translations" feature, but in our experience it does not give very good results for Markdown
|
||||
|
||||
:::
|
||||
|
||||
### Use the existing Crowdin project {#use-the-existing-crowdin-project}
|
||||
|
||||
If you don't mind modifying your existing Crowdin project and risking to mess things up, it may be possible to use the Crowdin branch system.
|
||||
|
||||
:::caution
|
||||
|
||||
This workflow has not been tested in practice, please report us how good it is.
|
||||
|
||||
:::
|
||||
|
||||
This way, you wouldn't need to create a new Crowdin project, transfer the translation memory, apply pre-translations, and try to fix the pre-translations errors.
|
||||
|
||||
You could create a Crowdin branch for Docusaurus v2, where you upload the v2 sources, and merge the Crowdin branch to master once ready.
|
||||
|
||||
### Use Git instead of Crowdin {#use-git-instead-of-crowdin}
|
||||
|
||||
It is possible to migrate away of Crowdin, and add the translation files to Git instead.
|
||||
|
||||
Use the Crowdin CLI to download the v1 translated files, and put these translated files at the correct Docusaurus v2 filesystem location.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue