mirror of
https://github.com/freeCodeCamp/freeCodeCamp.git
synced 2026-05-28 18:26:54 +00:00
fix(docs): update how to add/enable a new language (#48774)
* fix(docs): update how to add/enable a new language * fix: touch up * fix: more touch up * fix: apply suggestions and touch up
This commit is contained in:
@@ -52,8 +52,8 @@ There are a few steps to take in order to allow the codebase to build in your de
|
||||
|
||||
First, visit the `config/i18n.ts` file to add the language to the list of available languages and configure the values. There are several objects here.
|
||||
|
||||
- `availableLangs`: For both the `client` and `curriculum` arrays, add the text name of the language. This is the value that will be used in the `.env` file later.
|
||||
- `auditedCerts`: Add the text name of the language as the _key_, and add an array of `SuperBlocks.{cert}` variables as the _value_. This tells the client which certifications are fully translated.
|
||||
- `Languages`: Add the new language to `Languages` enum, similar to the others. The string value here will be used in the `.env` file to set a build language later.
|
||||
- `availableLangs`: Add the new property from the `Languages` enum to both the `client` and `curriculum` arrays.
|
||||
- `i18nextCodes`: These are the ISO language codes for each language. You will need to add the appropriate ISO code for the language you are enabling. These do need to be unique for each language.
|
||||
- `LangNames`: These are the display names for the language selector in the navigation menu.
|
||||
- `LangCodes`: These are the language codes used for formatting dates and numbers. These should be Unicode CLDR codes instead of ISO codes.
|
||||
@@ -63,78 +63,53 @@ First, visit the `config/i18n.ts` file to add the language to the list of availa
|
||||
As an example, if you wanted to enable Dothraki as a language, your `i18n.ts` objects should look like this:
|
||||
|
||||
```js
|
||||
export const availableLangs = {
|
||||
client: ['english', 'espanol', 'chinese', 'chinese-traditional', 'dothraki'],
|
||||
curriculum: [
|
||||
'english',
|
||||
'espanol',
|
||||
'chinese',
|
||||
'chinese-traditional',
|
||||
'dothraki'
|
||||
]
|
||||
};
|
||||
export enum Languages {
|
||||
English = 'english',
|
||||
Espanol = 'espanol',
|
||||
Chinese = 'chinese',
|
||||
ChineseTrandational = 'chinese-traditional',
|
||||
Dothraki = 'dothraki'
|
||||
}
|
||||
|
||||
export const auditedCerts = {
|
||||
espanol: [
|
||||
SuperBlocks.RespWebDesign,
|
||||
SuperBlocks.JsAlgoDataStruct,
|
||||
SuperBlocks.FrontEndDevLibs,
|
||||
SuperBlocks.DataVis,
|
||||
SuperBlocks.BackEndDevApis
|
||||
export const availableLangs = {
|
||||
client: [
|
||||
Languages.English,
|
||||
Languages.Espanol,
|
||||
Languages.Chinese,
|
||||
Languages.ChineseTrandational,
|
||||
Languages.Dothraki
|
||||
],
|
||||
chinese: [
|
||||
SuperBlocks.RespWebDesign,
|
||||
SuperBlocks.JsAlgoDataStruct,
|
||||
SuperBlocks.FrontEndDevLibs,
|
||||
SuperBlocks.DataVis,
|
||||
SuperBlocks.BackEndDevApis,
|
||||
SuperBlocks.QualityAssurance,
|
||||
SuperBlocks.SciCompPy,
|
||||
SuperBlocks.DataAnalysisPy,
|
||||
SuperBlocks.InfoSec,
|
||||
SuperBlocks.MachineLearningPy
|
||||
],
|
||||
'chinese-traditional': [
|
||||
SuperBlocks.RespWebDesign,
|
||||
SuperBlocks.JsAlgoDataStruct,
|
||||
SuperBlocks.FrontEndDevLibs,
|
||||
SuperBlocks.DataVis,
|
||||
SuperBlocks.BackEndDevApis,
|
||||
SuperBlocks.QualityAssurance,
|
||||
SuperBlocks.SciCompPy,
|
||||
SuperBlocks.DataAnalysisPy,
|
||||
SuperBlocks.InfoSec,
|
||||
SuperBlocks.MachineLearningPy
|
||||
],
|
||||
dothraki: [
|
||||
SuperBlocks.RespWebDesign,
|
||||
SuperBlocks.JsAlgoDataStruct,
|
||||
SuperBlocks.FrontEndDevLibs
|
||||
curriculum: [
|
||||
Languages.English,
|
||||
Languages.Espanol,
|
||||
Languages.Chinese,
|
||||
Languages.ChineseTrandational,
|
||||
Languages.Dothraki
|
||||
]
|
||||
};
|
||||
|
||||
export const i18nextCodes = {
|
||||
english: 'en',
|
||||
espanol: 'es',
|
||||
chinese: 'zh',
|
||||
'chinese-traditional': 'zh-Hant',
|
||||
dothraki: 'mis'
|
||||
[Languages.English]: 'en',
|
||||
[Languages.Espanol]: 'es',
|
||||
[Languages.Chinese]: 'zh',
|
||||
[Languages.ChineseTrandational]: 'zh-Hant',
|
||||
[Languages.Dothraki]: 'mis'
|
||||
};
|
||||
|
||||
export enum LangNames = {
|
||||
english: 'English',
|
||||
espanol: 'Español',
|
||||
chinese: '中文(简体字)',
|
||||
'chinese-traditional': '中文(繁體字)',
|
||||
dothraki: 'Dothraki'
|
||||
[Languages.English]: 'English',
|
||||
[Languages.Espanol]: 'Español',
|
||||
[Languages.Chinese]: '中文(简体字)',
|
||||
[Languages.ChineseTrandational]: '中文(繁體字)',
|
||||
[Languages.Dothraki]: 'Dothraki'
|
||||
};
|
||||
|
||||
export enum LangCodes = {
|
||||
english: 'en-US',
|
||||
espanol: 'es-419',
|
||||
chinese: 'zh',
|
||||
'chinese-traditional': 'zh-Hant',
|
||||
dothraki: 'mis'
|
||||
[Languages.English]: 'en-US',
|
||||
[Languages.Espanol]: 'es-419',
|
||||
[Languages.Chinese]: 'zh',
|
||||
[Languages.ChineseTrandational]: 'zh-Hant',
|
||||
[Languages.Dothraki]: 'mis'
|
||||
};
|
||||
|
||||
export const hiddenLangs = ['dothraki'];
|
||||
@@ -145,6 +120,72 @@ export const rtlLangs = [''];
|
||||
> [!NOTE]
|
||||
> When a language has been set up in the deployment pipeline AND has a public `/news` instance live, it can be removed from the `hiddenLangs` array and be made available to the public.
|
||||
|
||||
### Configure the Language Superblock Order
|
||||
|
||||
In the [config/superblock-order.ts](https://github.com/freeCodeCamp/freeCodeCamp/blob/main/config/superblock-order.ts) file, you need to set the order and state of all the superblocks for the new language in the `superBlockOrder` object. Copy one of the language keys and all its values, paste it to the bottom of the object (or wherever), and change the key to your new language from the `Languages` enum.
|
||||
|
||||
```js
|
||||
export const superBlockOrder: SuperBlockOrder = {
|
||||
...
|
||||
[Languages.Dothraki]: {
|
||||
[CurriculumMaps.Landing]: [
|
||||
SuperBlocks.RespWebDesignNew,
|
||||
SuperBlocks.JsAlgoDataStruct,
|
||||
SuperBlocks.FrontEndDevLibs,
|
||||
SuperBlocks.DataVis,
|
||||
SuperBlocks.RelationalDb,
|
||||
SuperBlocks.BackEndDevApis,
|
||||
SuperBlocks.QualityAssurance,
|
||||
SuperBlocks.SciCompPy,
|
||||
SuperBlocks.DataAnalysisPy,
|
||||
SuperBlocks.InfoSec,
|
||||
SuperBlocks.MachineLearningPy
|
||||
],
|
||||
[CurriculumMaps.Learn]: {
|
||||
[TranslationStates.Audited]: {
|
||||
[SuperBlockStates.Current]: [
|
||||
SuperBlocks.RespWebDesignNew,
|
||||
SuperBlocks.JsAlgoDataStruct,
|
||||
SuperBlocks.FrontEndDevLibs,
|
||||
SuperBlocks.DataVis,
|
||||
SuperBlocks.RelationalDb,
|
||||
SuperBlocks.BackEndDevApis,
|
||||
SuperBlocks.QualityAssurance,
|
||||
SuperBlocks.SciCompPy,
|
||||
SuperBlocks.DataAnalysisPy,
|
||||
SuperBlocks.InfoSec,
|
||||
SuperBlocks.MachineLearningPy,
|
||||
SuperBlocks.CodingInterviewPrep
|
||||
],
|
||||
[SuperBlockStates.New]: [],
|
||||
[SuperBlockStates.Upcoming]: [SuperBlocks.JsAlgoDataStructNew],
|
||||
[SuperBlockStates.Legacy]: [SuperBlocks.RespWebDesign]
|
||||
},
|
||||
[TranslationStates.NotAudited]: {
|
||||
[SuperBlockStates.Current]: [],
|
||||
[SuperBlockStates.New]: [],
|
||||
[SuperBlockStates.Upcoming]: [],
|
||||
[SuperBlockStates.Legacy]: []
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
The order of the superblocks in this object is how they appear on the "Landing" page and "Learn" maps. Follow the comments in that file so you know how you are allowed to order the superblocks, then move them to their proper places for the new language.
|
||||
|
||||
> [!ATTENTION]
|
||||
> Do not change the order of any of the keys in the object, just move the superblocks to the different arrays
|
||||
|
||||
The `CurriculumMaps.Landing` array should contain exactly one superblock for all our current certifications, and the `CurriculumMaps.Learn` object should have all existing superblocks in it. Translated superblocks go in `TranslationStates.Audited` and non-translated superblocks go in `TranslationStates.NotAudited`. Each of those two objects has four different states a superblock can be in.
|
||||
|
||||
- `SuperBlockStates.Current`: Means that the superblock is current, `(New) Responsive Web Design` for example.
|
||||
- `SuperBlockStates.New`: These only show up when `SHOW_NEW_CURRICULUM` is set to `true` in your `.env` file. It is for displaying new superblocks on a specific build. For example, when we released the new RWD, we only showed in on English to start.
|
||||
- `SuperBlockStates.Upcoming`: These only show up when `SHOW_UPCOMING_CHANGES` is set to `true` in your `.env` file. It is to show superblocks locally while they are in development. Or, if you just need to hide a superblock from the map for some other reason.
|
||||
- `SuperBlockStates.Legacy`: A superblock is moved here when a newer version of that superblock has been fully translated and replaced it.
|
||||
|
||||
### Configure Search
|
||||
|
||||
Next, open the `client/src/utils/algolia-locale-setup.ts` file. This data is used for the search bar that loads `/news` articles. While it is unlikely that you are going to test this functionality, missing the data for your language can lead to errors when attempting to build the codebase locally.
|
||||
|
||||
Add an object for your language to the `algoliaIndices` object. You should use the the same values as the `english` object for local testing, replacing the `english` key with your language's `availableLangs` value.
|
||||
@@ -179,30 +220,6 @@ const algoliaIndices = {
|
||||
};
|
||||
```
|
||||
|
||||
### Releasing a Superblock
|
||||
|
||||
After a superblock has been fully translated into a language, there are two steps to release it. First add the superblock enum to that language's `auditedCerts` array. So, if you want to release the new Responsive Web Design superblock for Dothraki, the array should look like this:
|
||||
|
||||
```ts
|
||||
export const auditedCerts = {
|
||||
// other languages
|
||||
dothraki: [
|
||||
SuperBlocks.RespWebDesignNew, // the newly translated superblock
|
||||
SuperBlocks.RespWebDesign,
|
||||
SuperBlocks.JsAlgoDataStruct,
|
||||
SuperBlocks.FrontEndDevLibs
|
||||
]
|
||||
};
|
||||
```
|
||||
|
||||
Finally, if the superblock is in a "new" state (that is, replacing a legacy superblock), the `languagesWithAuditedBetaReleases` array should be updated to include the new language like this:
|
||||
|
||||
```ts
|
||||
export const languagesWithAuditedBetaReleases: ['english', 'dothraki'];
|
||||
```
|
||||
|
||||
This will move the new superblock to the correct place in the curriculum map on `/learn`.
|
||||
|
||||
## Enabling Localized Videos
|
||||
|
||||
For the video challenges, you need to change a few things. First add the new locale to the GraphQL query in the `client/src/templates/Challenges/video/Show.tsx` file. For example, adding Dothraki to the query:
|
||||
|
||||
@@ -18,8 +18,8 @@ Let's understand how the i18n frameworks and tooling work.
|
||||
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.ts
|
||||
config
|
||||
└── i18n.ts
|
||||
...
|
||||
client/i18n
|
||||
├── configForTests.js
|
||||
@@ -30,37 +30,33 @@ Most of files for translating the platform are located in the [`client/i18n`](ht
|
||||
│ │ ├── links.json
|
||||
│ │ ├── meta-tags.json
|
||||
│ │ ├── motivation.json
|
||||
│ │ ├── translations.json
|
||||
│ │ └── trending.json
|
||||
│ │ └── translations.json
|
||||
... ...
|
||||
│ ├── dothraki
|
||||
│ │ ├── intro.json
|
||||
│ │ ├── links.json
|
||||
│ │ ├── meta-tags.json
|
||||
│ │ ├── motivation.json
|
||||
│ │ ├── translations.json
|
||||
│ │ └── trending.json
|
||||
│ │ └── translations.json
|
||||
... ...
|
||||
│ ├── english
|
||||
│ │ ├── intro.json
|
||||
│ │ ├── links.json
|
||||
│ │ ├── meta-tags.json
|
||||
│ │ ├── motivation.json
|
||||
│ │ ├── translations.json
|
||||
│ │ └── trending.json
|
||||
│ │ └── translations.json
|
||||
│ └── espanol
|
||||
│ ├── intro.json
|
||||
│ ├── links.json
|
||||
│ ├── meta-tags.json
|
||||
│ ├── motivation.json
|
||||
│ ├── translations.json
|
||||
│ └── trending.json
|
||||
│ └── translations.json
|
||||
├── locales.test.js
|
||||
├── schema-validation.js
|
||||
└── validate-keys.ts
|
||||
```
|
||||
|
||||
Some of these files are translated on our translation platform (Crowdin), some are not.
|
||||
Some of these files are translated on our translation platform (Crowdin), some are translated or created via PR's on GitHub.
|
||||
|
||||
**Files translated on our translation platform:**
|
||||
|
||||
@@ -74,28 +70,27 @@ Some of these files are translated on our translation platform (Crowdin), some a
|
||||
|
||||
- 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 [contributors chat room](https://discord.gg/PRyKn3Vbay).
|
||||
|
||||
## 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/main/config/i18n/all-langs.ts).
|
||||
You can test the client app in any language available in the [list of `availableLangs` here](https://github.com/freeCodeCamp/freeCodeCamp/blob/main/config/i18n.ts).
|
||||
|
||||
```js
|
||||
export const availableLangs = {
|
||||
export const availableLangs = {
|
||||
client: [
|
||||
'english',
|
||||
'espanol',
|
||||
'chinese',
|
||||
'chinese-traditional',
|
||||
'italian',
|
||||
'portuguese',
|
||||
'ukrainian',
|
||||
'japanese',
|
||||
'german'
|
||||
Languages.English,
|
||||
Languages.Espanol,
|
||||
Languages.Chinese,
|
||||
Languages.ChineseTrandational,
|
||||
Languages.Italian,
|
||||
Languages.Portuguese,
|
||||
Languages.Ukrainian,
|
||||
Languages.Japanese,
|
||||
Languages.German,
|
||||
Languages.Arabic
|
||||
],
|
||||
...
|
||||
};
|
||||
@@ -103,11 +98,11 @@ You can test the client app in any language available in the [list of languages
|
||||
|
||||
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.ts`](https://github.com/freeCodeCamp/freeCodeCamp/blob/main/config/i18n/all-langs.ts) file.
|
||||
Add the new language to the `Languages` enum and the `client` array at the top of the [`config/i18n.ts`](https://github.com/freeCodeCamp/freeCodeCamp/blob/main/config/i18n.ts) 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.
|
||||
Finally, set the `CLIENT_LOCALE` variable in your `.env` file to the string of the locale you want to build from the `Languages` enum in the above file.
|
||||
|
||||
## How to Structure Components
|
||||
|
||||
|
||||
Reference in New Issue
Block a user