fix(tools): update translation parser

Since we're adding more validation we can simplify the parser and
make sure it does catch all the comments.  Rather than worry about a
load of edge cases that do not appear in our challenges.
This commit is contained in:
Oliver Eyton-Williams
2020-09-28 15:13:18 +02:00
committed by Mrugesh Mohapatra
parent 793fa8fb52
commit 92a60f8bce
3 changed files with 63 additions and 39 deletions

View File

@ -201,12 +201,12 @@ async function parseTranslation(engPath, transPath, dict, lang) {
const engChal = await parseMarkdown(engPath);
const translatedChal = await parseMarkdown(transPath);
const engWithTranslatedComments = translateCommentsInChallenge(
engChal,
lang,
dict
);
// challengeType 11 is for video challenges, which have no seeds, so we skip
// them.
const engWithTranslatedComments =
engChal.challengeType !== 11
? translateCommentsInChallenge(engChal, lang, dict)
: engChal;
return mergeChallenges(engWithTranslatedComments, translatedChal);
}

View File

@ -6,11 +6,10 @@ exports.translateComments = (text, lang, dict, codeLang) => {
const config = { knownComments, dict, lang };
switch (codeLang) {
case 'js':
return transMultiline(transInline(text, config), config);
case 'jsx':
return transJSX(text, config);
return transMultiline(transInline(text, config), config);
case 'html':
return transHTML(transCSS(text, config), config);
return transScript(transHTML(transCSS(text, config), config), config);
default:
return text;
}
@ -18,7 +17,9 @@ exports.translateComments = (text, lang, dict, codeLang) => {
exports.translateCommentsInChallenge = (challenge, lang, dict) => {
const challClone = clone(challenge);
if (!challClone.files) {
console.warn(`Challenge ${challClone.title} has no comments to translate`);
} else {
Object.keys(challClone.files).forEach(key => {
if (challClone.files[key].contents) {
challClone.files[key].contents = this.translateComments(
@ -29,7 +30,7 @@ exports.translateCommentsInChallenge = (challenge, lang, dict) => {
);
}
});
}
return challClone;
};
@ -93,12 +94,7 @@ exports.mergeChallenges = (engChal, transChal) => {
// bare urls could be interpreted as comments, so we have to lookbehind for
// http:// or https://
function transInline(text, config) {
return translateGeneric(
text,
config,
'(^[^\'"`]*?(?<!https?:)//\\s*)',
'(\\s*$)'
);
return translateGeneric(text, config, '((?<!https?:)//\\s*)', '(\\s*$)');
}
function transMultiline(text, config) {
@ -116,8 +112,17 @@ function transCSS(text, config) {
return text;
}
function transJSX(text, config) {
return translateGeneric(text, config, '({[^}]*/\\*\\s*)', '(\\s*\\*/[^{]*})');
function transScript(text, config) {
const regex = /<script>.*?<\/script>/gms;
const matches = text.matchAll(regex);
for (const [match] of matches) {
text = text.replace(
match,
transMultiline(transInline(match, config), config)
);
}
return text;
}
function transHTML(text, config) {

View File

@ -205,15 +205,6 @@ describe('translation parser', () => {
);
});
// If a comment follows '"` it could be inside a string, so we should
// not try and translate it - erring on the side of caution.
it('should ignore comments if they follow an open quote', () => {
const seed = `var str = '// Add your code below this line'
var str2 = '// Add your code above this line`;
expect(translateComments(seed, 'chinese', SIMPLE_TRANSLATION, 'js')).toBe(
seed
);
});
it('replaces multiple English comments with their translations', () => {
const seed = `inline comment // Add your code below this line
// Add your code below this line `;
@ -330,6 +321,32 @@ describe('translation parser', () => {
).toBe(transSeed);
});
it('replaces English script comments with their translations', () => {
const seed = `<script>
// Add your code below this line
</script>`;
const transSeed = `<script>
// (Chinese) Add your code below this line (Chinese)
</script>`;
expect(
translateComments(seed, 'chinese', SIMPLE_TRANSLATION, 'html')
).toBe(transSeed);
});
it('replaces multiple script comments with their translations', () => {
const seed = `<script>
/* Add your code below this line */
// Add your code below this line
</script>`;
const transSeed = `<script>
/* (Chinese) Add your code below this line (Chinese) */
// (Chinese) Add your code below this line (Chinese)
</script>`;
expect(
translateComments(seed, 'chinese', SIMPLE_TRANSLATION, 'html')
).toBe(transSeed);
});
it('ignores html comments inside JavaScript', () => {
const seed = `<div> <!-- Add your code below this line
Add your code above this line --> <span>change code below this line</span> `;
@ -391,6 +408,7 @@ describe('translation parser', () => {
/* this is not a comment */
</style>`;
const seedHTML = `<div> <!-- this is not a comment --> `;
const seedScript = `<script> // this is not a comment </script>`;
translateComments(seedJSX, 'chinese', SIMPLE_TRANSLATION, 'jsx');
expect(logSpy).toBeCalledTimes(1);
@ -402,7 +420,8 @@ describe('translation parser', () => {
expect(logSpy).toBeCalledTimes(4);
translateComments(seedHTML, 'chinese', SIMPLE_TRANSLATION, 'html');
expect(logSpy).toBeCalledTimes(5);
logSpy.mockRestore();
translateComments(seedScript, 'chinese', SIMPLE_TRANSLATION, 'html');
expect(logSpy).toBeCalledTimes(6);
});
});
});