mirror of
https://github.com/freeCodeCamp/freeCodeCamp.git
synced 2025-12-19 10:07:46 -05:00
feat(curriculum): add i18n-curriculum submodule (#55341)
Co-authored-by: Oliver Eyton-Williams <ojeytonwilliams@gmail.com>
This commit is contained in:
4
.gitmodules
vendored
Normal file
4
.gitmodules
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
[submodule "curriculum/i18n-curriculum"]
|
||||
path = curriculum/i18n-curriculum
|
||||
url = https://github.com/freeCodeCamp/i18n-curriculum.git
|
||||
ignore = dirty
|
||||
@@ -6,8 +6,9 @@ const envData = require('../config/env.json');
|
||||
const {
|
||||
getChallengesForLang,
|
||||
generateChallengeCreator,
|
||||
CHALLENGES_DIR,
|
||||
ENGLISH_CHALLENGES_DIR,
|
||||
META_DIR,
|
||||
CHALLENGES_DIR,
|
||||
getChallengesDirForLang
|
||||
} = require('../../curriculum/get-challenges');
|
||||
|
||||
@@ -24,7 +25,11 @@ exports.replaceChallengeNode = () => {
|
||||
const metaPath = path.resolve(META_DIR, `${blockName}/meta.json`);
|
||||
delete require.cache[require.resolve(metaPath)];
|
||||
const meta = require(metaPath);
|
||||
const englishPath = path.resolve(CHALLENGES_DIR, 'english', filePath);
|
||||
const englishPath = path.resolve(
|
||||
ENGLISH_CHALLENGES_DIR,
|
||||
'english',
|
||||
filePath
|
||||
);
|
||||
const i18nPath = path.resolve(CHALLENGES_DIR, curriculumLocale, filePath);
|
||||
// TODO: reimplement hot-reloading of certifications
|
||||
const createChallenge = generateChallengeCreator(
|
||||
|
||||
@@ -21,17 +21,34 @@ const { metaSchemaValidator } = require('./schema/meta-schema');
|
||||
|
||||
const access = util.promisify(fs.access);
|
||||
|
||||
const CHALLENGES_DIR = path.resolve(__dirname, 'challenges');
|
||||
const META_DIR = path.resolve(CHALLENGES_DIR, '_meta');
|
||||
exports.CHALLENGES_DIR = CHALLENGES_DIR;
|
||||
exports.META_DIR = META_DIR;
|
||||
const ENGLISH_CHALLENGES_DIR = path.resolve(__dirname, 'challenges');
|
||||
const ENGLISH_DICTIONARIES_DIR = path.resolve(__dirname, 'dictionaries');
|
||||
const META_DIR = path.resolve(ENGLISH_CHALLENGES_DIR, '_meta');
|
||||
|
||||
const COMMENT_TRANSLATIONS = createCommentMap(
|
||||
path.resolve(__dirname, 'dictionaries')
|
||||
const CURRICULUM_DIR = path.resolve(
|
||||
__dirname,
|
||||
process.env.BUILD_WITH_SUBMODULE === 'true'
|
||||
? 'i18n-curriculum/curriculum'
|
||||
: '.'
|
||||
);
|
||||
|
||||
function createCommentMap(dictionariesDir) {
|
||||
// get all the languages for which there are dictionaries.
|
||||
const CHALLENGES_DIR = path.resolve(CURRICULUM_DIR, 'challenges');
|
||||
const DICTIONARIES_DIR = path.resolve(CURRICULUM_DIR, 'dictionaries');
|
||||
|
||||
exports.ENGLISH_CHALLENGES_DIR = ENGLISH_CHALLENGES_DIR;
|
||||
exports.META_DIR = META_DIR;
|
||||
exports.CHALLENGES_DIR = CHALLENGES_DIR;
|
||||
|
||||
const COMMENT_TRANSLATIONS = createCommentMap(
|
||||
DICTIONARIES_DIR,
|
||||
ENGLISH_DICTIONARIES_DIR
|
||||
);
|
||||
|
||||
function createCommentMap(dictionariesDir, englishDictionariesDir) {
|
||||
// get all the languages for which there are dictionaries. Note: this has to
|
||||
// include the english dictionaries since translateCommentsInChallenge treats
|
||||
// all languages equally and will simply remove comments if there is no entry
|
||||
// in the comment map.
|
||||
const languages = fs.readdirSync(dictionariesDir);
|
||||
|
||||
// get all their dictionaries
|
||||
@@ -45,11 +62,15 @@ function createCommentMap(dictionariesDir) {
|
||||
|
||||
// get the english dicts
|
||||
const COMMENTS_TO_TRANSLATE = require(
|
||||
path.resolve(dictionariesDir, 'english', 'comments.json')
|
||||
path.resolve(englishDictionariesDir, 'english', 'comments.json')
|
||||
);
|
||||
|
||||
const COMMENTS_TO_NOT_TRANSLATE = require(
|
||||
path.resolve(dictionariesDir, 'english', 'comments-to-not-translate')
|
||||
path.resolve(
|
||||
englishDictionariesDir,
|
||||
'english',
|
||||
'comments-to-not-translate.json'
|
||||
)
|
||||
);
|
||||
|
||||
// map from english comment text to translations
|
||||
@@ -98,7 +119,11 @@ function getTranslationEntry(dicts, { engId, text }) {
|
||||
}
|
||||
|
||||
function getChallengesDirForLang(lang) {
|
||||
if (lang === 'english') {
|
||||
return path.resolve(ENGLISH_CHALLENGES_DIR, `${lang}`);
|
||||
} else {
|
||||
return path.resolve(CHALLENGES_DIR, `${lang}`);
|
||||
}
|
||||
}
|
||||
|
||||
function getMetaForBlock(block) {
|
||||
@@ -221,7 +246,7 @@ async function buildChallenges({ path: filePath }, curriculum, lang) {
|
||||
const isCert = path.extname(filePath) === '.yml';
|
||||
const englishPath = path.resolve(
|
||||
__dirname,
|
||||
CHALLENGES_DIR,
|
||||
ENGLISH_CHALLENGES_DIR,
|
||||
'english',
|
||||
filePath
|
||||
);
|
||||
@@ -336,7 +361,8 @@ function challengeFilesToPolys(files) {
|
||||
|
||||
async function assertHasEnglishSource(filePath, lang, englishPath) {
|
||||
const missingEnglish =
|
||||
lang !== 'english' && !(await hasEnglishSource(CHALLENGES_DIR, filePath));
|
||||
lang !== 'english' &&
|
||||
!(await hasEnglishSource(ENGLISH_CHALLENGES_DIR, filePath));
|
||||
if (missingEnglish)
|
||||
throw Error(`Missing English challenge for
|
||||
${filePath}
|
||||
|
||||
@@ -56,12 +56,14 @@ describe('create non-English challenge', () => {
|
||||
);
|
||||
|
||||
it('returns an object', () => {
|
||||
expect(typeof createCommentMap(dictionaryDir)).toBe('object');
|
||||
expect(typeof createCommentMap(dictionaryDir, dictionaryDir)).toBe(
|
||||
'object'
|
||||
);
|
||||
});
|
||||
|
||||
it('fallback to the untranslated string', () => {
|
||||
expect.assertions(2);
|
||||
const commentMap = createCommentMap(incompleteDictDir);
|
||||
const commentMap = createCommentMap(incompleteDictDir, incompleteDictDir);
|
||||
expect(commentMap['To be translated one'].spanish).toEqual(
|
||||
'Spanish translation one'
|
||||
);
|
||||
@@ -78,7 +80,7 @@ describe('create non-English challenge', () => {
|
||||
'Not translated one',
|
||||
'Not translated two'
|
||||
];
|
||||
const map = createCommentMap(dictionaryDir);
|
||||
const map = createCommentMap(dictionaryDir, dictionaryDir);
|
||||
expect(Object.keys(map)).toEqual(expect.arrayContaining(expectedIds));
|
||||
|
||||
const mapValue = map['To be translated one'];
|
||||
@@ -98,7 +100,7 @@ describe('create non-English challenge', () => {
|
||||
'Not translated one',
|
||||
'Not translated two'
|
||||
];
|
||||
const map = createCommentMap(dictionaryDir);
|
||||
const map = createCommentMap(dictionaryDir, dictionaryDir);
|
||||
expect(Object.keys(map)).toEqual(expect.arrayContaining(expectedIds));
|
||||
|
||||
const translatedOne = map['To be translated one'];
|
||||
|
||||
1
curriculum/i18n-curriculum
Submodule
1
curriculum/i18n-curriculum
Submodule
Submodule curriculum/i18n-curriculum added at 531d189f02
@@ -51,6 +51,9 @@ FREECODECAMP_NODE_ENV=development
|
||||
CLIENT_LOCALE=english
|
||||
CURRICULUM_LOCALE=english
|
||||
|
||||
# Build using submodule - remove this once the workflow has been entirely moved to use the submodule
|
||||
BUILD_WITH_SUBMODULE=false
|
||||
|
||||
# Show or hide WIP in progress challenges
|
||||
SHOW_UPCOMING_CHANGES=false
|
||||
SHOW_NEW_CURRICULUM=true
|
||||
|
||||
Reference in New Issue
Block a user