fix(docs): improve i18n contribution guidelines (#41678)

* fix(docs): improve i18n contribution guidelines

* chore: apply suggestions from code review

Co-authored-by: Nicholas Carrigan (he/him) <nhcarrigan@gmail.com>

Co-authored-by: Nicholas Carrigan (he/him) <nhcarrigan@gmail.com>
This commit is contained in:
Mrugesh Mohapatra
2021-03-31 19:28:54 +05:30
committed by GitHub
parent ded18ded68
commit 40d7e04a61
7 changed files with 373 additions and 231 deletions

View File

@ -2,11 +2,13 @@
Read our ["How to Contribute to Open Source Guide"](https://github.com/freeCodeCamp/how-to-contribute-to-open-source). It's a comprehensive reference for first-timer-friendly projects. And it includes a lot of open source contribution tips.
### Can I translate freeCodeCamp's curriculum?
### Can I translate freeCodeCamp's resources?
Yes - Read [this guide](/how-to-translate-files) if you are interested in contributing to translations.
Yes - You can contribute to any of the 30+ languages we have enabled on our translation platform.
Currently we have the user contributed translations being done in Chinese and Español. We intend to localize freeCodeCamp into several major world languages. You can read all about this in our [announcement here](https://www.freecodecamp.org/news/world-language-translation-effort).
We have the user contributed translations live in Chinese (中文) and Spanish (Español). We intend to localize freeCodeCamp into several major world languages. You can read all about this in our [announcement here](https://www.freecodecamp.org/news/world-language-translation-effort).
If you are interested in contributing to translations please makes sure you [read this guide](/how-to-translate-files) first.
### How can I report a new bug?

View File

@ -9,12 +9,12 @@
- [Work on the news theme](how-to-work-on-the-news-theme.md)
- [Work on the docs theme](how-to-work-on-the-docs-theme.md)
- **Translation Contribution**
- [Translating a Curriculum File](how-to-translate-files.md)
- [Proofreading a Curriculum File](how-to-proofread-files.md)
- [How to Translate the Website](how-to-translate-the-website.md)
- [Work on translating resources](how-to-translate-files.md)
- [Work on proofreading translations](how-to-proofread-files.md)
- **Optional Guides**
- [Set up freeCodeCamp on Windows(WSL)](how-to-setup-wsl.md)
- [Set up freeCodeCamp on Windows (WSL)](how-to-setup-wsl.md)
- [Add Cypress tests](how-to-add-cypress-tests.md)
- [Work on localized client web app](how-to-work-on-localized-client-webapp.md)
- [Catch outgoing emails locally](how-to-catch-outgoing-emails-locally.md)
---

View File

@ -1,8 +1,10 @@
# How to Proofread Translations
Our proofreading team is responsible for ensuring that translations accurately reflect the source text.
Our proofreading team is responsible for ensuring that translations accurately reflect the source text. We trust our proofreaders to ensure that we have very high quality translations.
To begin proofreading, visit [our translation site](https://translate.freecodecamp.org) and login. Then select "Go to console" in the top navigation bar to switch from the public view to the workspace view.
All our translations are done by hand, by real humans. Proofreading ensures that there is a consistent tone across our all our translated resources like the curriculum.
To begin proofreading, visit [our translation platform](https://translate.freecodecamp.org) and login. Select "Go to console" in the top navigation bar to switch from the public view to the workspace view.
## Select a File
@ -23,21 +25,33 @@ You should now see the list of available files. Choose your file by selecting th
Here you will see the list of strings in the selected file, with their related translations. The translation that is displayed here is the translation that has received the highest score (between upvotes and downvotes) from the translation community.
While you can view *all* proposed translations for a given string, the community scores (determined by the upvotes and downvotes) should be taken into consideration when choosing which translation to approve. The community can review proposed translations and recommend which one is most accurate and clear.
While you can view _all_ proposed translations for a given string, the community scores (determined by the upvotes and downvotes) should be taken into consideration when choosing which translation to approve. The community can review proposed translations and recommend which one is most accurate and clear.
1. This is the original string (in English).
2. This is the matching translated string. The most popular translation proposal, based on upvotes and downvotes, will be displayed here.
3. Clicking this checkmark button will approve that translation.
4. Crowdin will display the status of each string. `Done` means a translation has been approved and will be downloaded on our next Crowdin pull. `Todo` means the string has not been proofread. `Hidden` means the string is locked and *should not be translated*. `Comment` means the string has a related comment.
4. Crowdin will display the status of each string. `Done` means a translation has been approved and will be downloaded on our next Crowdin pull. `Todo` means the string has not been proofread. `Hidden` means the string is locked and _should not be translated_. `Comment` means the string has a related comment.
5. Translations can be selected with the checkboxes and approved here in one bulk action.
6. You can view the community proposed translations, their popularity scores, and Crowdin suggested translations here.
7. This button shows/hides the right-hand side display pane, where you can view translations, comments, translation memory, and glossary terms.
8. Crowdin displays error messages here from the quality assurance checks. In other words, if something does not seem correct in the translation, Crowdin will notify you. These translations should be approved with care.
> [!WARNING]
No additional actions are required once a file has been proofread.
> [!NOTE]
> Approving a string in the proofreading view will mark it as complete and it will be downloaded in our next pull from Crowdin to GitHub.
No additional actions are required once a file has been proofread. If you have any questions, or are interested in becoming a proofreader, feel free to reach out to us in our [translators chat room](https://chat.freecodecamp.org/channel/translators). If you are already a proofreader and are interested in having a dedicated channel for a specific language, [fill out our form](https://forms.gle/XU5CyutrYCgDYaVZA).
## Becoming a proofreader
If you have any questions, or are interested in becoming a proofreader, feel free to reach out to us in our [translators chat room](https://chat.freecodecamp.org/channel/translators). We will typically grant you proofreading access if you have been contributing to freeCodeCamp for a while.
Our staff team and community moderators teams are always looking for kind volunteers like you who help us make high quality translations available to the world.
> [!NOTE]
> Crowdin will allow you to approve your translations. In general, it is best to allow another proofreader to review your proposed translations as extra safety to ensure there are no errors.
## Creating a channel on Chat for a world language
For the most part we encourage you to use the [translators chat](https://chat.freecodecamp.org/channel/translators) room for all correspondence. However if the team of volunteer translators grows for a certain language, we can consider creating additional break-out channel for the language.
If you are already a proofreader and are interested in having a dedicated channel on our chat servers for a specific language, [fill out this form](https://forms.gle/XU5CyutrYCgDYaVZA).

View File

@ -1,15 +1,79 @@
# How to Translate a File
# How to Translate freeCodeCamp's resources
> [!NOTE]
> All translations are handled through https://translate.freecodecamp.org - we are no longer using GitHub to translate files directly.
It's our dream to provide you with the resources to learn, no matter the world language you speak. To help us with this massive effort, we have integrated our open-source code-base & curriculum with [Crowdin](https://crowdin.com/) - A tool to help us localize our code-base.
To begin, head to our translation website and login (if you have not contributed to translations before, you will need to create an account).
The translation workflow is split into two main activities:
- **Translating** curriculum files, documentation and UI elements like buttons, labels, etc.:
As a translator you can sign up on [our translation platform](https://translate.freecodecamp.org) and contribute translations in any of the 30+ languages enabled in there. If you do not see a language that you speak and are interested in translating, [visit this frequently asked question](/FAQ?id=can-i-translate-freecodecamp39s-resources).
- **Proofreading** the translations for all of the above.
Proofreaders verify that the community contributed translations are uniform in tone and free of common issues like typos, etc. In short, they ensure that the quality of translations is high. Note that we do not use machine translations for a reason.
> [!WARNING]
> We are no longer using GitHub to translate files directly, if you are a returning contributor head to our [translation platform](https://translate.freecodecamp.org/) instead.
## Prepare yourself for contributions
> The freeCodeCamp Localization Roadmap There Are No Speed Limits
You can translate as much as you want, when you want. It's only a matter of how much time and energy you are willing to invest as a volunteer translator.
We just ask that you understand the following:
1. **Translations are a team effort.**
Translating freeCodeCamp's resources is one of the most fun and rewarding experiences as a contributor, and it works best if you involve your friends and colleagues who speak the same world language as you.
We recommend joining [our community forum](https://forum.freecodecamp.org/c/contributors/3) and [translators chat room](https://chat.freecodecamp.org/channel/translators) with your friends and showing your interest before starting off with translations. Crowdin makes it easy to contribute translations, but it's still a lot of work.
We want you to enjoy contributing and not burn out or lose interest.
A small group of 4-5 individuals is a good size to start your niche for your world language. You can then recruit even more friends to join the team.
2. **It costs quite a lot to spin servers for each language.**
On the surface it might not seem how complicated the technical stack is, but it costs quite a lot to keep the engines running. This includes provisioning additional servers and dedicating staff to look after them.
freeCodeCamp.org is committed to providing these for free as always, however we need to prioritize resources for those who need it the most. The last thing we want is to shutdown servers for a language if the translation activity dies off & things become outdated.
Once a language reaches at least a few certifications on the curriculum we can begin deploying the language live on [`/learn`](https://www.freecodecamp.org/learn), while you continue to translate the remaining certifications.
For example, we would want to deploy at least the entire front-end certifications suite when we ship a new world language for the first time.
3. **But what about the languages not listed on the translation platform?**
We have looked at our user base and added 30+ most widely spoken languages to the list of enabled languages on the translations platform. Some languages like Chinese and Spanish are already deployed live on **"/learn"** at this moment.
Unfortunately, the list does not include hundreds of languages out there. We get dozens of requests from contributors like you every day who want to help translate the site into a language they speak.
We are definitely looking forward to adding more languages to the list, but as you may already guess, it would only be feasible if we get enough momentum around a world language.
If you would like us to include a new world language, we recommend getting your friends excited about this.
Once you have a small group of people (at least 4-5) interested and committed, we can hop on a call. We will explain all the details and walk you through some of the tools and processes.
## Getting started
First, make sure you come say "Hi" in our [translators chat room](https://chat.freecodecamp.org/channel/translators). We post regular updates about translating resources and answer a lot of your queries in there.
Next, head to our [translation platform](https://translate.freecodecamp.org/) and login (if you have not contributed to translations before, you will need to create an account).
Finally, go through the detailed walk-thru below to understand the translation tools and workflows at your disposal.
Happy translating.
## Select a Project and File
You should see two "projects" available for translation: The `Contributing Documentation` project, which contains the files for this documentation site, and the `Coding Curriculum` project, which contains our challenge files for `/learn`.
Once you visit the translation platform, you should see multiple "projects" available for translation:
Select which project you want to contribute to, and you will see a list of available languages for translation.
1. [Contributing documentation](https://translate.freecodecamp.org/contributing-docs) project, which contains the files for this documentation site.
2. [Coding Curriculum](https://translate.freecodecamp.org/curriculum) project, which contains our challenge files for our curriculum.
3. [Learn User Interface](https://translate.freecodecamp.org/learn-ui) project which contains strings for UI elements like buttons, labels, etc. for our learning platform.
Select any project you want to contribute to, and you will see a list of available languages for translation.
![Image - List of available languages](https://contribute.freecodecamp.org/images/crowdin/languages.png)
@ -24,7 +88,7 @@ Select a file to work on and Crowdin will open the editor view.
> [!NOTE]
> When the editor view opens, you will need to click the settings icon (shown as a gear) and switch the 'HTML tags displaying' setting to 'SHOW'. This will ensure you can see tags such as `<code></code>` instead of `<0></0>`.
## Translate the File
## Translate Curriculum
![Image - Editor View](https://contribute.freecodecamp.org/images/crowdin/editor.png)
@ -51,7 +115,7 @@ You are welcome to translate as many strings as you like - there are no addition
> [!NOTE]
> If you see something in the English source file that is inaccurate or incorrect, please do not fix it through the translation flow. Instead, leave a comment on the string to notify us that there is a discrepancy, or create a GitHub issue.
### Translating Documentation
## Translate Documentation
Translating our contributing documentation is a similar flow to translating our curriculum files.

View File

@ -1,204 +0,0 @@
The client/react side of our website is translated into various world languages using [react-i18next](https://react.i18next.com/) and [i18next](https://www.i18next.com/).
> [!NOTE]
> Curriculum lesson content is [translated separately](./how-to-translate-files.md).
## File Structure
The files for translating the website are located in the `client/i18n` folder. Each language has a folder within that containing JSON files with the translations.
The values in the `translations.json` file contain the majority of the text that appears on the website. The keys are used in the codebase to get the correct text for whatever language is set. This file needs to have the exact same keys in all languages.
The `intro.json` file contains the key-value pairs for the introduction text on the certification pages.
The `motivation.json` files are not required to have the same quotes, compliments, or array length. Just the same JSON structure. These are not translated via Crowdin.
The `trending.json` file contians the titles and links for the trending news articles in the website's footer. These are not translated via Crowdin.
The `meta-tags.json` file contains the information for our website's meta tag information. These are not translated via Crowdin.
## Adding a Language
To add a new language, create a folder with the language name as the title next to the other languages and copy the JSON files from another language into your new folder.
In the `all-langs.js` file, add the language to the `client` array in the first variable. Then, follow the instructions in the comments to add the rest of the necessary variables.
## How to Translate
Translating the `intro.json` and `translations.json` are done through [our translation site](https://translate.freecodecamp.org). View our [translation documentation for that site](/how-to-translate-files.md).
Modifications to the `trending.json`, `meta-tags.json`, and `motivation.json` files should typically only be done by staff.
## Running it Locally
Set the `CLIENT_LOCALE` variable in your `.env` file to the locale you want to build.
> [!NOTE]
> The value needs to be one of the client languages available in `config/i18n/all-langs.js`
## How to Structure Components
### Functional Component
```js
import { useTranslation } from 'react-i18next';
// in the render method:
const { t } = useTranslation();
// call the "t" function with a key from the JSON file:
<p>{t('key')}</p> // more details below
```
### Class Component
```js
import { withTranslation } from 'react-i18next';
// withTranslation adds the "t" function to props:
const { t } = this.props;
// call the "t" function with a key from the JSON file:
<h1>{t('key')}</h1> // more details below
// export without redux:
export default withTranslation()(Component);
// or with redux:
export default connect(...)(withTranslation()(Component));
```
## Translate Using the "t" Function
### Basic Translation
```js
// in the component:
<p>{t('p1')}</p>
// in the JSON file:
{
"p1": "My paragraph"
}
// output:
<p>My paragraph</p>
```
### With Dynamic Data
```js
// in the component:
const username = 'moT';
<p>{t('welcome', { username: username })}</p>
// in the JSON file:
{
"welcome": "Welcome {{username}}"
}
// output:
<p>Welcome moT</p>
```
The above example passes an object to the `t` function with a `username` variable. The variable will be used in the JSON value where `{{username}}` is.
## Translate with the `Trans` Component
The general rule is to use the "t" function when you can. But there's a `Trans` component for when that isn't enough, usually when you have elements embedded in the text. You can use the `Trans` component with any type of react component.
### Basic Elements Nested
```js
// in the component:
import { Trans } from 'react-i18next'
<p>
<Trans>fcc.greeting</Trans>
</p>
// in the JSON file:
{
"fcc": {
"greeting": "Welcome to <strong>freeCodeCamp</strong>"
}
}
// output:
<p>Welcome to <strong>freeCodeCamp</strong></p>
```
You can place the key inside the component tags like the above example if the text contains "simple" tags with no attributes. `br`, `strong`, `i`, and `p` are the default, but that list can be expanded in the i18n config.
### Complex Elements Nested
Other times, you will want to have certain text inside another element, an anchor tag is a good example:
```js
// in the component:
<p>
<Trans i18nKey='check-forum'>
<a href='https://forum.freecodecamp.org/'>placeholder</a>
</Trans>
</p>
// in the JSON file:
{
"check-forum": "Check out <0>our forum</0>."
}
// output:
<p>Check out <a href='https://forum.freecodecamp.org/'>our forum</a></p>
```
In the above example, the key is set in the attributes of the `Trans` component. The `<0>` and `</0>` in the JSON represent the first child of the component, in this case, the anchor element. If there were more children, they would just count up from there using the same syntax. You can find the children of a component in the react dev tools by inspecting it. `placeholder` is simply there because the linter was complaining at me about an empty `<a>` element.
### With a Variable
```js
// in the component:
const email = 'team@freecodecamp.org';
<p>
<Trans email={email} i18nKey='fcc.email'>
<a href={`mailto:${email}`}>
{{ email }}
</a>
</Trans>
</p>
// in the JSON file:
{
"fcc": {
"email": "Send us an email at: <0>{{email}}</0>"
}
}
// output:
<p>Send us an email at: <a href='mailto:team@freecodecamp.org'>team@freecodecamp.org</a><p>
```
In the above example, the key and a variable are set in the attributes of the `Trans` component. `{{ email }}` needs to be somewhere in the `Trans` component as well, it doesn't matter where.
## Changing Text
To change text on the client side of things, go to the relevant `.json` file, find the key that is being used in the React component, and change the value to the new text you want. You should search the codebase for that key to make sure it isn't being used elsewhere. Or, if it is, that the changes make sense in all places.
## Adding Text
If the text you want to add to the client exists in the relevant `.json` file, use the existing key. Otherwise, create a new key.
The English file is the "source of truth" for all of the `.json` files sharing the same name. If you need to add a new key, add it there. Then, add the key to **all** of the `translations.json` files.
> [!NOTE]
> Use English text for all languages if the file is translated through Crowdin. The tests will fail if you don't.
It would be nice to keep the keys in the same order across all the files as well. Also, try to put all punctuation, spacing, quotes, etc in the JSON files and not in the components or server files.
> [!NOTE]
> The underscore (`_`) is a reserved character for keys in the client side files. See [the documentation](https://www.i18next.com/translation-function/plurals) for how they are used.
## Helpful Documentation
- [react-i18next docs](https://react.i18next.com/latest/usetranslation-hook)
- [i18next docs](https://www.i18next.com/translation-function/essentials)

View File

@ -0,0 +1,270 @@
# How to work on localized client webapp
The react based client web app that powers our learning platform is built using Gatsby. It is translated into various world languages using [react-i18next](https://react.i18next.com/) and [i18next](https://www.i18next.com/).
You can learn more about setting up the client application locally for development by following [our local setup guide here](/how-to-setup-freecodecamp-locally). By default the application is available only in English.
Once you have setup the project locally you should be able to follow this documentation to run the client in the language of your choice from the list of available languages.
This could be helpful when you are working on a feature that specifically targets something that involves localization, and requires you to validate for instance a button's label in a different language.
> [!TIP]
> You do not need to follow this document for translating freeCodeCamp's curriculum or contributing documentation. Read [this guide here](./how-to-translate-files.md) instead.
Let's understand how the i18n frameworks and tooling work.
## File Structure
Most of files for translating the platform are located in the [`client/i18n`](https://github.com/freeCodeCamp/freeCodeCamp/tree/main/client/i18n) folder. Each language has a directory within that containing JSON files with the translations.
```console
config/i18n
└── all-langs.js
...
client/i18n
├── configForTests.js
├── config.js
├── locales
│   ├── chinese
│   │   ├── intro.json
│   │   ├── links.json
│   │   ├── meta-tags.json
│   │   ├── motivation.json
│   │   ├── translations.json
│   │   └── trending.json
... ...
│   ├── dothraki
│   │   ├── intro.json
│   │   ├── links.json
│   │   ├── meta-tags.json
│   │   ├── motivation.json
│   │   ├── translations.json
│   │   └── trending.json
... ...
│   ├── english
│   │   ├── intro.json
│   │   ├── links.json
│   │   ├── meta-tags.json
│   │   ├── motivation.json
│   │   ├── translations.json
│   │   └── trending.json
│   └── espanol
│   ├── intro.json
│   ├── links.json
│   ├── meta-tags.json
│   ├── motivation.json
│   ├── translations.json
│   └── trending.json
├── locales.test.js
├── schema-validation.js
└── validate-keys.js
```
Some of these files are translated on our translation platform (Crowdin), some are not.
**Files translated on our translation platform:**
- The `translations.json` file contains the majority of the text that appears on the user interface elements. The keys are used in the codebase to get the correct text for whatever language is set. This file needs to have the exact same keys in all languages.
- The `intro.json` file contains the key-value pairs for the introduction text on the certification pages.
If you want to add/update translations for the keys please [read this guide here](/how-to-translate-files.md).
**Files NOT translated on our translations platform:**
- The `motivation.json` files are not required to have the same quotes, compliments, or array length. Just the same JSON structure.
- The `trending.json` file contains the titles and links for the trending news articles in the website's footer.
- The `meta-tags.json` file contains the information for our website's meta tag information.
Changes to these files are typically done by the staff team. If you see something out of the ordinary we recommend you reach us in the [translators chat room](https://chat.freecodecamp.org/channel/translators).
## Testing the client app in a world language
You can test the client app in any language available in the [list of languages here](https://github.com/freeCodeCamp/freeCodeCamp/blob/6b4a6a02568b809fc216ea8566ff5df446d1da4e/config/i18n/all-langs.js#L5).
```js
const availableLangs = {
client: ['english', 'espanol', 'chinese'],
...
};
```
If you are testing a new language, create a folder with the language name as the title next to the other languages and copy the JSON files from another language into your new folder.
Add the language to the `client` array as seen above in the [`config/i18n/all-langs.js`](https://github.com/freeCodeCamp/freeCodeCamp/blob/main/config/i18n/all-langs.js) file.
Next, follow the instructions in the comments in the same file to add/update the rest of the variables as needed.
Finally, set the `CLIENT_LOCALE` variable in your `.env` file to the locale you want to build and you're ready.
## How to Structure Components
If you are working on a feature or a bug for the client web app, say for example adding new UI items on the settings page, you should follow the guidelines below. They will help you prepare the components for localization into all the supported world languages.
### Functional Component
```js
import { useTranslation } from 'react-i18next';
// in the render method:
const { t } = useTranslation();
// call the "t" function with a key from the JSON file:
<p>{t('key')}</p>; // more details below
```
### Class Component
```js
import { withTranslation } from 'react-i18next';
// withTranslation adds the "t" function to props:
const { t } = this.props;
// call the "t" function with a key from the JSON file:
<h1>{t('key')}</h1> // more details below
// export without redux:
export default withTranslation()(Component);
// or with redux:
export default connect(...)(withTranslation()(Component));
```
## Translate Using the "t" Function
### Basic Translation
```js
// in the component:
<p>{t('p1')}</p>
// in the JSON file:
{
"p1": "My paragraph"
}
// output:
<p>My paragraph</p>
```
### With Dynamic Data
```js
// in the component:
const username = 'moT';
<p>{t('welcome', { username: username })}</p>
// in the JSON file:
{
"welcome": "Welcome {{username}}"
}
// output:
<p>Welcome moT</p>
```
The above example passes an object to the `t` function with a `username` variable. The variable will be used in the JSON value where `{{username}}` is.
## Translate with the `Trans` Component
The general rule is to use the "t" function when you can. But there's a `Trans` component for when that isn't enough, usually when you have elements embedded in the text. You can use the `Trans` component with any type of react component.
### Basic Elements Nested
```js
// in the component:
import { Trans } from 'react-i18next'
<p>
<Trans>fcc.greeting</Trans>
</p>
// in the JSON file:
{
"fcc": {
"greeting": "Welcome to <strong>freeCodeCamp</strong>"
}
}
// output:
<p>Welcome to <strong>freeCodeCamp</strong></p>
```
You can place the key inside the component tags like the above example if the text contains "simple" tags with no attributes. `br`, `strong`, `i`, and `p` are the default, but that list can be expanded in the i18n config.
### Complex Elements Nested
Other times, you will want to have certain text inside another element, an anchor tag is a good example:
```js
// in the component:
<p>
<Trans i18nKey='check-forum'>
<a href='https://forum.freecodecamp.org/'>placeholder</a>
</Trans>
</p>
// in the JSON file:
{
"check-forum": "Check out <0>our forum</0>."
}
// output:
<p>Check out <a href='https://forum.freecodecamp.org/'>our forum</a></p>
```
In the above example, the key is set in the attributes of the `Trans` component. The `<0>` and `</0>` in the JSON represent the first child of the component, in this case, the anchor element. If there were more children, they would just count up from there using the same syntax. You can find the children of a component in the react dev tools by inspecting it. `placeholder` is simply there because the linter complains about empty `<a>` elements.
### With a Variable
```js
// in the component:
const email = 'team@freecodecamp.org';
<p>
<Trans email={email} i18nKey='fcc.email'>
<a href={`mailto:${email}`}>
{{ email }}
</a>
</Trans>
</p>
// in the JSON file:
{
"fcc": {
"email": "Send us an email at: <0>{{email}}</0>"
}
}
// output:
<p>Send us an email at: <a href='mailto:team@freecodecamp.org'>team@freecodecamp.org</a><p>
```
In the above example, the key and a variable are set in the attributes of the `Trans` component. `{{ email }}` needs to be somewhere in the `Trans` component as well, it doesn't matter where.
## Changing Text
To change text on the client side of things, go to the relevant `.json` file, find the key that is being used in the React component, and change the value to the new text you want. You should search the codebase for that key to make sure it isn't being used elsewhere. Or, if it is, that the changes make sense in all places.
## Adding Text
If the text you want to add to the client exists in the relevant `.json` file, use the existing key. Otherwise, create a new key.
The English file is the "source of truth" for all of the `.json` files sharing the same name. If you need to add a new key, add it there. Then, add the key to **all** of the `translations.json` files.
> [!NOTE]
> Use English text for all languages if the file is translated through Crowdin. The tests will fail if you don't.
It would be nice to keep the keys in the same order across all the files as well. Also, try to put all punctuation, spacing, quotes, etc in the JSON files and not in the components or server files.
> [!NOTE]
> The underscore (`_`) is a reserved character for keys in the client side files. See [the documentation](https://www.i18next.com/translation-function/plurals) for how they are used.
## Helpful Documentation
- [react-i18next docs](https://react.i18next.com/latest/usetranslation-hook)
- [i18next docs](https://www.i18next.com/translation-function/essentials)

View File

@ -23,13 +23,9 @@ You can help expand and improve the curriculum. You can also update project user
## Translations
We are localizing freeCodeCamp.org to world languages starting with Chinese and Español. We will be expanding the translations to more languages.
We are localizing freeCodeCamp.org to major world languages. Some of the certifications are already live in [Chinese (中文)](https://chinese.freecodecamp.org/learn) and [Spanish (Español)](https://www.freecodecamp.org/espanol/learn/). We encourage you to read the [announcement here](https://www.freecodecamp.org/news/world-language-translation-effort) and share it your friends to get them excited about this.
To help us with this massive effort, we have integrated our open-source code-base & curriculum with [Crowdin](https://crowdin.com/). You can read all about this in our [announcement here](https://www.freecodecamp.org/news/world-language-translation-effort). We encourage you to read the announcement and share it your friends to get them excited about this.
It's our dream to provide you with the resources to learn, no matter the world language you speak.
**If you're interested in translating, here are the guides to translate our [curriculum](how-to-translate-files.md), the [learning platform](how-to-translate-the-website.md) and our [Contributing guidelines](https://translate.freecodecamp.org/contributing-docs).**
**If you're interested in translating, here's [how to translate freCodeCamp's resources](how-to-translate-files.md).**
## Learning Platform