i18n - Using 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, 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, Docusaurus and ReasonML.
Refer to the Crowdin documentation and Crowdin support for help.
tip
Use this community-driven GitHub issue to discuss anything related to Docusaurus + Crowdin.
#
Crowdin overviewCrowdin is a translation SaaS, offering a free plan for open-source projects.
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 to upload sources and download translations, allowing you to automate the translation process.
The crowdin.yml
configuration file is convenient for Docusaurus, and permits to download the localized translation files at the expected location (in i18n/<locale>/..
).
Read the official documentation to know more about advanced features and different translation workflows.
#
Crowdin tutorialThis 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.
The end result can be seen at docusaurus-crowdin-example.netlify.app (repository).
#
Prepare the Docusaurus siteInitialize a new Docusaurus site:
Add the site configuration for the French language:
Translate the homepage:
#
Create a Crowdin projectSign up on Crowdin, and create a project.
Use English as source language, and French as target language.
Your project is created, but it is empty for now. We will upload the files to translate in the next steps.
#
Create the Crowdin configurationThis configuration (doc) 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/<locale>
).
Create crowdin.yml
in website
:
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 tokenThe 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.
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 fieldsproject_id
: can be hardcoded, and is found onhttps://crowdin.com/project/<MY_PROJECT_NAME>/settings#api
.preserve_hierarchy
: preserve the folder's hierarchy of your docs on Crowdin UI instead of flattening everything.
#
Install the Crowdin CLIThis 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:
- npm
- Yarn
Add a crowdin
script:
Test that you can run the Crowdin CLI:
- npm
- Yarn
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 sourcesGenerate the JSON translation files for the default language in website/i18n/en
:
- npm
- Yarn
Upload all the JSON and Markdown translation files:
- npm
- Yarn
Your source files are now visible on the Crowdin interface: https://crowdin.com/project/<MY_PROJECT_NAME>/settings#files
#
Translate the sourcesOn https://crowdin.com/project/<MY_PROJECT_NAME>
, click on the French target language.
Translate some Markdown files.
tip
Use Hide String
to make sure translators don't translate things that should not be:
- Frontmatter:
id
,slug
,tags
... - Admonitions:
:::
,:::note
,:::tip
...
Translate some JSON files.
info
The description
attribute of JSON translation files is visible on Crowdin to help translate the strings.
tip
Pre-translate 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 translationsUse the Crowdin CLI to download the translated JSON and Markdown files.
- npm
- Yarn
The translated content should be downloaded in i18n/fr
.
Start your site on the French locale:
- npm
- Yarn
Make sure that your website is now translated in French at http://localhost:3000/fr/
#
Automate with CIWe 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):
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#
MDXwarning
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 versioningConfigure 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.
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 pluginsYou 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 siteSometimes, you will remove or rename a source file on Git, and Crowdin will display CLI warnings:
When your sources are refactored, you should use the Crowdin UI to update your Crowdin files manually:
#
Git / VCS integrationsCrowdin has multiple VCS integrations for GitHub, 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 localizationCrowdin has an 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...
#
Example configurationThe Docusaurus v2 configuration file is a good example of using versioning and multi-instance: